Commit 22b48e18 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #1172 from kmod/jit_time

Try to reduce JIT time for the LLVM tier
parents 7fd2c60c 31333266
...@@ -332,7 +332,7 @@ endmacro() ...@@ -332,7 +332,7 @@ endmacro()
# tests testname directory arguments # tests testname directory arguments
add_pyston_test(defaults tests --order-by-mtime -t50) add_pyston_test(defaults tests --order-by-mtime -t50)
# XXX: reenable # XXX: reenable
# add_pyston_test(force_llvm tests -a=-n -a=-X -t50) add_pyston_test(force_llvm tests -a=-n -a=-X -t50)
if(${CMAKE_BUILD_TYPE} STREQUAL "Release") if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
add_pyston_test(max_compilation_tier tests -a=-O -a=-X -t50) add_pyston_test(max_compilation_tier tests -a=-O -a=-X -t50)
endif() endif()
......
def f(l):
if l[0] > l[1]: l[0], l[1] = l[1], l[0]
if l[0] > l[2]: l[0], l[2] = l[2], l[0]
if l[0] > l[3]: l[0], l[3] = l[3], l[0]
if l[0] > l[4]: l[0], l[4] = l[4], l[0]
if l[0] > l[5]: l[0], l[5] = l[5], l[0]
if l[0] > l[6]: l[0], l[6] = l[6], l[0]
if l[0] > l[7]: l[0], l[7] = l[7], l[0]
if l[0] > l[8]: l[0], l[8] = l[8], l[0]
if l[0] > l[9]: l[0], l[9] = l[9], l[0]
if l[0] > l[10]: l[0], l[10] = l[10], l[0]
if l[0] > l[11]: l[0], l[11] = l[11], l[0]
if l[0] > l[12]: l[0], l[12] = l[12], l[0]
if l[0] > l[13]: l[0], l[13] = l[13], l[0]
if l[0] > l[14]: l[0], l[14] = l[14], l[0]
if l[0] > l[15]: l[0], l[15] = l[15], l[0]
if l[0] > l[16]: l[0], l[16] = l[16], l[0]
if l[0] > l[17]: l[0], l[17] = l[17], l[0]
if l[0] > l[18]: l[0], l[18] = l[18], l[0]
if l[0] > l[19]: l[0], l[19] = l[19], l[0]
if l[1] > l[2]: l[1], l[2] = l[2], l[1]
if l[1] > l[3]: l[1], l[3] = l[3], l[1]
if l[1] > l[4]: l[1], l[4] = l[4], l[1]
if l[1] > l[5]: l[1], l[5] = l[5], l[1]
if l[1] > l[6]: l[1], l[6] = l[6], l[1]
if l[1] > l[7]: l[1], l[7] = l[7], l[1]
if l[1] > l[8]: l[1], l[8] = l[8], l[1]
if l[1] > l[9]: l[1], l[9] = l[9], l[1]
if l[1] > l[10]: l[1], l[10] = l[10], l[1]
if l[1] > l[11]: l[1], l[11] = l[11], l[1]
if l[1] > l[12]: l[1], l[12] = l[12], l[1]
if l[1] > l[13]: l[1], l[13] = l[13], l[1]
if l[1] > l[14]: l[1], l[14] = l[14], l[1]
if l[1] > l[15]: l[1], l[15] = l[15], l[1]
if l[1] > l[16]: l[1], l[16] = l[16], l[1]
if l[1] > l[17]: l[1], l[17] = l[17], l[1]
if l[1] > l[18]: l[1], l[18] = l[18], l[1]
if l[1] > l[19]: l[1], l[19] = l[19], l[1]
if l[2] > l[3]: l[2], l[3] = l[3], l[2]
if l[2] > l[4]: l[2], l[4] = l[4], l[2]
if l[2] > l[5]: l[2], l[5] = l[5], l[2]
if l[2] > l[6]: l[2], l[6] = l[6], l[2]
if l[2] > l[7]: l[2], l[7] = l[7], l[2]
if l[2] > l[8]: l[2], l[8] = l[8], l[2]
if l[2] > l[9]: l[2], l[9] = l[9], l[2]
if l[2] > l[10]: l[2], l[10] = l[10], l[2]
if l[2] > l[11]: l[2], l[11] = l[11], l[2]
if l[2] > l[12]: l[2], l[12] = l[12], l[2]
if l[2] > l[13]: l[2], l[13] = l[13], l[2]
if l[2] > l[14]: l[2], l[14] = l[14], l[2]
if l[2] > l[15]: l[2], l[15] = l[15], l[2]
if l[2] > l[16]: l[2], l[16] = l[16], l[2]
if l[2] > l[17]: l[2], l[17] = l[17], l[2]
if l[2] > l[18]: l[2], l[18] = l[18], l[2]
if l[2] > l[19]: l[2], l[19] = l[19], l[2]
if l[3] > l[4]: l[3], l[4] = l[4], l[3]
if l[3] > l[5]: l[3], l[5] = l[5], l[3]
if l[3] > l[6]: l[3], l[6] = l[6], l[3]
if l[3] > l[7]: l[3], l[7] = l[7], l[3]
if l[3] > l[8]: l[3], l[8] = l[8], l[3]
if l[3] > l[9]: l[3], l[9] = l[9], l[3]
if l[3] > l[10]: l[3], l[10] = l[10], l[3]
if l[3] > l[11]: l[3], l[11] = l[11], l[3]
if l[3] > l[12]: l[3], l[12] = l[12], l[3]
if l[3] > l[13]: l[3], l[13] = l[13], l[3]
if l[3] > l[14]: l[3], l[14] = l[14], l[3]
if l[3] > l[15]: l[3], l[15] = l[15], l[3]
if l[3] > l[16]: l[3], l[16] = l[16], l[3]
if l[3] > l[17]: l[3], l[17] = l[17], l[3]
if l[3] > l[18]: l[3], l[18] = l[18], l[3]
if l[3] > l[19]: l[3], l[19] = l[19], l[3]
if l[4] > l[5]: l[4], l[5] = l[5], l[4]
if l[4] > l[6]: l[4], l[6] = l[6], l[4]
if l[4] > l[7]: l[4], l[7] = l[7], l[4]
if l[4] > l[8]: l[4], l[8] = l[8], l[4]
if l[4] > l[9]: l[4], l[9] = l[9], l[4]
if l[4] > l[10]: l[4], l[10] = l[10], l[4]
if l[4] > l[11]: l[4], l[11] = l[11], l[4]
if l[4] > l[12]: l[4], l[12] = l[12], l[4]
if l[4] > l[13]: l[4], l[13] = l[13], l[4]
if l[4] > l[14]: l[4], l[14] = l[14], l[4]
if l[4] > l[15]: l[4], l[15] = l[15], l[4]
if l[4] > l[16]: l[4], l[16] = l[16], l[4]
if l[4] > l[17]: l[4], l[17] = l[17], l[4]
if l[4] > l[18]: l[4], l[18] = l[18], l[4]
if l[4] > l[19]: l[4], l[19] = l[19], l[4]
if l[5] > l[6]: l[5], l[6] = l[6], l[5]
if l[5] > l[7]: l[5], l[7] = l[7], l[5]
if l[5] > l[8]: l[5], l[8] = l[8], l[5]
if l[5] > l[9]: l[5], l[9] = l[9], l[5]
if l[5] > l[10]: l[5], l[10] = l[10], l[5]
if l[5] > l[11]: l[5], l[11] = l[11], l[5]
if l[5] > l[12]: l[5], l[12] = l[12], l[5]
if l[5] > l[13]: l[5], l[13] = l[13], l[5]
if l[5] > l[14]: l[5], l[14] = l[14], l[5]
if l[5] > l[15]: l[5], l[15] = l[15], l[5]
if l[5] > l[16]: l[5], l[16] = l[16], l[5]
if l[5] > l[17]: l[5], l[17] = l[17], l[5]
if l[5] > l[18]: l[5], l[18] = l[18], l[5]
if l[5] > l[19]: l[5], l[19] = l[19], l[5]
if l[6] > l[7]: l[6], l[7] = l[7], l[6]
if l[6] > l[8]: l[6], l[8] = l[8], l[6]
if l[6] > l[9]: l[6], l[9] = l[9], l[6]
if l[6] > l[10]: l[6], l[10] = l[10], l[6]
if l[6] > l[11]: l[6], l[11] = l[11], l[6]
if l[6] > l[12]: l[6], l[12] = l[12], l[6]
if l[6] > l[13]: l[6], l[13] = l[13], l[6]
if l[6] > l[14]: l[6], l[14] = l[14], l[6]
if l[6] > l[15]: l[6], l[15] = l[15], l[6]
if l[6] > l[16]: l[6], l[16] = l[16], l[6]
if l[6] > l[17]: l[6], l[17] = l[17], l[6]
if l[6] > l[18]: l[6], l[18] = l[18], l[6]
if l[6] > l[19]: l[6], l[19] = l[19], l[6]
if l[7] > l[8]: l[7], l[8] = l[8], l[7]
if l[7] > l[9]: l[7], l[9] = l[9], l[7]
if l[7] > l[10]: l[7], l[10] = l[10], l[7]
if l[7] > l[11]: l[7], l[11] = l[11], l[7]
if l[7] > l[12]: l[7], l[12] = l[12], l[7]
if l[7] > l[13]: l[7], l[13] = l[13], l[7]
if l[7] > l[14]: l[7], l[14] = l[14], l[7]
if l[7] > l[15]: l[7], l[15] = l[15], l[7]
if l[7] > l[16]: l[7], l[16] = l[16], l[7]
if l[7] > l[17]: l[7], l[17] = l[17], l[7]
if l[7] > l[18]: l[7], l[18] = l[18], l[7]
if l[7] > l[19]: l[7], l[19] = l[19], l[7]
if l[8] > l[9]: l[8], l[9] = l[9], l[8]
if l[8] > l[10]: l[8], l[10] = l[10], l[8]
if l[8] > l[11]: l[8], l[11] = l[11], l[8]
if l[8] > l[12]: l[8], l[12] = l[12], l[8]
if l[8] > l[13]: l[8], l[13] = l[13], l[8]
if l[8] > l[14]: l[8], l[14] = l[14], l[8]
if l[8] > l[15]: l[8], l[15] = l[15], l[8]
if l[8] > l[16]: l[8], l[16] = l[16], l[8]
if l[8] > l[17]: l[8], l[17] = l[17], l[8]
if l[8] > l[18]: l[8], l[18] = l[18], l[8]
if l[8] > l[19]: l[8], l[19] = l[19], l[8]
if l[9] > l[10]: l[9], l[10] = l[10], l[9]
if l[9] > l[11]: l[9], l[11] = l[11], l[9]
if l[9] > l[12]: l[9], l[12] = l[12], l[9]
if l[9] > l[13]: l[9], l[13] = l[13], l[9]
if l[9] > l[14]: l[9], l[14] = l[14], l[9]
if l[9] > l[15]: l[9], l[15] = l[15], l[9]
if l[9] > l[16]: l[9], l[16] = l[16], l[9]
if l[9] > l[17]: l[9], l[17] = l[17], l[9]
if l[9] > l[18]: l[9], l[18] = l[18], l[9]
if l[9] > l[19]: l[9], l[19] = l[19], l[9]
if l[10] > l[11]: l[10], l[11] = l[11], l[10]
if l[10] > l[12]: l[10], l[12] = l[12], l[10]
if l[10] > l[13]: l[10], l[13] = l[13], l[10]
if l[10] > l[14]: l[10], l[14] = l[14], l[10]
if l[10] > l[15]: l[10], l[15] = l[15], l[10]
if l[10] > l[16]: l[10], l[16] = l[16], l[10]
if l[10] > l[17]: l[10], l[17] = l[17], l[10]
if l[10] > l[18]: l[10], l[18] = l[18], l[10]
if l[10] > l[19]: l[10], l[19] = l[19], l[10]
if l[11] > l[12]: l[11], l[12] = l[12], l[11]
if l[11] > l[13]: l[11], l[13] = l[13], l[11]
if l[11] > l[14]: l[11], l[14] = l[14], l[11]
if l[11] > l[15]: l[11], l[15] = l[15], l[11]
if l[11] > l[16]: l[11], l[16] = l[16], l[11]
if l[11] > l[17]: l[11], l[17] = l[17], l[11]
if l[11] > l[18]: l[11], l[18] = l[18], l[11]
if l[11] > l[19]: l[11], l[19] = l[19], l[11]
if l[12] > l[13]: l[12], l[13] = l[13], l[12]
if l[12] > l[14]: l[12], l[14] = l[14], l[12]
if l[12] > l[15]: l[12], l[15] = l[15], l[12]
if l[12] > l[16]: l[12], l[16] = l[16], l[12]
if l[12] > l[17]: l[12], l[17] = l[17], l[12]
if l[12] > l[18]: l[12], l[18] = l[18], l[12]
if l[12] > l[19]: l[12], l[19] = l[19], l[12]
if l[13] > l[14]: l[13], l[14] = l[14], l[13]
if l[13] > l[15]: l[13], l[15] = l[15], l[13]
if l[13] > l[16]: l[13], l[16] = l[16], l[13]
if l[13] > l[17]: l[13], l[17] = l[17], l[13]
if l[13] > l[18]: l[13], l[18] = l[18], l[13]
if l[13] > l[19]: l[13], l[19] = l[19], l[13]
if l[14] > l[15]: l[14], l[15] = l[15], l[14]
if l[14] > l[16]: l[14], l[16] = l[16], l[14]
if l[14] > l[17]: l[14], l[17] = l[17], l[14]
if l[14] > l[18]: l[14], l[18] = l[18], l[14]
if l[14] > l[19]: l[14], l[19] = l[19], l[14]
if l[15] > l[16]: l[15], l[16] = l[16], l[15]
if l[15] > l[17]: l[15], l[17] = l[17], l[15]
if l[15] > l[18]: l[15], l[18] = l[18], l[15]
if l[15] > l[19]: l[15], l[19] = l[19], l[15]
if l[16] > l[17]: l[16], l[17] = l[17], l[16]
if l[16] > l[18]: l[16], l[18] = l[18], l[16]
if l[16] > l[19]: l[16], l[19] = l[19], l[16]
if l[17] > l[18]: l[17], l[18] = l[18], l[17]
if l[17] > l[19]: l[17], l[19] = l[19], l[17]
if l[18] > l[19]: l[18], l[19] = l[19], l[18]
return l
print f([3, 12, 16, 8, 17, 6, 13, 0, 4, 15, 1, 14, 11, 18, 10, 5, 9, 7, 2, 19])
print f([2, 6, 11, 4, 7, 18, 19, 10, 15, 13, 3, 0, 17, 5, 8, 1, 14, 9, 16, 12])
print f([6, 12, 10, 7, 19, 15, 14, 5, 16, 1, 4, 11, 13, 2, 18, 9, 0, 3, 17, 8])
print f([1, 17, 13, 8, 9, 19, 18, 6, 5, 10, 12, 14, 2, 15, 0, 4, 11, 16, 7, 3])
print f([4, 7, 8, 6, 16, 10, 0, 5, 1, 3, 19, 2, 15, 12, 17, 11, 13, 18, 14, 9])
print f([14, 16, 11, 12, 5, 0, 10, 3, 1, 8, 17, 13, 4, 19, 9, 15, 6, 2, 7, 18])
print f([0, 3, 14, 9, 19, 13, 1, 7, 4, 17, 8, 16, 10, 5, 12, 6, 15, 11, 2, 18])
print f([17, 19, 3, 13, 15, 6, 16, 4, 0, 18, 8, 1, 9, 11, 2, 12, 7, 10, 5, 14])
print f([19, 5, 15, 1, 8, 2, 3, 12, 6, 14, 17, 7, 13, 10, 4, 18, 11, 9, 16, 0])
print f([13, 10, 11, 17, 19, 12, 14, 7, 5, 9, 2, 4, 18, 8, 6, 3, 16, 15, 0, 1])
import itertools
import sys
N = 5
if len(sys.argv) > 1:
N = int(sys.argv[1])
print "def f(l):"
for i in xrange(N):
for j in xrange(i + 1, N):
print " if l[%d] > l[%d]: l[%d], l[%d] = l[%d], l[%d]" % (i, j, i, j, j, i)
print " return l"
import random
for i in xrange(10):
l = range(N)
random.shuffle(l)
print "print f(%s)" % (l,)
...@@ -52,28 +52,17 @@ private: ...@@ -52,28 +52,17 @@ private:
} }
}; };
llvm::DenseSet<AST_Name*> kills;
llvm::DenseMap<InternedString, AST_Name*> last_uses;
llvm::DenseMap<InternedString, Status> statuses; llvm::DenseMap<InternedString, Status> statuses;
LivenessAnalysis* analysis; LivenessAnalysis* analysis;
void _doLoad(InternedString name, AST_Name* node) { void _doLoad(InternedString name, AST_Name* node) {
Status& status = statuses[name]; Status& status = statuses[name];
status.addUsage(Status::USED); status.addUsage(Status::USED);
last_uses[name] = node;
} }
void _doStore(InternedString name) { void _doStore(InternedString name) {
Status& status = statuses[name]; Status& status = statuses[name];
status.addUsage(Status::DEFINED); status.addUsage(Status::DEFINED);
auto it = last_uses.find(name);
if (it != last_uses.end()) {
kills.insert(it->second);
last_uses.erase(it);
}
} }
Status::Usage getStatusFirst(InternedString name) const { Status::Usage getStatusFirst(InternedString name) const {
...@@ -90,22 +79,7 @@ public: ...@@ -90,22 +79,7 @@ public:
bool firstIsDef(InternedString name) const { return getStatusFirst(name) == Status::DEFINED; } bool firstIsDef(InternedString name) const { return getStatusFirst(name) == Status::DEFINED; }
bool isKilledAt(AST_Name* node, bool is_live_at_end) const { bool isKilledAt(AST_Name* node, bool is_live_at_end) { return node->is_kill; }
if (kills.count(node))
return true;
// If it's not live at the end, then the last use is a kill
// even though we weren't able to determine that in a single
// pass
if (!is_live_at_end) {
auto it = last_uses.find(node->id);
if (it != last_uses.end() && node == it->second)
return true;
}
return false;
}
bool visit_classdef(AST_ClassDef* node) { bool visit_classdef(AST_ClassDef* node) {
......
...@@ -1691,7 +1691,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1691,7 +1691,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
bool is_live = true; bool is_live = true;
if (node->is_kill) { if (node->is_kill) {
is_live = false; is_live = false;
assert(!source_info->getLiveness()->isLiveAtEnd(node->id, current_block));
} else if (node->lookup_type == ScopeInfo::VarScopeType::FAST) } else if (node->lookup_type == ScopeInfo::VarScopeType::FAST)
is_live = source_info->getLiveness()->isLiveAtEnd(node->id, current_block); is_live = source_info->getLiveness()->isLiveAtEnd(node->id, current_block);
......
...@@ -1008,6 +1008,8 @@ CompiledFunction* doCompile(FunctionMetadata* md, SourceInfo* source, ParamNames ...@@ -1008,6 +1008,8 @@ CompiledFunction* doCompile(FunctionMetadata* md, SourceInfo* source, ParamNames
assert((entry_descriptor != NULL) + (spec != NULL) == 1); assert((entry_descriptor != NULL) + (spec != NULL) == 1);
md->calculateNumVRegs();
if (VERBOSITY("irgen") >= 2) if (VERBOSITY("irgen") >= 2)
source->cfg->print(); source->cfg->print();
......
...@@ -1881,13 +1881,9 @@ private: ...@@ -1881,13 +1881,9 @@ private:
} }
template <typename GetLLVMValCB> template <typename GetLLVMValCB>
void _setVRegIfUserVisible(InternedString name, GetLLVMValCB get_llvm_val_cb, CompilerVariable* prev, void _setVRegIfUserVisible(int vreg, GetLLVMValCB get_llvm_val_cb, CompilerVariable* prev,
bool potentially_undefined) { bool potentially_undefined) {
auto cfg = irstate->getSourceInfo()->cfg; auto cfg = irstate->getSourceInfo()->cfg;
if (!cfg->hasVregsAssigned())
irstate->getMD()->calculateNumVRegs();
assert(cfg->sym_vreg_map.count(name));
int vreg = cfg->sym_vreg_map[name];
assert(vreg >= 0); assert(vreg >= 0);
if (vreg < cfg->sym_vreg_map_user_visible.size()) { if (vreg < cfg->sym_vreg_map_user_visible.size()) {
...@@ -1908,13 +1904,12 @@ private: ...@@ -1908,13 +1904,12 @@ private:
} }
// only updates symbol_table if we're *not* setting a global // only updates symbol_table if we're *not* setting a global
void _doSet(InternedString name, CompilerVariable* val, const UnwindInfo& unw_info) { void _doSet(int vreg, InternedString name, ScopeInfo::VarScopeType vst, CompilerVariable* val,
const UnwindInfo& unw_info) {
assert(name.s() != "None"); assert(name.s() != "None");
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
assert(val->getType()->isUsable()); assert(val->getType()->isUsable());
auto scope_info = irstate->getScopeInfo();
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
assert(vst != ScopeInfo::VarScopeType::DEREF); assert(vst != ScopeInfo::VarScopeType::DEREF);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
...@@ -1949,7 +1944,7 @@ private: ...@@ -1949,7 +1944,7 @@ private:
bool maybe_was_undefined = _popFake(defined_name, true); bool maybe_was_undefined = _popFake(defined_name, true);
if (vst == ScopeInfo::VarScopeType::CLOSURE) { if (vst == ScopeInfo::VarScopeType::CLOSURE) {
size_t offset = scope_info->getClosureOffset(name); size_t offset = irstate->getScopeInfo()->getClosureOffset(name);
// This is basically `closure->elts[offset] = val;` // This is basically `closure->elts[offset] = val;`
CompilerVariable* closure = symbol_table[internString(CREATED_CLOSURE_NAME)]; CompilerVariable* closure = symbol_table[internString(CREATED_CLOSURE_NAME)];
...@@ -1967,10 +1962,19 @@ private: ...@@ -1967,10 +1962,19 @@ private:
} }
auto&& get_llvm_val = [&]() { return val->makeConverted(emitter, UNKNOWN)->getValue(); }; auto&& get_llvm_val = [&]() { return val->makeConverted(emitter, UNKNOWN)->getValue(); };
_setVRegIfUserVisible(name, get_llvm_val, prev, maybe_was_undefined); _setVRegIfUserVisible(vreg, get_llvm_val, prev, maybe_was_undefined);
} }
} }
void _doSet(AST_Name* name, CompilerVariable* val, const UnwindInfo& unw_info) {
auto scope_info = irstate->getScopeInfo();
auto vst = name->lookup_type;
if (vst == ScopeInfo::VarScopeType::UNKNOWN)
vst = scope_info->getScopeTypeOfName(name->id);
assert(vst != ScopeInfo::VarScopeType::DEREF);
_doSet(name->vreg, name->id, vst, val, unw_info);
}
void _doSetattr(AST_Attribute* target, CompilerVariable* val, const UnwindInfo& unw_info) { void _doSetattr(AST_Attribute* target, CompilerVariable* val, const UnwindInfo& unw_info) {
CompilerVariable* t = evalExpr(target->value, unw_info); CompilerVariable* t = evalExpr(target->value, unw_info);
t->setattr(emitter, getEmptyOpInfo(unw_info), target->attr.getBox(), val); t->setattr(emitter, getEmptyOpInfo(unw_info), target->attr.getBox(), val);
...@@ -2028,7 +2032,7 @@ private: ...@@ -2028,7 +2032,7 @@ private:
_doSetattr(ast_cast<AST_Attribute>(target), val, unw_info); _doSetattr(ast_cast<AST_Attribute>(target), val, unw_info);
break; break;
case AST_TYPE::Name: case AST_TYPE::Name:
_doSet(ast_cast<AST_Name>(target)->id, val, unw_info); _doSet(ast_cast<AST_Name>(target), val, unw_info);
break; break;
case AST_TYPE::Subscript: case AST_TYPE::Subscript:
_doSetitem(ast_cast<AST_Subscript>(target), val, unw_info); _doSetitem(ast_cast<AST_Subscript>(target), val, unw_info);
...@@ -2164,7 +2168,7 @@ private: ...@@ -2164,7 +2168,7 @@ private:
InternedString defined_name = getIsDefinedName(target->id); InternedString defined_name = getIsDefinedName(target->id);
ConcreteCompilerVariable* is_defined_var = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true)); ConcreteCompilerVariable* is_defined_var = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true));
_setVRegIfUserVisible(target->id, []() { return getNullPtr(g.llvm_value_type_ptr); }, prev, _setVRegIfUserVisible(target->vreg, []() { return getNullPtr(g.llvm_value_type_ptr); }, prev,
(bool)is_defined_var); (bool)is_defined_var);
if (symbol_table.count(target->id) == 0) { if (symbol_table.count(target->id) == 0) {
...@@ -2599,7 +2603,14 @@ private: ...@@ -2599,7 +2603,14 @@ private:
void loadArgument(InternedString name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) { void loadArgument(InternedString name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
assert(name.s() != FRAME_INFO_PTR_NAME); assert(name.s() != FRAME_INFO_PTR_NAME);
CompilerVariable* var = unboxVar(t, v); CompilerVariable* var = unboxVar(t, v);
_doSet(name, var, unw_info); auto cfg = irstate->getSourceInfo()->cfg;
auto vst = irstate->getScopeInfo()->getScopeTypeOfName(name);
int vreg = -1;
if (vst == ScopeInfo::VarScopeType::FAST || vst == ScopeInfo::VarScopeType::CLOSURE) {
assert(cfg->sym_vreg_map.count(name));
vreg = cfg->sym_vreg_map[name];
}
_doSet(vreg, name, vst, var, unw_info);
} }
void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) { void loadArgument(AST_expr* name, ConcreteCompilerType* t, llvm::Value* v, const UnwindInfo& unw_info) {
......
...@@ -373,20 +373,25 @@ void addCXXFixup(llvm::Instruction* inst, const llvm::SmallVector<llvm::Tracking ...@@ -373,20 +373,25 @@ void addCXXFixup(llvm::Instruction* inst, const llvm::SmallVector<llvm::Tracking
call->replaceAllUsesWith(new_invoke); call->replaceAllUsesWith(new_invoke);
call->eraseFromParent(); call->eraseFromParent();
llvm::Value* exc_type, *exc_value, *exc_traceback;
std::tie(exc_type, exc_value, exc_traceback) = createLandingpad(fixup_block);
llvm::IRBuilder<true> builder(fixup_block); llvm::IRBuilder<true> builder(fixup_block);
llvm::SmallVector<llvm::Value*, 4> decref_args; static llvm::Function* _personality_func = g.stdlib_module->getFunction("__gxx_personality_v0");
decref_args.push_back(getConstantInt(to_decref.size(), g.i32)); assert(_personality_func);
decref_args.append(to_decref.begin(), to_decref.end()); llvm::Value* personality_func
builder.CreateCall(g.funcs.xdecrefAll, decref_args); = g.cur_module->getOrInsertFunction(_personality_func->getName(), _personality_func->getFunctionType());
assert(personality_func);
auto rethrow = builder.CreateCall3(g.funcs.rawReraise, exc_type, exc_value, exc_traceback); static llvm::Type* lp_type = llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 });
assert(lp_type);
llvm::LandingPadInst* landing_pad = builder.CreateLandingPad(lp_type, personality_func, 1);
landing_pad->addClause(getNullPtr(g.i8_ptr));
llvm::SmallVector<llvm::Value*, 4> call_args;
llvm::Value* cxaexc_pointer = builder.CreateExtractValue(landing_pad, { 0 });
call_args.push_back(cxaexc_pointer);
call_args.push_back(getConstantInt(to_decref.size(), g.i32));
call_args.append(to_decref.begin(), to_decref.end());
builder.CreateCall(g.funcs.xdecrefAndRethrow, call_args);
builder.CreateUnreachable(); builder.CreateUnreachable();
// new_invoke->getParent()->getParent()->dump();
} }
// TODO: this should be cleaned up and moved to src/core/ // TODO: this should be cleaned up and moved to src/core/
......
...@@ -324,7 +324,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -324,7 +324,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(reraiseCapiExcAsCxx); GET(reraiseCapiExcAsCxx);
GET(deopt); GET(deopt);
GET(checkRefs); GET(checkRefs);
GET(xdecrefAll); GET(xdecrefAndRethrow);
GET(div_float_float); GET(div_float_float);
GET(floordiv_float_float); GET(floordiv_float_float);
......
...@@ -55,7 +55,7 @@ struct GlobalFuncs { ...@@ -55,7 +55,7 @@ struct GlobalFuncs {
llvm::Value* raise0, *raise0_capi, *raise3, *raise3_capi, *rawReraise; llvm::Value* raise0, *raise0_capi, *raise3, *raise3_capi, *rawReraise;
llvm::Value* PyErr_Fetch, *PyErr_NormalizeException, *PyErr_Restore, *caughtCapiException, *reraiseCapiExcAsCxx; llvm::Value* PyErr_Fetch, *PyErr_NormalizeException, *PyErr_Restore, *caughtCapiException, *reraiseCapiExcAsCxx;
llvm::Value* deopt; llvm::Value* deopt;
llvm::Value* checkRefs, *xdecrefAll; llvm::Value* checkRefs, *xdecrefAndRethrow;
llvm::Value* div_float_float, *floordiv_float_float, *mod_float_float, *pow_float_float; llvm::Value* div_float_float, *floordiv_float_float, *mod_float_float, *pow_float_float;
......
This diff is collapsed.
...@@ -120,6 +120,7 @@ public: ...@@ -120,6 +120,7 @@ public:
class SourceInfo; class SourceInfo;
CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body); CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body);
void printCFG(CFG* cfg);
} }
#endif #endif
...@@ -70,9 +70,9 @@ public: ...@@ -70,9 +70,9 @@ public:
const char* c_str() const; const char* c_str() const;
bool operator==(InternedString rhs) const { bool operator==(InternedString rhs) const {
assert(this->_str || this->pool == invalidPool()); // assert(this->_str || this->pool == invalidPool());
assert(rhs._str || rhs.pool == invalidPool()); // assert(rhs._str || rhs.pool == invalidPool());
assert(this->pool == rhs.pool || this->pool == invalidPool() || rhs.pool == invalidPool()); // assert(this->pool == rhs.pool || this->pool == invalidPool() || rhs.pool == invalidPool());
return this->_str == rhs._str; return this->_str == rhs._str;
} }
......
...@@ -140,7 +140,7 @@ void force() { ...@@ -140,7 +140,7 @@ void force() {
FORCE(reraiseCapiExcAsCxx); FORCE(reraiseCapiExcAsCxx);
FORCE(deopt); FORCE(deopt);
FORCE(checkRefs); FORCE(checkRefs);
FORCE(xdecrefAll); FORCE(xdecrefAndRethrow);
FORCE(div_i64_i64); FORCE(div_i64_i64);
FORCE(mod_i64_i64); FORCE(mod_i64_i64);
......
...@@ -118,7 +118,10 @@ static inline Box* callattrInternal3(Box* obj, BoxedString* attr, LookupScope sc ...@@ -118,7 +118,10 @@ static inline Box* callattrInternal3(Box* obj, BoxedString* attr, LookupScope sc
return callattrInternal<S, rewritable>(obj, attr, scope, rewrite_args, argspec, arg1, arg2, arg3, NULL, NULL); return callattrInternal<S, rewritable>(obj, attr, scope, rewrite_args, argspec, arg1, arg2, arg3, NULL, NULL);
} }
extern "C" void xdecrefAll(int num, ...) { extern "C" void* __cxa_begin_catch(void*);
extern "C" void xdecrefAndRethrow(void* cxa_ptr, int num, ...) {
ExcInfo e = *(ExcInfo*)__cxa_begin_catch(cxa_ptr);
va_list va; va_list va;
va_start(va, num); va_start(va, num);
...@@ -128,6 +131,8 @@ extern "C" void xdecrefAll(int num, ...) { ...@@ -128,6 +131,8 @@ extern "C" void xdecrefAll(int num, ...) {
} }
va_end(va); va_end(va);
rawReraise(e.type, e.value, e.traceback);
} }
extern "C" Box* deopt(AST_expr* expr, Box* value) { extern "C" Box* deopt(AST_expr* expr, Box* value) {
......
...@@ -231,6 +231,6 @@ extern "C" void boxedLocalsDel(Box* boxedLocals, BoxedString* attr); ...@@ -231,6 +231,6 @@ extern "C" void boxedLocalsDel(Box* boxedLocals, BoxedString* attr);
extern "C" void checkRefs(Box* b); // asserts that b has >= 0 refs extern "C" void checkRefs(Box* b); // asserts that b has >= 0 refs
extern "C" Box* assertAlive(Box* b); // asserts that b has > 0 refs, and returns b extern "C" Box* assertAlive(Box* b); // asserts that b has > 0 refs, and returns b
extern "C" void xdecrefAll(int num, ...); extern "C" void xdecrefAndRethrow(void* cxa_ptr, int num_decref, ...);
} }
#endif #endif
...@@ -1683,6 +1683,12 @@ static void functionSetDefaults(Box* b, Box* v, void*) { ...@@ -1683,6 +1683,12 @@ static void functionSetDefaults(Box* b, Box* v, void*) {
// and leave this assert. // and leave this assert.
RELEASE_ASSERT(func->can_change_defaults, "trying to change the defaults on a non-defaults-changable function."); RELEASE_ASSERT(func->can_change_defaults, "trying to change the defaults on a non-defaults-changable function.");
// Changing defaults of builtins would be very scary. Python functions are safe since they
// store their arguments into their symbol table, but builtin functions are free to let them
// stay borrowed. If a builtin function has changable defaults, and it can call into arbitrary
// user code, then it could call something that changes its own defaults, and all of a sudden
// one of its arguments gets deallocated from under it.
if (v == None) if (v == None)
v = NULL; v = NULL;
else if (v && !PyTuple_Check(v)) { else if (v && !PyTuple_Check(v)) {
......
# expected: fail
# - we have an extra evaluation of __nonzero__ at the end
class A(object):
def __init__(self, n):
print "init", n
self.n = n
def __lt__(self, rhs):
print "lt", self.n, rhs.n
return self
def __nonzero__(self):
print "nonzero", self.n
return True
def __repr__(self):
return "<A (%d)>" % self.n
print A(1) < A(2) < A(3)
...@@ -70,3 +70,9 @@ print type(C.__new__), type(C.__dict__['__new__']) ...@@ -70,3 +70,9 @@ print type(C.__new__), type(C.__dict__['__new__'])
C.__new__.__defaults__ = (1,) C.__new__.__defaults__ = (1,)
print type(C()) print type(C())
def f(a=1, b=2, c=3):
print a, b, c, type(a), type(b), type(c)
f.func_defaults = (a + 3, b + 3, c + 3)
for i in xrange(1000):
f()
# fail-if: '-n' in EXTRA_JIT_ARGS or '-O' in EXTRA_JIT_ARGS
class C(object):
def next(self):
return 1
def __del__(self):
print "del"
class D(object):
def __iter__(self):
return C()
def f():
for i in D():
print i
break
for i in xrange(100):
print
f()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment