Commit 0c84c153 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #703 from kmod/tiering_merge

type speculation support
parents dae4f6b2 a077670c
...@@ -74,10 +74,7 @@ static BoxedClass* simpleCallSpeculation(AST_Call* node, CompilerType* rtn_type, ...@@ -74,10 +74,7 @@ static BoxedClass* simpleCallSpeculation(AST_Call* node, CompilerType* rtn_type,
if (node->func->type == AST_TYPE::Name && ast_cast<AST_Name>(node->func)->id.s() == "xrange") if (node->func->type == AST_TYPE::Name && ast_cast<AST_Name>(node->func)->id.s() == "xrange")
return xrange_cls; return xrange_cls;
// if (node->func->type == AST_TYPE::Attribute && ast_cast<AST_Attribute>(node->func)->attr == "dot") return predictClassFor(node);
// return float_cls;
return NULL;
} }
typedef llvm::DenseMap<InternedString, CompilerType*> TypeMap; typedef llvm::DenseMap<InternedString, CompilerType*> TypeMap;
...@@ -115,8 +112,7 @@ private: ...@@ -115,8 +112,7 @@ private:
assert(old_type); assert(old_type);
assert(speculation != TypeAnalysis::NONE); assert(speculation != TypeAnalysis::NONE);
if (VERBOSITY() >= 3) // TODO: reenable this
printf("Would maybe try to speculate but deopt is currently broken\n");
return old_type; return old_type;
if (speculated_cls != NULL && speculated_cls->is_constant) { if (speculated_cls != NULL && speculated_cls->is_constant) {
......
...@@ -1940,28 +1940,6 @@ bool spillFrameArgumentIfNecessary(StackMap::Record::Location& l, uint8_t*& inst ...@@ -1940,28 +1940,6 @@ bool spillFrameArgumentIfNecessary(StackMap::Record::Location& l, uint8_t*& inst
} }
} }
void* extractSlowpathFunc(uint8_t* pp_addr) {
#ifndef NDEBUG
// mov $imm, %r11:
ASSERT(pp_addr[0] == 0x49, "%x", pp_addr[0]);
assert(pp_addr[1] == 0xbb);
// 8 bytes of the addr
// callq *%r11:
assert(pp_addr[10] == 0x41);
assert(pp_addr[11] == 0xff);
assert(pp_addr[12] == 0xd3);
int i = INITIAL_CALL_SIZE;
while (*(pp_addr + i) == 0x66 || *(pp_addr + i) == 0x0f || *(pp_addr + i) == 0x2e)
i++;
assert(*(pp_addr + i) == 0x90 || *(pp_addr + i) == 0x1f);
#endif
void* call_addr = *(void**)&pp_addr[2];
return call_addr;
}
void setSlowpathFunc(uint8_t* pp_addr, void* func) { void setSlowpathFunc(uint8_t* pp_addr, void* func) {
#ifndef NDEBUG #ifndef NDEBUG
// mov $imm, %r11: // mov $imm, %r11:
......
...@@ -518,7 +518,6 @@ public: ...@@ -518,7 +518,6 @@ public:
friend class RewriterVar; friend class RewriterVar;
}; };
void* extractSlowpathFunc(uint8_t* pp_addr);
void setSlowpathFunc(uint8_t* pp_addr, void* func); void setSlowpathFunc(uint8_t* pp_addr, void* func);
struct GRCompare { struct GRCompare {
......
...@@ -711,6 +711,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -711,6 +711,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
std::map<InternedString, Box*> sorted_symbol_table; std::map<InternedString, Box*> sorted_symbol_table;
// TODO: maybe use a different placeholder?
static Box* const VAL_UNDEFINED = (Box*)-1;
for (auto& name : phis->definedness.getDefinedNamesAtEnd(current_block)) { for (auto& name : phis->definedness.getDefinedNamesAtEnd(current_block)) {
auto it = sym_table.find(name); auto it = sym_table.find(name);
if (!liveness->isLiveAtEnd(name, current_block)) if (!liveness->isLiveAtEnd(name, current_block))
...@@ -722,10 +725,11 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -722,10 +725,11 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sorted_symbol_table[getIsDefinedName(name, source_info->getInternedStrings())] = (Box*)is_defined; sorted_symbol_table[getIsDefinedName(name, source_info->getInternedStrings())] = (Box*)is_defined;
if (is_defined) if (is_defined)
assert(sym_table.getMapped(it->second) != NULL); assert(sym_table.getMapped(it->second) != NULL);
sorted_symbol_table[name] = is_defined ? sym_table.getMapped(it->second) : NULL; sorted_symbol_table[name] = is_defined ? sym_table.getMapped(it->second) : VAL_UNDEFINED;
} else { } else {
ASSERT(it != sym_table.end(), "%s", name.c_str()); ASSERT(it != sym_table.end(), "%s", name.c_str());
sorted_symbol_table[it->first] = sym_table.getMapped(it->second); Box* v = sorted_symbol_table[it->first] = sym_table.getMapped(it->second);
assert(gc::isValidGCObject(v));
} }
} }
...@@ -1363,7 +1367,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) { ...@@ -1363,7 +1367,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
CallattrFlags callattr_flags{.cls_only = callattr_clsonly, .null_on_nonexistent = false, .argspec = argspec }; CallattrFlags callattr_flags{.cls_only = callattr_clsonly, .null_on_nonexistent = false, .argspec = argspec };
if (jit) if (jit)
v.var = jit->emitCallattr(func, attr.getBox(), callattr_flags, args_vars, keyword_names); v.var = jit->emitCallattr(node, func, attr.getBox(), callattr_flags, args_vars, keyword_names);
v.o = callattr(func.o, attr.getBox(), callattr_flags, args.size() > 0 ? args[0] : 0, v.o = callattr(func.o, attr.getBox(), callattr_flags, args.size() > 0 ? args[0] : 0,
args.size() > 1 ? args[1] : 0, args.size() > 2 ? args[2] : 0, args.size() > 3 ? &args[3] : 0, args.size() > 1 ? args[1] : 0, args.size() > 2 ? args[2] : 0, args.size() > 3 ? &args[3] : 0,
...@@ -1373,7 +1377,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) { ...@@ -1373,7 +1377,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
Value v; Value v;
if (jit) if (jit)
v.var = jit->emitRuntimeCall(func, argspec, args_vars, keyword_names); v.var = jit->emitRuntimeCall(node, func, argspec, args_vars, keyword_names);
v.o = runtimeCall(func.o, argspec, args.size() > 0 ? args[0] : 0, args.size() > 1 ? args[1] : 0, v.o = runtimeCall(func.o, argspec, args.size() > 0 ? args[0] : 0, args.size() > 1 ? args[1] : 0,
args.size() > 2 ? args[2] : 0, args.size() > 3 ? &args[3] : 0, keyword_names); args.size() > 2 ? args[2] : 0, args.size() > 3 ? &args[3] : 0, keyword_names);
...@@ -1547,7 +1551,8 @@ Value ASTInterpreter::visit_tuple(AST_Tuple* node) { ...@@ -1547,7 +1551,8 @@ Value ASTInterpreter::visit_tuple(AST_Tuple* node) {
Value ASTInterpreter::visit_attribute(AST_Attribute* node) { Value ASTInterpreter::visit_attribute(AST_Attribute* node) {
Value v = visit_expr(node->value); Value v = visit_expr(node->value);
return Value(pyston::getattr(v.o, node->attr.getBox()), jit ? jit->emitGetAttr(v, node->attr.getBox()) : NULL); return Value(pyston::getattr(v.o, node->attr.getBox()),
jit ? jit->emitGetAttr(v, node->attr.getBox(), node) : NULL);
} }
} }
...@@ -1749,7 +1754,7 @@ Box* astInterpretFunctionEval(CLFunction* clfunc, Box* globals, Box* boxedLocals ...@@ -1749,7 +1754,7 @@ Box* astInterpretFunctionEval(CLFunction* clfunc, Box* globals, Box* boxedLocals
return v.o ? v.o : None; return v.o ? v.o : None;
} }
Box* astInterpretFrom(CLFunction* clfunc, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val, Box* astInterpretDeopt(CLFunction* clfunc, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state) { FrameStackState frame_state) {
assert(clfunc); assert(clfunc);
assert(enclosing_stmt); assert(enclosing_stmt);
......
...@@ -75,7 +75,7 @@ void setupInterpreter(); ...@@ -75,7 +75,7 @@ void setupInterpreter();
Box* astInterpretFunction(CLFunction* f, int nargs, Box* closure, Box* generator, Box* globals, Box* arg1, Box* arg2, Box* astInterpretFunction(CLFunction* f, int nargs, Box* closure, Box* generator, Box* globals, Box* arg1, Box* arg2,
Box* arg3, Box** args); Box* arg3, Box** args);
Box* astInterpretFunctionEval(CLFunction* cf, Box* globals, Box* boxedLocals); Box* astInterpretFunctionEval(CLFunction* cf, Box* globals, Box* boxedLocals);
Box* astInterpretFrom(CLFunction* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val, Box* astInterpretDeopt(CLFunction* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state); FrameStackState frame_state);
AST_stmt* getCurrentStatementForInterpretedFrame(void* frame_ptr); AST_stmt* getCurrentStatementForInterpretedFrame(void* frame_ptr);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
#include "codegen/memmgr.h" #include "codegen/memmgr.h"
#include "codegen/type_recording.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
...@@ -133,9 +134,11 @@ RewriterVar* JitFragmentWriter::emitBinop(RewriterVar* lhs, RewriterVar* rhs, in ...@@ -133,9 +134,11 @@ RewriterVar* JitFragmentWriter::emitBinop(RewriterVar* lhs, RewriterVar* rhs, in
return emitPPCall((void*)binop, { lhs, rhs, imm(op_type) }, 2, 240); return emitPPCall((void*)binop, { lhs, rhs, imm(op_type) }, 2, 240);
} }
RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr, CallattrFlags flags, RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, BoxedString* attr, CallattrFlags flags,
const llvm::ArrayRef<RewriterVar*> args, const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) { std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS #if ENABLE_BASELINEJIT_ICS
RewriterVar* attr_var = imm(attr); RewriterVar* attr_var = imm(attr);
RewriterVar* flags_var = imm(flags.asInt()); RewriterVar* flags_var = imm(flags.asInt());
...@@ -159,7 +162,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr ...@@ -159,7 +162,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
if (keyword_names) if (keyword_names)
call_args.push_back(imm(keyword_names)); call_args.push_back(imm(keyword_names));
return emitPPCall((void*)callattr, call_args, 2, 640); return emitPPCall((void*)callattr, call_args, 2, 640, type_recorder);
#else #else
// We could make this faster but for now: keep it simple, stupid... // We could make this faster but for now: keep it simple, stupid...
RewriterVar* attr_var = imm(attr); RewriterVar* attr_var = imm(attr);
...@@ -177,6 +180,8 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr ...@@ -177,6 +180,8 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
call_args.push_back(attr_var); call_args.push_back(attr_var);
call_args.push_back(flags_var); call_args.push_back(flags_var);
call_args.push_back(imm(type_recorder));
if (args_array) if (args_array)
call_args.push_back(args_array); call_args.push_back(args_array);
if (keyword_names_var) if (keyword_names_var)
...@@ -247,8 +252,8 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar ...@@ -247,8 +252,8 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
return call(false, (void*)exceptionMatchesHelper, v, cls); return call(false, (void*)exceptionMatchesHelper, v, cls);
} }
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s) { RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node) {
return emitPPCall((void*)getattr, { obj, imm(s) }, 2, 512); return emitPPCall((void*)getattr, { obj, imm(s) }, 2, 512, getTypeRecorderForNode(node));
} }
RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s) { RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s) {
...@@ -311,9 +316,11 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) { ...@@ -311,9 +316,11 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) {
return call(false, (void*)repr, v); return call(false, (void*)repr, v);
} }
RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec argspec, RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj, ArgPassSpec argspec,
const llvm::ArrayRef<RewriterVar*> args, const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) { std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS #if ENABLE_BASELINEJIT_ICS
RewriterVar* argspec_var = imm(argspec.asInt()); RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar::SmallVector call_args; RewriterVar::SmallVector call_args;
...@@ -333,7 +340,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar ...@@ -333,7 +340,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
if (keyword_names) if (keyword_names)
call_args.push_back(imm(keyword_names)); call_args.push_back(imm(keyword_names));
return emitPPCall((void*)runtimeCall, call_args, 2, 640); return emitPPCall((void*)runtimeCall, call_args, 2, 640, type_recorder);
#else #else
RewriterVar* argspec_var = imm(argspec.asInt()); RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar* keyword_names_var = keyword_names ? imm(keyword_names) : nullptr; RewriterVar* keyword_names_var = keyword_names ? imm(keyword_names) : nullptr;
...@@ -347,6 +354,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar ...@@ -347,6 +354,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
RewriterVar::SmallVector call_args; RewriterVar::SmallVector call_args;
call_args.push_back(obj); call_args.push_back(obj);
call_args.push_back(argspec_var); call_args.push_back(argspec_var);
call_args.push_back(imm(type_recorder));
if (args_array) if (args_array)
call_args.push_back(args_array); call_args.push_back(args_array);
if (keyword_names_var) if (keyword_names_var)
...@@ -570,12 +578,14 @@ RewriterVar* JitFragmentWriter::getInterp() { ...@@ -570,12 +578,14 @@ RewriterVar* JitFragmentWriter::getInterp() {
} }
RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots, RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots,
int slot_size) { int slot_size, TypeRecorder* type_recorder) {
RewriterVar::SmallVector args_vec(args.begin(), args.end()); RewriterVar::SmallVector args_vec(args.begin(), args.end());
#if ENABLE_BASELINEJIT_ICS #if ENABLE_BASELINEJIT_ICS
RewriterVar* result = createNewVar(); RewriterVar* result = createNewVar();
addAction([=]() { this->_emitPPCall(result, func_addr, args_vec, num_slots, slot_size); }, args, addAction([=]() { this->_emitPPCall(result, func_addr, args_vec, num_slots, slot_size); }, args,
ActionType::NORMAL); ActionType::NORMAL);
if (type_recorder)
return call(false, (void*)recordType, imm(type_recorder), result);
return result; return result;
#else #else
assert(args_vec.size() < 7); assert(args_vec.size() < 7);
...@@ -583,13 +593,13 @@ RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<Rewri ...@@ -583,13 +593,13 @@ RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<Rewri
#endif #endif
} }
Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args, Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
std::vector<BoxedString*>* keyword_names) { Box** args, std::vector<BoxedString*>* keyword_names) {
auto arg_tuple = getTupleFromArgsArray(&args[0], flags.argspec.totalPassed()); auto arg_tuple = getTupleFromArgsArray(&args[0], flags.argspec.totalPassed());
Box* r = callattr(obj, attr, flags, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple), Box* r = callattr(obj, attr, flags, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple), keyword_names); std::get<3>(arg_tuple), keyword_names);
assert(gc::isValidGCObject(r)); assert(gc::isValidGCObject(r));
return r; return recordType(type_recorder, r);
} }
Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) { Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) {
...@@ -639,11 +649,12 @@ Box* JitFragmentWriter::notHelper(Box* b) { ...@@ -639,11 +649,12 @@ Box* JitFragmentWriter::notHelper(Box* b) {
return boxBool(!b->nonzeroIC()); return boxBool(!b->nonzeroIC());
} }
Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args, Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, TypeRecorder* type_recorder, Box** args,
std::vector<BoxedString*>* keyword_names) { std::vector<BoxedString*>* keyword_names) {
auto arg_tuple = getTupleFromArgsArray(&args[0], argspec.totalPassed()); auto arg_tuple = getTupleFromArgsArray(&args[0], argspec.totalPassed());
return runtimeCall(obj, argspec, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple), Box* r = runtimeCall(obj, argspec, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple), keyword_names); std::get<3>(arg_tuple), keyword_names);
return recordType(type_recorder, r);
} }
......
...@@ -33,6 +33,8 @@ class BoxedDict; ...@@ -33,6 +33,8 @@ class BoxedDict;
class BoxedList; class BoxedList;
class BoxedTuple; class BoxedTuple;
class TypeRecorder;
class JitFragmentWriter; class JitFragmentWriter;
// This JIT tier is designed as Pystons entry level JIT tier (executed after a only a few dozens runs of a basic block) // This JIT tier is designed as Pystons entry level JIT tier (executed after a only a few dozens runs of a basic block)
...@@ -193,7 +195,7 @@ public: ...@@ -193,7 +195,7 @@ public:
RewriterVar* emitAugbinop(RewriterVar* lhs, RewriterVar* rhs, int op_type); RewriterVar* emitAugbinop(RewriterVar* lhs, RewriterVar* rhs, int op_type);
RewriterVar* emitBinop(RewriterVar* lhs, RewriterVar* rhs, int op_type); RewriterVar* emitBinop(RewriterVar* lhs, RewriterVar* rhs, int op_type);
RewriterVar* emitCallattr(RewriterVar* obj, BoxedString* attr, CallattrFlags flags, RewriterVar* emitCallattr(AST_expr* node, RewriterVar* obj, BoxedString* attr, CallattrFlags flags,
const llvm::ArrayRef<RewriterVar*> args, std::vector<BoxedString*>* keyword_names); const llvm::ArrayRef<RewriterVar*> args, std::vector<BoxedString*>* keyword_names);
RewriterVar* emitCompare(RewriterVar* lhs, RewriterVar* rhs, int op_type); RewriterVar* emitCompare(RewriterVar* lhs, RewriterVar* rhs, int op_type);
RewriterVar* emitCreateDict(const llvm::ArrayRef<RewriterVar*> keys, const llvm::ArrayRef<RewriterVar*> values); RewriterVar* emitCreateDict(const llvm::ArrayRef<RewriterVar*> keys, const llvm::ArrayRef<RewriterVar*> values);
...@@ -203,7 +205,7 @@ public: ...@@ -203,7 +205,7 @@ public:
RewriterVar* emitCreateTuple(const llvm::ArrayRef<RewriterVar*> values); RewriterVar* emitCreateTuple(const llvm::ArrayRef<RewriterVar*> values);
RewriterVar* emitDeref(InternedString s); RewriterVar* emitDeref(InternedString s);
RewriterVar* emitExceptionMatches(RewriterVar* v, RewriterVar* cls); RewriterVar* emitExceptionMatches(RewriterVar* v, RewriterVar* cls);
RewriterVar* emitGetAttr(RewriterVar* obj, BoxedString* s); RewriterVar* emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node);
RewriterVar* emitGetBlockLocal(InternedString s); RewriterVar* emitGetBlockLocal(InternedString s);
RewriterVar* emitGetBoxedLocal(BoxedString* s); RewriterVar* emitGetBoxedLocal(BoxedString* s);
RewriterVar* emitGetBoxedLocals(); RewriterVar* emitGetBoxedLocals();
...@@ -217,8 +219,8 @@ public: ...@@ -217,8 +219,8 @@ public:
RewriterVar* emitNonzero(RewriterVar* v); RewriterVar* emitNonzero(RewriterVar* v);
RewriterVar* emitNotNonzero(RewriterVar* v); RewriterVar* emitNotNonzero(RewriterVar* v);
RewriterVar* emitRepr(RewriterVar* v); RewriterVar* emitRepr(RewriterVar* v);
RewriterVar* emitRuntimeCall(RewriterVar* obj, ArgPassSpec argspec, const llvm::ArrayRef<RewriterVar*> args, RewriterVar* emitRuntimeCall(AST_expr* node, RewriterVar* obj, ArgPassSpec argspec,
std::vector<BoxedString*>* keyword_names); const llvm::ArrayRef<RewriterVar*> args, std::vector<BoxedString*>* keyword_names);
RewriterVar* emitUnaryop(RewriterVar* v, int op_type); RewriterVar* emitUnaryop(RewriterVar* v, int op_type);
RewriterVar* emitUnpackIntoArray(RewriterVar* v, uint64_t num); RewriterVar* emitUnpackIntoArray(RewriterVar* v, uint64_t num);
RewriterVar* emitYield(RewriterVar* v); RewriterVar* emitYield(RewriterVar* v);
...@@ -255,10 +257,11 @@ private: ...@@ -255,10 +257,11 @@ private:
#endif #endif
RewriterVar* getInterp(); RewriterVar* getInterp();
RewriterVar* emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots, int slot_size); RewriterVar* emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots, int slot_size,
TypeRecorder* type_recorder = NULL);
static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args, static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
std::vector<BoxedString*>* keyword_names); Box** args, std::vector<BoxedString*>* keyword_names);
static Box* createDictHelper(uint64_t num, Box** keys, Box** values); static Box* createDictHelper(uint64_t num, Box** keys, Box** values);
static Box* createListHelper(uint64_t num, Box** data); static Box* createListHelper(uint64_t num, Box** data);
static Box* createSetHelper(uint64_t num, Box** data); static Box* createSetHelper(uint64_t num, Box** data);
...@@ -267,7 +270,8 @@ private: ...@@ -267,7 +270,8 @@ private:
static Box* hasnextHelper(Box* b); static Box* hasnextHelper(Box* b);
static Box* nonzeroHelper(Box* b); static Box* nonzeroHelper(Box* b);
static Box* notHelper(Box* b); static Box* notHelper(Box* b);
static Box* runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args, std::vector<BoxedString*>* keyword_names); static Box* runtimeCallHelper(Box* obj, ArgPassSpec argspec, TypeRecorder* type_recorder, Box** args,
std::vector<BoxedString*>* keyword_names);
void _emitJump(CFGBlock* b, RewriterVar* block_next, int& size_of_exit_to_interp); void _emitJump(CFGBlock* b, RewriterVar* block_next, int& size_of_exit_to_interp);
void _emitOSRPoint(RewriterVar* result, RewriterVar* node_var); void _emitOSRPoint(RewriterVar* result, RewriterVar* node_var);
......
...@@ -670,6 +670,7 @@ void CompiledFunction::speculationFailed() { ...@@ -670,6 +670,7 @@ void CompiledFunction::speculationFailed() {
CLFunction* cl = this->clfunc; CLFunction* cl = this->clfunc;
assert(cl); assert(cl);
assert(this != cl->always_use_version);
bool found = false; bool found = false;
for (int i = 0; i < clfunc->versions.size(); i++) { for (int i = 0; i < clfunc->versions.size(); i++) {
...@@ -681,6 +682,17 @@ void CompiledFunction::speculationFailed() { ...@@ -681,6 +682,17 @@ void CompiledFunction::speculationFailed() {
} }
} }
if (!found) {
for (auto it = clfunc->osr_versions.begin(); it != clfunc->osr_versions.end(); ++it) {
if (it->second == this) {
clfunc->osr_versions.erase(it);
this->dependent_callsites.invalidateAll();
found = true;
break;
}
}
}
if (!found) { if (!found) {
for (int i = 0; i < clfunc->versions.size(); i++) { for (int i = 0; i < clfunc->versions.size(); i++) {
printf("%p\n", clfunc->versions[i]); printf("%p\n", clfunc->versions[i]);
......
...@@ -493,7 +493,10 @@ private: ...@@ -493,7 +493,10 @@ private:
assert(ast); assert(ast);
EffortLevel effort = irstate->getEffortLevel(); EffortLevel effort = irstate->getEffortLevel();
bool record_types = effort != EffortLevel::MAXIMAL; // This is the only place we create type recorders for the llvm tier;
// if we are ok with never doing that there's a bunch of code that could
// be removed.
bool record_types = false;
TypeRecorder* type_recorder; TypeRecorder* type_recorder;
if (record_types) { if (record_types) {
......
...@@ -20,10 +20,12 @@ ...@@ -20,10 +20,12 @@
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
#include "llvm/IR/InstIterator.h" #include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Cloning.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/patchpoints.h"
#include "core/common.h" #include "core/common.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -158,9 +160,14 @@ llvm::Constant* getConstantDouble(double val) { ...@@ -158,9 +160,14 @@ llvm::Constant* getConstantDouble(double val) {
class PrettifyingMaterializer : public llvm::ValueMaterializer { class PrettifyingMaterializer : public llvm::ValueMaterializer {
private: private:
llvm::Module* module; llvm::Module* module;
llvm::ValueToValueMapTy& VMap;
llvm::RemapFlags flags;
llvm::ValueMapTypeRemapper* type_remapper;
public: public:
PrettifyingMaterializer(llvm::Module* module) : module(module) {} PrettifyingMaterializer(llvm::Module* module, llvm::ValueToValueMapTy& VMap, llvm::RemapFlags flags,
llvm::ValueMapTypeRemapper* type_remapper)
: module(module), VMap(VMap), flags(flags), type_remapper(type_remapper) {}
virtual llvm::Value* materializeValueFor(llvm::Value* v) { virtual llvm::Value* materializeValueFor(llvm::Value* v) {
if (llvm::ConstantExpr* ce = llvm::dyn_cast<llvm::ConstantExpr>(v)) { if (llvm::ConstantExpr* ce = llvm::dyn_cast<llvm::ConstantExpr>(v)) {
...@@ -183,6 +190,46 @@ public: ...@@ -183,6 +190,46 @@ public:
return module->getOrInsertGlobal(name, pt->getElementType()); return module->getOrInsertGlobal(name, pt->getElementType());
} }
} }
if (llvm::IntrinsicInst* ii = llvm::dyn_cast<llvm::IntrinsicInst>(v)) {
if (ii->getIntrinsicID() == llvm::Intrinsic::experimental_patchpoint_i64
|| ii->getIntrinsicID() == llvm::Intrinsic::experimental_patchpoint_void
|| ii->getIntrinsicID() == llvm::Intrinsic::experimental_patchpoint_double) {
int pp_id = -1;
for (int i = 0; i < ii->getNumArgOperands(); i++) {
llvm::Value* op = ii->getArgOperand(i);
if (i != 1) {
if (i == 0) {
llvm::ConstantInt* l_pp_id = llvm::cast<llvm::ConstantInt>(op);
pp_id = l_pp_id->getSExtValue();
}
ii->setArgOperand(i, llvm::MapValue(op, VMap, flags, type_remapper, this));
continue;
} else {
assert(pp_id != -1);
void* addr = PatchpointInfo::getSlowpathAddr(pp_id);
bool lookup_success = true;
std::string name;
if (addr == (void*)None) {
name = "None";
} else {
name = g.func_addr_registry.getFuncNameAtAddress(addr, true, &lookup_success);
}
if (!lookup_success) {
llvm::Constant* int_val
= llvm::ConstantInt::get(g.i64, reinterpret_cast<uintptr_t>(addr), false);
llvm::Constant* ptr_val = llvm::ConstantExpr::getIntToPtr(int_val, g.i8_ptr);
ii->setArgOperand(i, ptr_val);
continue;
} else {
ii->setArgOperand(i, module->getOrInsertGlobal(name, g.i8_ptr));
}
}
}
return ii;
}
}
return v; return v;
} }
}; };
...@@ -194,12 +241,14 @@ void dumpPrettyIR(llvm::Function* f) { ...@@ -194,12 +241,14 @@ void dumpPrettyIR(llvm::Function* f) {
llvm::Function* new_f = tmp_module->begin(); llvm::Function* new_f = tmp_module->begin();
llvm::ValueToValueMapTy VMap; llvm::ValueToValueMapTy VMap;
PrettifyingMaterializer materializer(tmp_module.get()); llvm::RemapFlags flags = llvm::RF_None;
llvm::ValueMapTypeRemapper* type_remapper = NULL;
PrettifyingMaterializer materializer(tmp_module.get(), VMap, flags, type_remapper);
for (llvm::Function::iterator I = new_f->begin(), E = new_f->end(); I != E; ++I) { for (llvm::Function::iterator I = new_f->begin(), E = new_f->end(); I != E; ++I) {
VMap[I] = I; VMap[I] = I;
} }
for (llvm::inst_iterator it = inst_begin(new_f), end = inst_end(new_f); it != end; ++it) { for (llvm::inst_iterator it = inst_begin(new_f), end = inst_end(new_f); it != end; ++it) {
llvm::RemapInstruction(&*it, VMap, llvm::RF_None, NULL, &materializer); llvm::RemapInstruction(&*it, VMap, flags, type_remapper, &materializer);
} }
tmp_module->begin()->dump(); tmp_module->begin()->dump();
// tmp_module->dump(); // tmp_module->dump();
......
...@@ -162,7 +162,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -162,7 +162,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
PatchpointInfo* pp = new_patchpoints[r->id].first; PatchpointInfo* pp = new_patchpoints[r->id].first;
assert(pp); assert(pp);
void* dst_func = new_patchpoints[r->id].second; void* slowpath_func = PatchpointInfo::getSlowpathAddr(r->id);
if (VERBOSITY() >= 2) { if (VERBOSITY() >= 2) {
printf("Processing pp %ld; [%d, %d)\n", reinterpret_cast<int64_t>(pp), r->offset, printf("Processing pp %ld; [%d, %d)\n", reinterpret_cast<int64_t>(pp), r->offset,
r->offset + pp->patchpointSize()); r->offset + pp->patchpointSize());
...@@ -179,10 +179,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -179,10 +179,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
uint8_t* end_addr = start_addr + pp->patchpointSize(); uint8_t* end_addr = start_addr + pp->patchpointSize();
if (ENABLE_JIT_OBJECT_CACHE) if (ENABLE_JIT_OBJECT_CACHE)
setSlowpathFunc(start_addr, dst_func); setSlowpathFunc(start_addr, slowpath_func);
// TODO shouldn't have to do it this way
void* slowpath_func = extractSlowpathFunc(start_addr);
//*start_addr = 0xcc; //*start_addr = 0xcc;
// start_addr++; // start_addr++;
...@@ -287,6 +284,11 @@ PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetu ...@@ -287,6 +284,11 @@ PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetu
return r; return r;
} }
void* PatchpointInfo::getSlowpathAddr(unsigned int pp_id) {
RELEASE_ASSERT(pp_id < new_patchpoints.size(), "");
return new_patchpoints[pp_id].second;
}
ICSetupInfo* createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size) { ICSetupInfo* createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size) {
return ICSetupInfo::initialize(has_return_value, 1, size, ICSetupInfo::Generic, type_recorder); return ICSetupInfo::initialize(has_return_value, 1, size, ICSetupInfo::Generic, type_recorder);
} }
......
...@@ -97,6 +97,7 @@ public: ...@@ -97,6 +97,7 @@ public:
static PatchpointInfo* create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args, static PatchpointInfo* create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args,
void* func_addr); void* func_addr);
static void* getSlowpathAddr(unsigned int pp_id);
}; };
class ICSetupInfo { class ICSetupInfo {
......
...@@ -170,7 +170,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -170,7 +170,7 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.malloc = addFunc((void*)malloc, g.i8_ptr, g.i64); g.funcs.malloc = addFunc((void*)malloc, g.i8_ptr, g.i64);
g.funcs.free = addFunc((void*)free, g.void_, g.i8_ptr); g.funcs.free = addFunc((void*)free, g.void_, g.i8_ptr);
g.funcs.allowGLReadPreemption = addFunc((void*)threading::allowGLReadPreemption, g.void_); g.funcs.allowGLReadPreemption = getFunc((void*)threading::allowGLReadPreemption, "allowGLReadPreemption");
GET(softspace); GET(softspace);
......
...@@ -30,6 +30,7 @@ class TypeRecorder; ...@@ -30,6 +30,7 @@ class TypeRecorder;
// (I think most compilers pass "this" as the argument 0 and then shift the rest of the // (I think most compilers pass "this" as the argument 0 and then shift the rest of the
// arguments, but I'd rather not depend on that behavior since I can't find where that's // arguments, but I'd rather not depend on that behavior since I can't find where that's
// specified.) // specified.)
// The return value of this function is 'obj' for ease of use.
extern "C" Box* recordType(TypeRecorder* recorder, Box* obj); extern "C" Box* recordType(TypeRecorder* recorder, Box* obj);
class TypeRecorder { class TypeRecorder {
private: private:
......
...@@ -426,9 +426,11 @@ static bool inGeneratorEntry(unw_word_t ip) { ...@@ -426,9 +426,11 @@ static bool inGeneratorEntry(unw_word_t ip) {
return ((unw_word_t)generatorEntry < ip && ip <= generator_entry_end); return ((unw_word_t)generatorEntry < ip && ip <= generator_entry_end);
} }
static bool inDeopt(unw_word_t ip) { static bool isDeopt(unw_word_t ip) {
static unw_word_t deopt_end = getFunctionEnd((unw_word_t)deopt); // Check for astInterpretDeopt() instead of deopt(), since deopt() will do some
return ((unw_word_t)deopt < ip && ip <= deopt_end); // unwinding and we don't want it to skip things.
static unw_word_t deopt_end = getFunctionEnd((unw_word_t)astInterpretDeopt);
return ((unw_word_t)astInterpretDeopt < ip && ip <= deopt_end);
} }
...@@ -626,7 +628,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu ...@@ -626,7 +628,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
unw_word_t bp = get_cursor_bp(cursor); unw_word_t bp = get_cursor_bp(cursor);
PythonFrameIteratorImpl frame_iter; PythonFrameIteratorImpl frame_iter;
if (inDeopt(ip)) { if (isDeopt(ip)) {
assert(!unwind_session->shouldSkipFrame()); assert(!unwind_session->shouldSkipFrame());
unwind_session->setShouldSkipNextFrame(true); unwind_session->setShouldSkipNextFrame(true);
} else if (frameIsPythonFrame(ip, bp, cursor, &frame_iter)) { } else if (frameIsPythonFrame(ip, bp, cursor, &frame_iter)) {
...@@ -667,7 +669,7 @@ template <typename Func> void unwindPythonStack(Func func) { ...@@ -667,7 +669,7 @@ template <typename Func> void unwindPythonStack(Func func) {
bool stop_unwinding = false; bool stop_unwinding = false;
PythonFrameIteratorImpl frame_iter; PythonFrameIteratorImpl frame_iter;
if (inDeopt(ip)) { if (isDeopt(ip)) {
assert(!unwind_session->shouldSkipFrame()); assert(!unwind_session->shouldSkipFrame());
unwind_session->setShouldSkipNextFrame(true); unwind_session->setShouldSkipNextFrame(true);
} else if (frameIsPythonFrame(ip, bp, &cursor, &frame_iter)) { } else if (frameIsPythonFrame(ip, bp, &cursor, &frame_iter)) {
......
...@@ -89,7 +89,8 @@ void _allowGLReadPreemption(); ...@@ -89,7 +89,8 @@ void _allowGLReadPreemption();
// only be accessed by the thread that holds the gil: // only be accessed by the thread that holds the gil:
extern int gil_check_count; extern int gil_check_count;
extern std::atomic<int> threads_waiting_on_gil; extern std::atomic<int> threads_waiting_on_gil;
inline void allowGLReadPreemption() { extern "C" inline void allowGLReadPreemption() __attribute__((visibility("default")));
extern "C" inline void allowGLReadPreemption() {
#if ENABLE_SAMPLING_PROFILER #if ENABLE_SAMPLING_PROFILER
if (unlikely(sigprof_pending)) { if (unlikely(sigprof_pending)) {
// Output multiple stacktraces if we received multiple signals // Output multiple stacktraces if we received multiple signals
...@@ -167,7 +168,8 @@ inline void promoteGL() { ...@@ -167,7 +168,8 @@ inline void promoteGL() {
} }
inline void demoteGL() { inline void demoteGL() {
} }
inline void allowGLReadPreemption() { extern "C" inline void allowGLReadPreemption() __attribute__((visibility("default")));
extern "C" inline void allowGLReadPreemption() {
} }
#endif #endif
......
...@@ -347,8 +347,9 @@ public: ...@@ -347,8 +347,9 @@ public:
compiled->clfunc = this; compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) { if (compiled->entry_descriptor == NULL) {
if (versions.size() == 0 && compiled->effort == EffortLevel::MAXIMAL && compiled->spec->accepts_all_inputs bool could_have_speculations = (source.get() != NULL);
&& compiled->spec->boxed_return_value) if (!could_have_speculations && versions.size() == 0 && compiled->effort == EffortLevel::MAXIMAL
&& compiled->spec->accepts_all_inputs && compiled->spec->boxed_return_value)
always_use_version = compiled; always_use_version = compiled;
assert(compiled->spec->arg_types.size() == paramspec.totalReceived()); assert(compiled->spec->arg_types.size() == paramspec.totalReceived());
......
...@@ -166,17 +166,11 @@ bool PyLt::operator()(Box* lhs, Box* rhs) const { ...@@ -166,17 +166,11 @@ bool PyLt::operator()(Box* lhs, Box* rhs) const {
} }
extern "C" Box* deopt(AST_expr* expr, Box* value) { extern "C" Box* deopt(AST_expr* expr, Box* value) {
STAT_TIMER(t0, "us_timer_deopt", 10);
static StatCounter num_deopt("num_deopt"); static StatCounter num_deopt("num_deopt");
num_deopt.log(); num_deopt.log();
printf("Deopt!\n");
print_ast(expr);
printf("\n");
dump(value);
printf("\n");
RELEASE_ASSERT(0, "deopt is currently broken...");
auto deopt_state = getDeoptState(); auto deopt_state = getDeoptState();
// Should we only do this selectively? // Should we only do this selectively?
...@@ -189,7 +183,7 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) { ...@@ -189,7 +183,7 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) {
deopt_state.frame_state.frame_info->exc.value = NULL; deopt_state.frame_state.frame_info->exc.value = NULL;
} }
return astInterpretFrom(deopt_state.cf->clfunc, expr, deopt_state.current_stmt, value, deopt_state.frame_state); return astInterpretDeopt(deopt_state.cf->clfunc, expr, deopt_state.current_stmt, value, deopt_state.frame_state);
} }
extern "C" bool softspace(Box* b, bool newval) { extern "C" bool softspace(Box* b, bool newval) {
......
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