Commit 1e672eb3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add a FrameInfo object to all JIT'd frames

parent c75e90df
...@@ -969,6 +969,10 @@ test_cpp_ll: ...@@ -969,6 +969,10 @@ test_cpp_ll:
$(CLANGPP_EXE) $(TEST_DIR)/test.cpp -o test.ll -c -O3 -emit-llvm -S -std=c++11 -g $(CLANGPP_EXE) $(TEST_DIR)/test.cpp -o test.ll -c -O3 -emit-llvm -S -std=c++11 -g
less test.ll less test.ll
rm test.ll rm test.ll
bench_exceptions:
$(CLANGPP_EXE) $(TEST_DIR)/bench_exceptions.cpp -o bench_exceptions -O3 -std=c++11
zsh -c 'ulimit -v $(MAX_MEM_KB); ulimit -d $(MAX_MEM_KB); time ./bench_exceptions'
rm bench_exceptions
TEST_EXT_MODULE_NAMES := basic_test descr_test slots_test TEST_EXT_MODULE_NAMES := basic_test descr_test slots_test
......
...@@ -70,6 +70,7 @@ struct GlobalState { ...@@ -70,6 +70,7 @@ struct GlobalState {
llvm::Type* llvm_class_type, *llvm_class_type_ptr; llvm::Type* llvm_class_type, *llvm_class_type_ptr;
llvm::Type* llvm_opaque_type; llvm::Type* llvm_opaque_type;
llvm::Type* llvm_str_type_ptr; llvm::Type* llvm_str_type_ptr;
llvm::Type* frame_info_type;
llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr; llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr;
llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr; llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr;
llvm::Type* llvm_excinfo_type; llvm::Type* llvm_excinfo_type;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
namespace pyston { namespace pyston {
extern "C" void dumpLLVM(llvm::Value* v) { extern "C" void dumpLLVM(llvm::Value* v) {
v->getType()->dump();
v->dump(); v->dump();
} }
...@@ -71,6 +72,28 @@ llvm::Value* IRGenState::getScratchSpace(int min_bytes) { ...@@ -71,6 +72,28 @@ llvm::Value* IRGenState::getScratchSpace(int min_bytes) {
return scratch_space; return scratch_space;
} }
llvm::Value* IRGenState::getFrameInfoVar() {
if (!frame_info) {
llvm::BasicBlock& entry_block = getLLVMFunction()->getEntryBlock();
llvm::IRBuilder<true> builder(&entry_block);
if (entry_block.begin() != entry_block.end())
builder.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt());
llvm::AllocaInst* al = builder.CreateAlloca(g.frame_info_type, NULL, "frame_info");
assert(al->isStaticAlloca());
static_assert(offsetof(FrameInfo, exc_type) == 0, "");
llvm::Value* exctype_gep = builder.CreateConstInBoundsGEP2_32(al, 0, 0);
builder.CreateStore(embedConstantPtr(NULL, g.llvm_value_type_ptr), exctype_gep);
frame_info = al;
}
return frame_info;
}
ScopeInfo* IRGenState::getScopeInfo() { ScopeInfo* IRGenState::getScopeInfo() {
return getSourceInfo()->getScopeInfo(); return getSourceInfo()->getScopeInfo();
} }
...@@ -2240,6 +2263,8 @@ public: ...@@ -2240,6 +2263,8 @@ public:
std::vector<llvm::Value*>& stackmap_args) override { std::vector<llvm::Value*>& stackmap_args) override {
int initial_args = stackmap_args.size(); int initial_args = stackmap_args.size();
stackmap_args.push_back(irstate->getFrameInfoVar());
assert(INT->llvmType() == g.i64); assert(INT->llvmType() == g.i64);
stackmap_args.push_back(getConstantInt((uint64_t)current_stmt, g.i64)); stackmap_args.push_back(getConstantInt((uint64_t)current_stmt, g.i64));
pp->addFrameVar("!current_stmt", INT); pp->addFrameVar("!current_stmt", INT);
......
...@@ -58,11 +58,13 @@ private: ...@@ -58,11 +58,13 @@ private:
llvm::MDNode* func_dbg_info; llvm::MDNode* func_dbg_info;
llvm::AllocaInst* scratch_space; llvm::AllocaInst* scratch_space;
llvm::Value* frame_info;
int scratch_size; int scratch_size;
public: public:
IRGenState(CompiledFunction* cf, SourceInfo* source_info, GCBuilder* gc, llvm::MDNode* func_dbg_info) IRGenState(CompiledFunction* cf, SourceInfo* source_info, GCBuilder* gc, llvm::MDNode* func_dbg_info)
: cf(cf), source_info(source_info), gc(gc), func_dbg_info(func_dbg_info), scratch_space(NULL), scratch_size(0) { : cf(cf), source_info(source_info), gc(gc), func_dbg_info(func_dbg_info), scratch_space(NULL), frame_info(NULL),
scratch_size(0) {
assert(cf->func); assert(cf->func);
assert(!cf->clfunc); // in this case don't need to pass in sourceinfo assert(!cf->clfunc); // in this case don't need to pass in sourceinfo
} }
...@@ -76,6 +78,7 @@ public: ...@@ -76,6 +78,7 @@ public:
GCBuilder* getGC() { return gc; } GCBuilder* getGC() { return gc; }
llvm::Value* getScratchSpace(int min_bytes); llvm::Value* getScratchSpace(int min_bytes);
llvm::Value* getFrameInfoVar();
ConcreteCompilerType* getReturnType() { ConcreteCompilerType* getReturnType() {
assert(cf->spec); assert(cf->spec);
......
...@@ -63,6 +63,12 @@ int PatchpointInfo::patchpointSize() { ...@@ -63,6 +63,12 @@ int PatchpointInfo::patchpointSize() {
return CALL_ONLY_SIZE; return CALL_ONLY_SIZE;
} }
bool StackMap::Record::Location::operator==(const StackMap::Record::Location& rhs) {
// TODO: this check is overly-strict. Some fields are not used depending
// on the value of type, and I don't think "flags" is used at all currently.
return (type == rhs.type) && (flags == rhs.flags) && (regnum == rhs.regnum) && (offset == rhs.offset);
}
void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) { void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) {
assert(r->locations.size() == totalStackmapArgs()); assert(r->locations.size() == totalStackmapArgs());
...@@ -70,6 +76,16 @@ void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) { ...@@ -70,6 +76,16 @@ void PatchpointInfo::parseLocationMap(StackMap::Record* r, LocationMap* map) {
// printf("parsing pp %ld:\n", reinterpret_cast<int64_t>(this)); // printf("parsing pp %ld:\n", reinterpret_cast<int64_t>(this));
StackMap::Record::Location frame_info_location = r->locations[cur_arg];
cur_arg++;
// We could allow the frame_info to exist in a different location for each callsite,
// but in reality it will always live at a fixed stack offset.
if (map->frameInfoFound()) {
assert(frame_info_location == map->frame_info_location);
} else {
map->frame_info_location = frame_info_location;
}
for (FrameVarInfo& frame_var : frame_vars) { for (FrameVarInfo& frame_var : frame_vars) {
int num_args = frame_var.type->numFrameArgs(); int num_args = frame_var.type->numFrameArgs();
......
...@@ -146,6 +146,9 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -146,6 +146,9 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_excinfo_type = g.stdlib_module->getTypeByName("struct.pyston::ExcInfo"); g.llvm_excinfo_type = g.stdlib_module->getTypeByName("struct.pyston::ExcInfo");
assert(g.llvm_excinfo_type); assert(g.llvm_excinfo_type);
g.frame_info_type = g.stdlib_module->getTypeByName("struct.pyston::FrameInfo");
assert(g.frame_info_type);
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N)) #define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
g.funcs.printf = addFunc((void*)printf, g.i8_ptr, true); g.funcs.printf = addFunc((void*)printf, g.i8_ptr, true);
......
...@@ -48,6 +48,8 @@ struct StackMap { ...@@ -48,6 +48,8 @@ struct StackMap {
uint8_t flags; uint8_t flags;
uint16_t regnum; uint16_t regnum;
int32_t offset; int32_t offset;
bool operator==(const Location& rhs);
}; };
struct __attribute__((__packed__)) LiveOut { struct __attribute__((__packed__)) LiveOut {
...@@ -73,6 +75,10 @@ struct StackMap { ...@@ -73,6 +75,10 @@ struct StackMap {
class LocationMap { class LocationMap {
public: public:
std::vector<uint64_t> constants; std::vector<uint64_t> constants;
StackMap::Record::Location frame_info_location;
bool frameInfoFound() { return frame_info_location.type != 0; }
struct LocationTable { struct LocationTable {
struct LocationEntry { struct LocationEntry {
uint64_t _debug_pp_id; uint64_t _debug_pp_id;
......
...@@ -450,6 +450,17 @@ const LineInfo* getMostRecentLineInfo() { ...@@ -450,6 +450,17 @@ const LineInfo* getMostRecentLineInfo() {
return lineInfoForFrame(*frame); return lineInfoForFrame(*frame);
} }
FrameInfo* getTopFrameInfo() {
std::unique_ptr<PythonFrameIterator> frame = getTopPythonFrame();
if (frame.get_id().type == PythonFrameId::COMPILED) {
abort();
} else if (frame.get_id().type == PythonFrameId::INTERPRETED) {
abort();
} else {
abort();
}
}
CompiledFunction* getTopCompiledFunction() { CompiledFunction* getTopCompiledFunction() {
return getTopPythonFrame()->getCF(); return getTopPythonFrame()->getCF();
} }
...@@ -460,13 +471,6 @@ BoxedModule* getCurrentModule() { ...@@ -460,13 +471,6 @@ BoxedModule* getCurrentModule() {
return compiledFunction->clfunc->source->parent_module; return compiledFunction->clfunc->source->parent_module;
} }
ExecutionPoint getExecutionPoint() {
auto frame = getTopPythonFrame();
auto cf = frame->getCF();
auto current_stmt = frame->getCurrentStatement();
return ExecutionPoint({.cf = cf, .current_stmt = current_stmt });
}
BoxedDict* getLocals(bool only_user_visible) { BoxedDict* getLocals(bool only_user_visible) {
for (PythonFrameIterator& frame_info : unwindPythonFrames()) { for (PythonFrameIterator& frame_info : unwindPythonFrames()) {
if (frame_info.getId().type == PythonFrameId::COMPILED) { if (frame_info.getId().type == PythonFrameId::COMPILED) {
......
...@@ -30,11 +30,9 @@ CompiledFunction* getCFForAddress(uint64_t addr); ...@@ -30,11 +30,9 @@ CompiledFunction* getCFForAddress(uint64_t addr);
class BoxedDict; class BoxedDict;
BoxedDict* getLocals(bool only_user_visible); BoxedDict* getLocals(bool only_user_visible);
struct ExecutionPoint { struct FrameInfo;
CompiledFunction* cf; FrameInfo* getTopFrameInfo();
AST_stmt* current_stmt;
};
ExecutionPoint getExecutionPoint();
} }
#endif #endif
...@@ -476,6 +476,14 @@ struct ExcInfo { ...@@ -476,6 +476,14 @@ struct ExcInfo {
ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {} ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {}
bool matches(BoxedClass* cls) const; bool matches(BoxedClass* cls) const;
}; };
struct FrameInfo {
// *Not the same semantics as CPython's frame->f_exc*
// In CPython, f_exc is the saved exc_info from the previous frame.
// In Pyston, exc is the frame-local value of sys.exc_info.
// - This makes frame entering+leaving faster at the expense of slower exceptions.
ExcInfo exc;
};
} }
#endif #endif
...@@ -688,13 +688,6 @@ Box* locals() { ...@@ -688,13 +688,6 @@ Box* locals() {
return getLocals(true /* filter */); return getLocals(true /* filter */);
} }
Box* deopt() {
auto locals = getLocals(false /* filter */);
auto execution_point = getExecutionPoint();
return astInterpretFrom(execution_point.cf, execution_point.current_stmt, locals);
}
Box* divmod(Box* lhs, Box* rhs) { Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL); return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL);
} }
...@@ -1054,7 +1047,6 @@ void setupBuiltins() { ...@@ -1054,7 +1047,6 @@ void setupBuiltins() {
builtins_module->giveAttr("globals", new BoxedFunction(boxRTFunction((void*)globals, UNKNOWN, 0, 0, false, false))); builtins_module->giveAttr("globals", new BoxedFunction(boxRTFunction((void*)globals, UNKNOWN, 0, 0, false, false)));
builtins_module->giveAttr("locals", new BoxedFunction(boxRTFunction((void*)locals, UNKNOWN, 0, 0, false, false))); builtins_module->giveAttr("locals", new BoxedFunction(boxRTFunction((void*)locals, UNKNOWN, 0, 0, false, false)));
builtins_module->giveAttr("deopt", new BoxedFunction(boxRTFunction((void*)deopt, UNKNOWN, 0, 0, false, false)));
builtins_module->giveAttr("iter", new BoxedFunction(boxRTFunction((void*)getiter, UNKNOWN, 1, 0, false, false))); builtins_module->giveAttr("iter", new BoxedFunction(boxRTFunction((void*)getiter, UNKNOWN, 1, 0, false, false)));
......
...@@ -35,13 +35,11 @@ static void forceLink(void* x) { ...@@ -35,13 +35,11 @@ static void forceLink(void* x) {
printf("%p\n", x); printf("%p\n", x);
} }
extern "C" void __py_personality_v0() {
RELEASE_ASSERT(0, "not used");
}
namespace _force { namespace _force {
// Force the "FrameInfo" type to make it into the stdlib:
FrameInfo* _frame_info_forcer;
#define FORCE(name) forceLink((void*)name) #define FORCE(name) forceLink((void*)name)
void force() { void force() {
FORCE(softspace); FORCE(softspace);
......
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