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,
if (node->func->type == AST_TYPE::Name && ast_cast<AST_Name>(node->func)->id.s() == "xrange")
return xrange_cls;
// if (node->func->type == AST_TYPE::Attribute && ast_cast<AST_Attribute>(node->func)->attr == "dot")
// return float_cls;
return NULL;
return predictClassFor(node);
}
typedef llvm::DenseMap<InternedString, CompilerType*> TypeMap;
......@@ -115,8 +112,7 @@ private:
assert(old_type);
assert(speculation != TypeAnalysis::NONE);
if (VERBOSITY() >= 3)
printf("Would maybe try to speculate but deopt is currently broken\n");
// TODO: reenable this
return old_type;
if (speculated_cls != NULL && speculated_cls->is_constant) {
......
......@@ -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) {
#ifndef NDEBUG
// mov $imm, %r11:
......
......@@ -518,7 +518,6 @@ public:
friend class RewriterVar;
};
void* extractSlowpathFunc(uint8_t* pp_addr);
void setSlowpathFunc(uint8_t* pp_addr, void* func);
struct GRCompare {
......
......@@ -711,6 +711,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
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)) {
auto it = sym_table.find(name);
if (!liveness->isLiveAtEnd(name, current_block))
......@@ -722,10 +725,11 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sorted_symbol_table[getIsDefinedName(name, source_info->getInternedStrings())] = (Box*)is_defined;
if (is_defined)
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 {
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) {
CallattrFlags callattr_flags{.cls_only = callattr_clsonly, .null_on_nonexistent = false, .argspec = argspec };
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,
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) {
Value v;
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,
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) {
Value ASTInterpreter::visit_attribute(AST_Attribute* node) {
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
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) {
assert(clfunc);
assert(enclosing_stmt);
......
......@@ -75,7 +75,7 @@ void setupInterpreter();
Box* astInterpretFunction(CLFunction* f, int nargs, Box* closure, Box* generator, Box* globals, Box* arg1, Box* arg2,
Box* arg3, Box** args);
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);
AST_stmt* getCurrentStatementForInterpretedFrame(void* frame_ptr);
......
......@@ -19,6 +19,7 @@
#include "codegen/irgen/hooks.h"
#include "codegen/memmgr.h"
#include "codegen/type_recording.h"
#include "core/cfg.h"
#include "runtime/objmodel.h"
#include "runtime/set.h"
......@@ -133,9 +134,11 @@ RewriterVar* JitFragmentWriter::emitBinop(RewriterVar* lhs, RewriterVar* rhs, in
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,
std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS
RewriterVar* attr_var = imm(attr);
RewriterVar* flags_var = imm(flags.asInt());
......@@ -159,7 +162,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
if (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
// We could make this faster but for now: keep it simple, stupid...
RewriterVar* attr_var = imm(attr);
......@@ -177,6 +180,8 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
call_args.push_back(attr_var);
call_args.push_back(flags_var);
call_args.push_back(imm(type_recorder));
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
......@@ -247,8 +252,8 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
return call(false, (void*)exceptionMatchesHelper, v, cls);
}
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s) {
return emitPPCall((void*)getattr, { obj, imm(s) }, 2, 512);
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node) {
return emitPPCall((void*)getattr, { obj, imm(s) }, 2, 512, getTypeRecorderForNode(node));
}
RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s) {
......@@ -311,9 +316,11 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* 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,
std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS
RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar::SmallVector call_args;
......@@ -333,7 +340,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
if (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
RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar* keyword_names_var = keyword_names ? imm(keyword_names) : nullptr;
......@@ -347,6 +354,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(argspec_var);
call_args.push_back(imm(type_recorder));
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
......@@ -570,12 +578,14 @@ RewriterVar* JitFragmentWriter::getInterp() {
}
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());
#if ENABLE_BASELINEJIT_ICS
RewriterVar* result = createNewVar();
addAction([=]() { this->_emitPPCall(result, func_addr, args_vec, num_slots, slot_size); }, args,
ActionType::NORMAL);
if (type_recorder)
return call(false, (void*)recordType, imm(type_recorder), result);
return result;
#else
assert(args_vec.size() < 7);
......@@ -583,13 +593,13 @@ RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<Rewri
#endif
}
Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args,
std::vector<BoxedString*>* keyword_names) {
Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
Box** args, std::vector<BoxedString*>* keyword_names) {
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),
std::get<3>(arg_tuple), keyword_names);
assert(gc::isValidGCObject(r));
return r;
return recordType(type_recorder, r);
}
Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) {
......@@ -639,11 +649,12 @@ Box* JitFragmentWriter::notHelper(Box* b) {
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) {
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);
return recordType(type_recorder, r);
}
......
......@@ -33,6 +33,8 @@ class BoxedDict;
class BoxedList;
class BoxedTuple;
class TypeRecorder;
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)
......@@ -193,7 +195,7 @@ public:
RewriterVar* emitAugbinop(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);
RewriterVar* emitCompare(RewriterVar* lhs, RewriterVar* rhs, int op_type);
RewriterVar* emitCreateDict(const llvm::ArrayRef<RewriterVar*> keys, const llvm::ArrayRef<RewriterVar*> values);
......@@ -203,7 +205,7 @@ public:
RewriterVar* emitCreateTuple(const llvm::ArrayRef<RewriterVar*> values);
RewriterVar* emitDeref(InternedString s);
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* emitGetBoxedLocal(BoxedString* s);
RewriterVar* emitGetBoxedLocals();
......@@ -217,8 +219,8 @@ public:
RewriterVar* emitNonzero(RewriterVar* v);
RewriterVar* emitNotNonzero(RewriterVar* v);
RewriterVar* emitRepr(RewriterVar* v);
RewriterVar* emitRuntimeCall(RewriterVar* obj, ArgPassSpec argspec, const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names);
RewriterVar* emitRuntimeCall(AST_expr* node, RewriterVar* obj, ArgPassSpec argspec,
const llvm::ArrayRef<RewriterVar*> args, std::vector<BoxedString*>* keyword_names);
RewriterVar* emitUnaryop(RewriterVar* v, int op_type);
RewriterVar* emitUnpackIntoArray(RewriterVar* v, uint64_t num);
RewriterVar* emitYield(RewriterVar* v);
......@@ -255,10 +257,11 @@ private:
#endif
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,
std::vector<BoxedString*>* keyword_names);
static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
Box** args, std::vector<BoxedString*>* keyword_names);
static Box* createDictHelper(uint64_t num, Box** keys, Box** values);
static Box* createListHelper(uint64_t num, Box** data);
static Box* createSetHelper(uint64_t num, Box** data);
......@@ -267,7 +270,8 @@ private:
static Box* hasnextHelper(Box* b);
static Box* nonzeroHelper(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 _emitOSRPoint(RewriterVar* result, RewriterVar* node_var);
......
......@@ -670,6 +670,7 @@ void CompiledFunction::speculationFailed() {
CLFunction* cl = this->clfunc;
assert(cl);
assert(this != cl->always_use_version);
bool found = false;
for (int i = 0; i < clfunc->versions.size(); i++) {
......@@ -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) {
for (int i = 0; i < clfunc->versions.size(); i++) {
printf("%p\n", clfunc->versions[i]);
......
......@@ -493,7 +493,10 @@ private:
assert(ast);
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;
if (record_types) {
......
......@@ -20,10 +20,12 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "codegen/codegen.h"
#include "codegen/patchpoints.h"
#include "core/common.h"
#include "runtime/types.h"
......@@ -158,9 +160,14 @@ llvm::Constant* getConstantDouble(double val) {
class PrettifyingMaterializer : public llvm::ValueMaterializer {
private:
llvm::Module* module;
llvm::ValueToValueMapTy& VMap;
llvm::RemapFlags flags;
llvm::ValueMapTypeRemapper* type_remapper;
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) {
if (llvm::ConstantExpr* ce = llvm::dyn_cast<llvm::ConstantExpr>(v)) {
......@@ -183,6 +190,46 @@ public:
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;
}
};
......@@ -194,12 +241,14 @@ void dumpPrettyIR(llvm::Function* f) {
llvm::Function* new_f = tmp_module->begin();
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) {
VMap[I] = I;
}
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->dump();
......
......@@ -162,7 +162,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
PatchpointInfo* pp = new_patchpoints[r->id].first;
assert(pp);
void* dst_func = new_patchpoints[r->id].second;
void* slowpath_func = PatchpointInfo::getSlowpathAddr(r->id);
if (VERBOSITY() >= 2) {
printf("Processing pp %ld; [%d, %d)\n", reinterpret_cast<int64_t>(pp), r->offset,
r->offset + pp->patchpointSize());
......@@ -179,10 +179,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
uint8_t* end_addr = start_addr + pp->patchpointSize();
if (ENABLE_JIT_OBJECT_CACHE)
setSlowpathFunc(start_addr, dst_func);
// TODO shouldn't have to do it this way
void* slowpath_func = extractSlowpathFunc(start_addr);
setSlowpathFunc(start_addr, slowpath_func);
//*start_addr = 0xcc;
// start_addr++;
......@@ -287,6 +284,11 @@ PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetu
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) {
return ICSetupInfo::initialize(has_return_value, 1, size, ICSetupInfo::Generic, type_recorder);
}
......
......@@ -97,6 +97,7 @@ public:
static PatchpointInfo* create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args,
void* func_addr);
static void* getSlowpathAddr(unsigned int pp_id);
};
class ICSetupInfo {
......
......@@ -170,7 +170,7 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.malloc = addFunc((void*)malloc, g.i8_ptr, g.i64);
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);
......
......@@ -30,6 +30,7 @@ class TypeRecorder;
// (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
// specified.)
// The return value of this function is 'obj' for ease of use.
extern "C" Box* recordType(TypeRecorder* recorder, Box* obj);
class TypeRecorder {
private:
......
......@@ -426,9 +426,11 @@ static bool inGeneratorEntry(unw_word_t ip) {
return ((unw_word_t)generatorEntry < ip && ip <= generator_entry_end);
}
static bool inDeopt(unw_word_t ip) {
static unw_word_t deopt_end = getFunctionEnd((unw_word_t)deopt);
return ((unw_word_t)deopt < ip && ip <= deopt_end);
static bool isDeopt(unw_word_t ip) {
// Check for astInterpretDeopt() instead of deopt(), since deopt() will do some
// 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
unw_word_t bp = get_cursor_bp(cursor);
PythonFrameIteratorImpl frame_iter;
if (inDeopt(ip)) {
if (isDeopt(ip)) {
assert(!unwind_session->shouldSkipFrame());
unwind_session->setShouldSkipNextFrame(true);
} else if (frameIsPythonFrame(ip, bp, cursor, &frame_iter)) {
......@@ -667,7 +669,7 @@ template <typename Func> void unwindPythonStack(Func func) {
bool stop_unwinding = false;
PythonFrameIteratorImpl frame_iter;
if (inDeopt(ip)) {
if (isDeopt(ip)) {
assert(!unwind_session->shouldSkipFrame());
unwind_session->setShouldSkipNextFrame(true);
} else if (frameIsPythonFrame(ip, bp, &cursor, &frame_iter)) {
......
......@@ -89,7 +89,8 @@ void _allowGLReadPreemption();
// only be accessed by the thread that holds the gil:
extern int gil_check_count;
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 (unlikely(sigprof_pending)) {
// Output multiple stacktraces if we received multiple signals
......@@ -167,7 +168,8 @@ inline void promoteGL() {
}
inline void demoteGL() {
}
inline void allowGLReadPreemption() {
extern "C" inline void allowGLReadPreemption() __attribute__((visibility("default")));
extern "C" inline void allowGLReadPreemption() {
}
#endif
......
......@@ -347,8 +347,9 @@ public:
compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) {
if (versions.size() == 0 && compiled->effort == EffortLevel::MAXIMAL && compiled->spec->accepts_all_inputs
&& compiled->spec->boxed_return_value)
bool could_have_speculations = (source.get() != NULL);
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;
assert(compiled->spec->arg_types.size() == paramspec.totalReceived());
......
......@@ -166,17 +166,11 @@ bool PyLt::operator()(Box* lhs, Box* rhs) const {
}
extern "C" Box* deopt(AST_expr* expr, Box* value) {
STAT_TIMER(t0, "us_timer_deopt", 10);
static StatCounter num_deopt("num_deopt");
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();
// Should we only do this selectively?
......@@ -189,7 +183,7 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) {
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) {
......
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