Commit a239c80b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Refactor some unwinding code

Make some things owned by the cf rather than using global registries,
so that 1) we can eventually free the right things when we start freeing
cf's, and 2) we can have a single ip->cf mapping instead of lots of
ip->other things mappings.

Also added some helper classes for making stack crawling easier.
parent c61e828d
......@@ -47,3 +47,6 @@ find_problem.status
*.pch
compile.log
*.swp
*.swo
......@@ -543,7 +543,7 @@ llvm/profile/%: $(LLVM_SRC)/_patched $(LLVM_CONFIGURATION)
$(VERB) if [ ! -f $(patsubst llvm/profile/%,$(LLVM_BUILD)/%/Makefile,$@) ]; then cp $(patsubst llvm/profile/%,$(LLVM_SRC)/%/Makefile,$@) $(patsubst llvm/profile/%,$(LLVM_BUILD)/%/,$@); fi
$(LLVM_BUILD_ENV) $(MAKE) -C $(patsubst llvm/profile/%,$(LLVM_BUILD)/%,$@) $(LLVM_BUILD_VARS) CXXFLAGS="-fno-omit-frame-pointer -fno-function-sections" ENABLE_PROFILING=1 ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 $(LLVM_MAKE_ARGS)
$(LLVM_SRC)/_patched: $(wildcard llvm_patches/*) $(wildcard clang_patches/*) $(LLVM_REVISION_FILE)
$(LLVM_SRC)/_patched: $(wildcard ../llvm_patches/*) $(wildcard ../clang_patches/*) $(LLVM_REVISION_FILE)
$(MAKE) llvm_up
llvm_up:
python $(TOOLS_DIR)/git_svn_gotorev.py $(LLVM_SRC) $(LLVM_REVISION) ../llvm_patches
......@@ -880,8 +880,13 @@ test_cpp_asm:
# $(GPP) tests/test.cpp -o test -c -O3
objdump -d test | less
rm test
test_cpp_dwarf:
$(CLANGPP_EXE) ../test/test.cpp -o test -c -O3 -std=c++11 -g
# $(GPP) tests/test.cpp -o test -c -O3
objdump -W test | less
rm test
test_cpp_ll:
$(CLANGPP_EXE) ../test/test.cpp -o test.ll -c -O3 -emit-llvm -S -std=c++11
$(CLANGPP_EXE) ../test/test.cpp -o test.ll -c -O3 -emit-llvm -S -std=c++11 -g
less test.ll
rm test.ll
......
......@@ -20,6 +20,7 @@
#include "analysis/fpc.h"
#include "analysis/scoping_analysis.h"
#include "codegen/codegen.h"
#include "codegen/type_recording.h"
#include "core/ast.h"
#include "core/cfg.h"
......
......@@ -198,8 +198,8 @@ ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int
}
static std::unordered_map<void*, ICInfo*> ics_by_return_addr;
void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, StackInfo stack_info,
std::unordered_set<int> live_outs) {
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, PatchpointSetupInfo* pp,
StackInfo stack_info, std::unordered_set<int> live_outs) {
int size = pp->totalSize();
uint8_t* end_addr = start_addr + size;
uint8_t* slowpath_addr = end_addr;
......@@ -255,12 +255,17 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St
writer->jmp(JumpDestination::fromStart(pp->slot_size * (pp->num_slots - i)));
}
ics_by_return_addr[rtn_addr]
= new ICInfo(start_addr, slowpath_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(),
live_outs, return_register, pp->type_recorder);
ICInfo* ic = new ICInfo(start_addr, slowpath_addr, stack_info, pp->num_slots, pp->slot_size,
pp->getCallingConvention(), live_outs, return_register, pp->type_recorder);
ics_by_return_addr[rtn_addr] = ic;
assert(cf);
cf->ics.push_back(ic);
}
ICInfo* getICInfo(void* rtn_addr) {
// TODO: load this from the CF instead of tracking it separately
std::unordered_map<void*, ICInfo*>::iterator it = ics_by_return_addr.find(rtn_addr);
if (it == ics_by_return_addr.end())
return NULL;
......
......@@ -128,7 +128,8 @@ public:
};
class PatchpointSetupInfo;
void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo*, StackInfo stack_info,
class CompiledFunction;
void registerCompiledPatchpoint(CompiledFunction* cf, uint8_t* start_addr, PatchpointSetupInfo*, StackInfo stack_info,
std::unordered_set<int> live_outs);
ICInfo* getICInfo(void* rtn_addr);
......
......@@ -173,7 +173,7 @@ public:
}
};
GlobalState::GlobalState() : context(llvm::getGlobalContext()){};
GlobalState::GlobalState() : context(llvm::getGlobalContext()), cur_module(NULL), cur_cf(NULL){};
llvm::JITEventListener* makeRegistryListener() {
return new RegistryEventListener();
......
......@@ -31,8 +31,6 @@ class TargetMachine;
namespace pyston {
class PystonJITEventListener;
class FunctionAddressRegistry {
private:
struct FuncInfo {
......@@ -57,8 +55,11 @@ llvm::JITEventListener* makeRegistryListener();
llvm::JITEventListener* makeTracebacksListener();
struct GlobalState {
// Much of this section is not thread-safe:
llvm::LLVMContext& context;
llvm::Module* stdlib_module, *cur_module;
llvm::Module* stdlib_module;
llvm::Module* cur_module;
CompiledFunction* cur_cf;
llvm::TargetMachine* tm;
llvm::ExecutionEngine* engine;
......@@ -84,8 +85,6 @@ extern GlobalState g;
// in runtime_hooks.cpp:
void initGlobalFuncs(GlobalState& g);
const LineInfo* getLineInfoFor(uint64_t inst_addr);
DS_DECLARE_RWLOCK(codegen_rwlock);
}
......
......@@ -20,6 +20,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/raw_ostream.h"
#include "codegen/codegen.h"
#include "codegen/gcbuilder.h"
#include "codegen/irgen.h"
#include "codegen/irgen/util.h"
......
......@@ -18,7 +18,6 @@
#include <stdint.h>
#include <vector>
#include "codegen/codegen.h"
#include "core/ast.h"
#include "core/types.h"
......
......@@ -42,7 +42,7 @@
namespace pyston {
PystonJITEventListener::PystonJITEventListener() {
DisassemblerJITEventListener::DisassemblerJITEventListener() {
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
llvm::InitializeNativeTargetDisassembler();
......@@ -113,8 +113,8 @@ PystonJITEventListener::PystonJITEventListener() {
assert(MIA);
}
void PystonJITEventListener::NotifyFunctionEmitted(const llvm::Function& f, void* ptr, size_t size,
const llvm::JITEvent_EmittedFunctionDetails& details) {
void DisassemblerJITEventListener::NotifyFunctionEmitted(const llvm::Function& f, void* ptr, size_t size,
const llvm::JITEvent_EmittedFunctionDetails& details) {
const llvm::MachineFunction& MF = *details.MF; //*const_cast<llvm::MachineFunction*>(details.MF);
printf("emitted! %p %ld %s\n", ptr, size, f.getName().data());
// MF.dump();
......@@ -140,7 +140,7 @@ void PystonJITEventListener::NotifyFunctionEmitted(const llvm::Function& f, void
llvm::errs().flush();
}
void PystonJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
void DisassemblerJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
llvm::outs() << "An object has been emitted:\n";
llvm::error_code code;
......
......@@ -27,7 +27,7 @@ class MCInstPrinter;
namespace pyston {
class PystonJITEventListener : public llvm::JITEventListener {
class DisassemblerJITEventListener : public llvm::JITEventListener {
private:
llvm::AsmPrinter* asm_printer;
llvm::MCDisassembler* DisAsm;
......@@ -35,7 +35,7 @@ private:
llvm::MCInstPrinter* IP;
public:
PystonJITEventListener();
DisassemblerJITEventListener();
virtual void NotifyFunctionEmitted(const llvm::Function& f, void* ptr, size_t size,
const llvm::JITEvent_EmittedFunctionDetails& details);
......
......@@ -250,7 +250,7 @@ void initCodegen() {
if (SHOW_DISASM) {
#if LLVMREV < 216983
llvm::JITEventListener* listener = new PystonJITEventListener();
llvm::JITEventListener* listener = new DisassemblerJITEventListener();
g.jit_listeners.push_back(listener);
g.engine->RegisterJITEventListener(listener);
#else
......
......@@ -14,6 +14,7 @@
#include "codegen/gcbuilder.h"
#include "codegen/codegen.h"
#include "codegen/irgen.h"
#include "core/options.h"
......
......@@ -100,6 +100,7 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
}
void* compiled = NULL;
cf->code = NULL;
if (effort > EffortLevel::INTERPRETED) {
Timer _t("to jit the IR");
#if LLVMREV < 215967
......@@ -107,8 +108,13 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
#else
g.engine->addModule(std::unique_ptr<llvm::Module>(cf->func->getParent()));
#endif
compiled = (void*)g.engine->getFunctionAddress(cf->func->getName());
g.cur_cf = cf;
void* compiled = (void*)g.engine->getFunctionAddress(cf->func->getName());
g.cur_cf = NULL;
assert(compiled);
ASSERT(compiled == cf->code, "cf->code should have gotten filled in");
cf->llvm_code = embedConstantPtr(compiled, cf->func->getType());
long us = _t.end();
......@@ -116,31 +122,27 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
us_jitting.log(us);
static StatCounter num_jits("num_jits");
num_jits.log();
} else {
// HAX just get it for now; this is just to make sure everything works
//(void*)g.func_registry.getFunctionAddress(cf->func->getName());
}
cf->code = compiled;
if (VERBOSITY("irgen") >= 1) {
printf("Compiled function to %p\n", compiled);
printf("Compiled function to %p\n", cf->code);
}
StackMap* stackmap = parseStackMap();
patchpoints::processStackmap(stackmap);
patchpoints::processStackmap(cf, stackmap);
}
static std::unordered_map<std::string, CLFunction*> machine_name_to_clfunction;
CLFunction* clFunctionForMachineFunctionName(const std::string& machine_name) {
static std::unordered_map<std::string, CompiledFunction*> machine_name_to_cf;
CompiledFunction* cfForMachineFunctionName(const std::string& machine_name) {
assert(machine_name.size());
auto r = machine_name_to_clfunction[machine_name];
auto r = machine_name_to_cf[machine_name];
ASSERT(r, "%s", machine_name.c_str());
return r;
}
void registerMachineName(const std::string& machine_name, CLFunction* cl) {
assert(machine_name_to_clfunction.count(machine_name) == 0);
machine_name_to_clfunction[machine_name] = cl;
void registerMachineName(const std::string& machine_name, CompiledFunction* cf) {
assert(machine_name_to_cf.count(machine_name) == 0);
machine_name_to_cf[machine_name] = cf;
}
// Compiles a new version of the function with the given signature and adds it to the list;
......@@ -190,7 +192,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
CompiledFunction* cf = doCompile(source, entry, effort, spec, name);
registerMachineName(cf->func->getName(), f);
registerMachineName(cf->func->getName(), cf);
compileIR(cf, effort);
f->addVersion(cf);
......
......@@ -31,7 +31,7 @@ class BoxedModule;
void compileAndRunModule(AST_Module* m, BoxedModule* bm);
// will we always want to generate unique function names? (ie will this function always be reasonable?)
CLFunction* clFunctionForMachineFunctionName(const std::string&);
CompiledFunction* cfForMachineFunctionName(const std::string&);
}
#endif
......@@ -19,6 +19,7 @@
#include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h"
#include "analysis/type_analysis.h"
#include "codegen/codegen.h"
#include "codegen/compvars.h"
#include "codegen/irgen.h"
#include "codegen/irgen/util.h"
......
......@@ -54,7 +54,7 @@ PatchpointSetupInfo* PatchpointSetupInfo::initialize(bool has_return_value, int
namespace patchpoints {
void processStackmap(StackMap* stackmap) {
void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
int nrecords = stackmap ? stackmap->records.size() : 0;
for (int i = 0; i < nrecords; i++) {
......@@ -103,7 +103,7 @@ void processStackmap(StackMap* stackmap) {
live_outs.insert(14);
live_outs.insert(15);
registerCompiledPatchpoint(start_addr, pp,
registerCompiledPatchpoint(cf, start_addr, pp,
StackInfo({ stack_size, has_scratch, pp->numScratchBytes(), scratch_rbp_offset }),
std::move(live_outs));
}
......
......@@ -84,7 +84,7 @@ struct StackMap;
namespace patchpoints {
void processStackmap(StackMap* stackmap);
void processStackmap(CompiledFunction* cf, StackMap* stackmap);
PatchpointSetupInfo* createGenericPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder,
bool has_return_value, int size);
......
......@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "codegen/unwinding.h"
#include <dlfcn.h>
#include <sys/types.h>
#include <unistd.h>
......@@ -22,6 +24,8 @@
#include "llvm/IR/DebugInfo.h"
#include "codegen/codegen.h"
#include "codegen/irgen/hooks.h"
#include "codegen/llvm_interpreter.h"
#define UNW_LOCAL_ONLY
......@@ -65,57 +69,37 @@ void parseEhFrame(uint64_t start_addr, uint64_t size, uint64_t* out_data, uint64
*out_len = nentries;
}
class LineTableRegistry {
class CFRegistry {
private:
struct LineTableRegistryEntry {
const uint64_t addr, size;
std::vector<std::pair<uint64_t, LineInfo> > linetable;
LineTableRegistryEntry(uint64_t addr, uint64_t size) : addr(addr), size(size) {}
};
std::vector<LineTableRegistryEntry> entries;
// TODO use a binary search tree
std::vector<CompiledFunction*> cfs;
public:
void registerLineTable(uint64_t addr, uint64_t size, llvm::DILineInfoTable& lines) {
entries.push_back(LineTableRegistryEntry(addr, size));
auto& entry = entries.back();
for (int i = 0; i < lines.size(); i++) {
entry.linetable.push_back(
std::make_pair(lines[i].first, LineInfo(lines[i].second.Line, lines[i].second.Column,
lines[i].second.FileName, lines[i].second.FunctionName)));
}
}
void registerCF(CompiledFunction* cf) { cfs.push_back(cf); }
const LineInfo* getLineInfoFor(uint64_t addr) {
for (const auto& entry : entries) {
if (addr < entry.addr || addr >= entry.addr + entry.size)
continue;
const auto& linetable = entry.linetable;
for (int i = linetable.size() - 1; i >= 0; i--) {
if (linetable[i].first < addr)
return &linetable[i].second;
}
abort();
CompiledFunction* getCFForAddress(uint64_t addr) {
for (auto* cf : cfs) {
if (cf->code_start <= addr && addr < cf->code_start + cf->code_size)
return cf;
}
return NULL;
}
};
static LineTableRegistry line_table_registry;
const LineInfo* getLineInfoFor(uint64_t addr) {
return line_table_registry.getLineInfoFor(addr);
static CFRegistry cf_registry;
CompiledFunction* getCFForAddress(uint64_t addr) {
return cf_registry.getCFForAddress(addr);
}
class TracebacksEventListener : public llvm::JITEventListener {
public:
void NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
#if LLVMREV < 214433
llvm::DIContext* Context = llvm::DIContext::getDWARFContext(Obj.getObjectFile());
#else
llvm::DIContext* Context = llvm::DIContext::getDWARFContext(*Obj.getObjectFile());
#endif
std::unique_ptr<llvm::DIContext> Context(llvm::DIContext::getDWARFContext(*Obj.getObjectFile()));
assert(g.cur_cf);
assert(!g.cur_cf->line_table);
LineTable* line_table = g.cur_cf->line_table = new LineTable();
llvm_error_code ec;
for (llvm::object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E && !ec; ++I) {
......@@ -149,10 +133,18 @@ public:
lines[i].second.FunctionName.c_str(), lines[i].first);
}
}
line_table_registry.registerLineTable(Addr, Size, lines);
assert(g.cur_cf->code_start == 0);
g.cur_cf->code_start = Addr;
g.cur_cf->code_size = Size;
cf_registry.registerCF(g.cur_cf);
for (const auto& p : lines) {
line_table->entries.push_back(std::make_pair(
p.first, LineInfo(p.second.Line, p.second.Column, p.second.FileName, p.second.FunctionName)));
}
}
}
delete Context;
// Currently-unused libunwind support:
llvm_error_code code;
......@@ -212,10 +204,199 @@ public:
}
};
std::string getPythonFuncAt(void* addr, void* sp) {
return "";
struct PythonFrameId {
enum FrameType {
COMPILED,
INTERPRETED,
} type;
union {
uint64_t ip; // if type == COMPILED
uint64_t bp; // if type == INTERPRETED
};
};
class PythonFrameIterator {
private:
PythonFrameId id;
unw_context_t ctx;
unw_cursor_t cursor;
CompiledFunction* cf;
PythonFrameIterator() {}
// not copyable or movable, since 'cursor' holds an internal pointer to 'ctx'
PythonFrameIterator(const PythonFrameIterator&) = delete;
void operator=(const PythonFrameIterator&) = delete;
PythonFrameIterator(const PythonFrameIterator&&) = delete;
void operator=(const PythonFrameIterator&&) = delete;
public:
CompiledFunction* getCF() const {
assert(cf);
return cf;
}
const PythonFrameId& getId() const { return id; }
static std::unique_ptr<PythonFrameIterator> end() { return std::unique_ptr<PythonFrameIterator>(nullptr); }
static std::unique_ptr<PythonFrameIterator> begin() {
std::unique_ptr<PythonFrameIterator> rtn(new PythonFrameIterator());
unw_getcontext(&rtn->ctx);
unw_init_local(&rtn->cursor, &rtn->ctx);
bool found = rtn->incr();
if (!found)
return NULL;
return rtn;
}
uint64_t getReg(int dwarf_num) {
assert(0 <= dwarf_num && dwarf_num < 16);
// for x86_64, at least, libunwind seems to use the dwarf numbering
unw_word_t rtn;
int code = unw_get_reg(&cursor, dwarf_num, &rtn);
assert(code == 0);
return rtn;
}
bool incr() {
while (true) {
int r = unw_step(&this->cursor);
if (r <= 0) {
return false;
}
unw_word_t ip;
unw_get_reg(&this->cursor, UNW_REG_IP, &ip);
CompiledFunction* cf = getCFForAddress(ip);
this->cf = cf;
if (cf) {
this->id.type = PythonFrameId::COMPILED;
this->id.ip = ip;
unw_word_t bp;
unw_get_reg(&this->cursor, UNW_TDEP_BP, &bp);
return true;
}
// TODO shouldn't need to do this expensive-looking query, if we
// knew the bounds of the interpretFunction() function:
unw_proc_info_t pip;
int code = unw_get_proc_info(&this->cursor, &pip);
RELEASE_ASSERT(code == 0, "%d", code);
if (pip.start_ip == (intptr_t)interpretFunction) {
unw_word_t bp;
unw_get_reg(&this->cursor, UNW_TDEP_BP, &bp);
this->id.type = PythonFrameId::INTERPRETED;
this->id.bp = bp;
return true;
}
// keep unwinding
}
}
// Adapter classes to be able to use this in a C++11 range for loop.
// (Needed because we do more memory management than typical.)
// TODO: maybe the memory management should be handled by the Manager?
class Manager {
public:
class Holder {
public:
std::unique_ptr<PythonFrameIterator> it;
Holder(std::unique_ptr<PythonFrameIterator> it) : it(std::move(it)) {}
bool operator!=(const Holder& rhs) const {
assert(rhs.it.get() == NULL); // this is the only intended use case, for comparing to end()
return it != rhs.it;
}
Holder& operator++() {
assert(it.get());
bool found = it->incr();
if (!found)
it.release();
return *this;
}
const PythonFrameIterator& operator*() const {
assert(it.get());
return *it.get();
}
};
Holder begin() { return PythonFrameIterator::begin(); }
Holder end() { return PythonFrameIterator::end(); }
};
};
PythonFrameIterator::Manager unwindPythonFrames() {
return PythonFrameIterator::Manager();
}
static std::unique_ptr<PythonFrameIterator> getTopPythonFrame() {
std::unique_ptr<PythonFrameIterator> fr = PythonFrameIterator::begin();
RELEASE_ASSERT(fr != PythonFrameIterator::end(), "no valid python frames??");
return fr;
}
static const LineInfo* lineInfoForFrame(const PythonFrameIterator& frame_it) {
auto& id = frame_it.getId();
switch (id.type) {
case PythonFrameId::COMPILED:
return frame_it.getCF()->line_table->getLineInfoFor(id.ip);
case PythonFrameId::INTERPRETED:
return getLineInfoForInterpretedFrame((void*)id.bp);
}
abort();
}
std::vector<const LineInfo*> getTracebackEntries() {
std::vector<const LineInfo*> entries;
for (auto& frame_info : unwindPythonFrames()) {
entries.push_back(lineInfoForFrame(frame_info));
}
std::reverse(entries.begin(), entries.end());
return entries;
}
const LineInfo* getMostRecentLineInfo() {
std::unique_ptr<PythonFrameIterator> frame = getTopPythonFrame();
return lineInfoForFrame(*frame);
}
CompiledFunction* getTopCompiledFunction() {
// TODO This is a bad way to do this...
const LineInfo* last_entry = getMostRecentLineInfo();
assert(last_entry->func.size());
CompiledFunction* cf = cfForMachineFunctionName(last_entry->func);
assert(cf);
return cf;
}
BoxedModule* getCurrentModule() {
return getTopCompiledFunction()->clfunc->source->parent_module;
}
llvm::JITEventListener* makeTracebacksListener() {
return new TracebacksEventListener();
}
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CODEGEN_UNWINDING_H
#define PYSTON_CODEGEN_UNWINDING_H
#include <unordered_map>
#include "codegen/codegen.h"
namespace pyston {
class LineTable {
public:
std::vector<std::pair<uint64_t, LineInfo> > entries;
const LineInfo* getLineInfoFor(uint64_t addr) {
for (int i = entries.size() - 1; i >= 0; i--) {
if (entries[i].first < addr)
return &entries[i].second;
}
abort();
}
};
std::vector<const LineInfo*> getTracebackEntries();
const LineInfo* getMostRecentLineInfo();
class BoxedModule;
BoxedModule* getCurrentModule();
CompiledFunction* getCFForAddress(uint64_t addr);
class BoxedDict;
BoxedDict* getLocals(bool only_user_visible);
}
#endif
......@@ -19,7 +19,9 @@
// over having them spread randomly in different files, this should probably be split again
// but in a way that makes more sense.
#include <memory>
#include <stddef.h>
#include <vector>
#include "llvm/ADT/iterator_range.h"
#include "Python.h"
......@@ -149,6 +151,9 @@ struct FunctionSpecialization {
class BoxedClosure;
class BoxedGenerator;
class LineTable;
class ICInfo;
struct CompiledFunction {
private:
public:
......@@ -164,7 +169,9 @@ public:
Box* (*closure_generator_call)(BoxedClosure*, BoxedGenerator*, Box*, Box*, Box*, Box**);
Box* (*generator_call)(BoxedGenerator*, Box*, Box*, Box*, Box**);
void* code;
uintptr_t code_start;
};
int code_size;
llvm::Value* llvm_code; // the llvm callable.
EffortLevel::EffortLevel effort;
......@@ -172,11 +179,19 @@ public:
int64_t times_called;
ICInvalidator dependent_callsites;
// Unfortunately, can't make this a std::unique_ptr if we want to forward-declare LineTable:
LineTable* line_table;
std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, bool is_interpreted, void* code,
llvm::Value* llvm_code, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL), func(func), spec(spec), entry_descriptor(entry_descriptor), is_interpreted(is_interpreted),
code(code), llvm_code(llvm_code), effort(effort), times_called(0) {}
code(code), llvm_code(llvm_code), effort(effort), times_called(0), line_table(nullptr) {}
// TODO this will need to be implemented eventually, and delete line_table if it exists
~CompiledFunction();
};
class BoxedModule;
......@@ -464,8 +479,6 @@ void teardownRuntime();
BoxedModule* createAndRunModule(const std::string& name, const std::string& fn);
BoxedModule* createModule(const std::string& name, const std::string& fn);
std::string getPythonFuncAt(void* ip, void* sp);
// TODO where to put this
void appendToSysPath(const std::string& path);
void prependToSysPath(const std::string& path);
......
......@@ -23,6 +23,7 @@
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "codegen/codegen.h"
#include "codegen/compvars.h"
#include "codegen/irgen/hooks.h"
#include "codegen/llvm_interpreter.h"
......
......@@ -18,9 +18,7 @@
#include "llvm/DebugInfo/DIContext.h"
#include "codegen/codegen.h"
#include "codegen/irgen/hooks.h"
#include "codegen/llvm_interpreter.h"
#include "codegen/unwinding.h"
#include "core/options.h"
#include "gc/collector.h"
#include "runtime/objmodel.h"
......@@ -45,11 +43,6 @@ void showBacktrace() {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf("ip = %lx, sp = %lx\n", (long)ip, (long)sp);
std::string py_info = getPythonFuncAt((void*)ip, (void*)sp);
if (py_info.size()) {
printf("Which is: %s\n", py_info.c_str());
}
}
}
......@@ -102,7 +95,6 @@ void unwindExc(Box* exc_obj) {
abort();
}
static std::vector<const LineInfo*> getTracebackEntries();
static gc::GCRootHandle last_exc;
static std::vector<const LineInfo*> last_tb;
......@@ -219,58 +211,6 @@ extern "C" void exit(int code) {
__builtin_unreachable();
}
static std::vector<const LineInfo*> getTracebackEntries() {
std::vector<const LineInfo*> entries;
unw_cursor_t cursor;
unw_context_t uc;
unw_word_t ip, bp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
int code;
unw_proc_info_t pip;
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
const LineInfo* line = getLineInfoFor((uint64_t)ip);
if (line) {
entries.push_back(line);
} else {
unw_get_reg(&cursor, UNW_TDEP_BP, &bp);
unw_proc_info_t pip;
code = unw_get_proc_info(&cursor, &pip);
RELEASE_ASSERT(code == 0, "%d", code);
if (pip.start_ip == (intptr_t)interpretFunction) {
line = getLineInfoForInterpretedFrame((void*)bp);
assert(line);
entries.push_back(line);
}
}
}
std::reverse(entries.begin(), entries.end());
return entries;
}
static const LineInfo* getMostRecentLineInfo() {
// TODO not very efficient, could stop after the first one:
return getTracebackEntries().back();
}
BoxedModule* getCurrentModule() {
const LineInfo* last_entry = getMostRecentLineInfo();
assert(last_entry->func.size());
CLFunction* cl = clFunctionForMachineFunctionName(last_entry->func);
assert(cl);
return cl->source->parent_module;
}
void raise0() {
raiseRaw(last_exc);
}
......
......@@ -123,18 +123,23 @@ def verify_include_order(_, dir, files):
sys.exit(1)
assert len(sections[0]) == len(set(sections[0]))
dbg = []
if sections and is_corresponding_header(sections[0]):
dbg.append("corresponding")
del sections[0]
if sections and is_system_section(sections[0]):
dbg.append("system")
check_sorted(sections[0])
del sections[0]
while sections and is_third_party_section(sections[0]):
dbg.append("3rdp")
check_sorted(sections[0])
del sections[0]
if sections and is_pyston_section(sections[0]):
dbg.append("pyston")
check_sorted(sections[0])
for incl in sections[0]:
if is_corresponding_header([incl]):
......@@ -151,6 +156,7 @@ def verify_include_order(_, dir, files):
print >>sys.stderr, "- Third party headers"
print >>sys.stderr, "- Pyston headers"
print >>sys.stderr, "There should be an extra line between sections but not within sections"
print >>sys.stderr, "\ndbg: %s" % dbg
sys.exit(1)
assert not sections, fn
......
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