Commit ca7765ac authored by Marius Wachtler's avatar Marius Wachtler

Add a cache for JITed object code.

We still need to generate the IR but if we can find,
a cache file created for the exact same IR we will load it and
skip instruction selection etc...
parent 982a0f59
...@@ -283,8 +283,12 @@ public: ...@@ -283,8 +283,12 @@ public:
assert(usage); assert(usage);
assert(ast); assert(ast);
// Sort the entries by name to make the order deterministic.
std::vector<InternedString> referenced_from_nested_sorted(usage->referenced_from_nested.begin(),
usage->referenced_from_nested.end());
std::sort(referenced_from_nested_sorted.begin(), referenced_from_nested_sorted.end());
int i = 0; int i = 0;
for (auto& p : usage->referenced_from_nested) { for (auto& p : referenced_from_nested_sorted) {
closure_offsets[p] = i; closure_offsets[p] = i;
i++; i++;
} }
......
...@@ -1555,6 +1555,27 @@ void* extractSlowpathFunc(uint8_t* pp_addr) { ...@@ -1555,6 +1555,27 @@ void* extractSlowpathFunc(uint8_t* pp_addr) {
return call_addr; return call_addr;
} }
void setSlowpathFunc(uint8_t* pp_addr, void* func) {
#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**)&pp_addr[2] = func;
}
std::pair<uint8_t*, uint8_t*> initializePatchpoint3(void* slowpath_func, uint8_t* start_addr, uint8_t* end_addr, std::pair<uint8_t*, uint8_t*> initializePatchpoint3(void* slowpath_func, uint8_t* start_addr, uint8_t* end_addr,
int scratch_offset, int scratch_size, int scratch_offset, int scratch_size,
const std::unordered_set<int>& live_outs, SpillMap& remapped) { const std::unordered_set<int>& live_outs, SpillMap& remapped) {
......
...@@ -476,6 +476,7 @@ public: ...@@ -476,6 +476,7 @@ public:
}; };
void* extractSlowpathFunc(uint8_t* pp_addr); void* extractSlowpathFunc(uint8_t* pp_addr);
void setSlowpathFunc(uint8_t* pp_addr, void* func);
struct GRCompare { struct GRCompare {
bool operator()(assembler::GenericRegister gr1, assembler::GenericRegister gr2) const { bool operator()(assembler::GenericRegister gr1, assembler::GenericRegister gr2) const {
......
...@@ -293,7 +293,8 @@ public: ...@@ -293,7 +293,8 @@ public:
llvm::Value* cls_value = emitter.getBuilder()->CreateLoad(cls_ptr); llvm::Value* cls_value = emitter.getBuilder()->CreateLoad(cls_ptr);
assert(cls_value->getType() == g.llvm_class_type_ptr); assert(cls_value->getType() == g.llvm_class_type_ptr);
llvm::Value* rtn = emitter.getBuilder()->CreateICmpEQ(cls_value, embedConstantPtr(cls, g.llvm_class_type_ptr)); llvm::Value* rtn
= emitter.getBuilder()->CreateICmpEQ(cls_value, embedRelocatablePtr(cls, g.llvm_class_type_ptr));
return rtn; return rtn;
} }
...@@ -367,8 +368,8 @@ public: ...@@ -367,8 +368,8 @@ public:
} }
// We don't know the type so we have to check at runtime if __iter__ is implemented // We don't know the type so we have to check at runtime if __iter__ is implemented
llvm::Value* cmp = emitter.getBuilder()->CreateICmpNE(converted_iter_call->getValue(), llvm::Value* cmp
embedConstantPtr(0, g.llvm_value_type_ptr)); = emitter.getBuilder()->CreateICmpNE(converted_iter_call->getValue(), getNullPtr(g.llvm_value_type_ptr));
llvm::BasicBlock* bb_has_iter = emitter.createBasicBlock("has_iter"); llvm::BasicBlock* bb_has_iter = emitter.createBasicBlock("has_iter");
bb_has_iter->moveAfter(emitter.currentBasicBlock()); bb_has_iter->moveAfter(emitter.currentBasicBlock());
...@@ -529,19 +530,19 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -529,19 +530,19 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
if (args.size() >= 1) { if (args.size() >= 1) {
llvm_args.push_back(converted_args[0]->getValue()); llvm_args.push_back(converted_args[0]->getValue());
} else if (pass_keyword_names) { } else if (pass_keyword_names) {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr)); llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr));
} }
if (args.size() >= 2) { if (args.size() >= 2) {
llvm_args.push_back(converted_args[1]->getValue()); llvm_args.push_back(converted_args[1]->getValue());
} else if (pass_keyword_names) { } else if (pass_keyword_names) {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr)); llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr));
} }
if (args.size() >= 3) { if (args.size() >= 3) {
llvm_args.push_back(converted_args[2]->getValue()); llvm_args.push_back(converted_args[2]->getValue());
} else if (pass_keyword_names) { } else if (pass_keyword_names) {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr)); llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr));
} }
llvm::Value* mallocsave = NULL; llvm::Value* mallocsave = NULL;
...@@ -569,10 +570,10 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -569,10 +570,10 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
llvm_args.push_back(arg_array); llvm_args.push_back(arg_array);
if (pass_keyword_names) if (pass_keyword_names)
llvm_args.push_back(embedConstantPtr(keyword_names, g.vector_ptr)); llvm_args.push_back(embedRelocatablePtr(keyword_names, g.vector_ptr));
} else if (pass_keyword_names) { } else if (pass_keyword_names) {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr->getPointerTo())); llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr->getPointerTo()));
llvm_args.push_back(embedConstantPtr(keyword_names, g.vector_ptr)); llvm_args.push_back(embedRelocatablePtr(keyword_names, g.vector_ptr));
} }
// f->dump(); // f->dump();
...@@ -683,7 +684,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info, ...@@ -683,7 +684,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
std::vector<llvm::Value*> other_args; std::vector<llvm::Value*> other_args;
other_args.push_back(var->getValue()); other_args.push_back(var->getValue());
other_args.push_back(embedConstantPtr(attr, g.llvm_str_type_ptr)); other_args.push_back(embedRelocatablePtr(attr, g.llvm_str_type_ptr));
other_args.push_back(getConstantInt(flags_to_int.value, g.i8)); other_args.push_back(getConstantInt(flags_to_int.value, g.i8));
llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false); llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false);
...@@ -737,7 +738,7 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab ...@@ -737,7 +738,7 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
convertedClosure = closure->makeConverted(emitter, closure->getConcreteType()); convertedClosure = closure->makeConverted(emitter, closure->getConcreteType());
closure_v = convertedClosure->getValue(); closure_v = convertedClosure->getValue();
} else { } else {
closure_v = embedConstantPtr(nullptr, g.llvm_closure_type_ptr); closure_v = getNullPtr(g.llvm_closure_type_ptr);
} }
llvm::Value* scratch; llvm::Value* scratch;
...@@ -752,20 +753,20 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab ...@@ -752,20 +753,20 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
i++; i++;
} }
} else { } else {
scratch = embedConstantPtr(nullptr, g.llvm_value_type_ptr_ptr); scratch = getNullPtr(g.llvm_value_type_ptr_ptr);
} }
llvm::Value* isGenerator_v = llvm::ConstantInt::get(g.i1, isGenerator, false); llvm::Value* isGenerator_v = llvm::ConstantInt::get(g.i1, isGenerator, false);
assert(globals == NULL); assert(globals == NULL);
llvm::Value* globals_v = embedConstantPtr(nullptr, g.llvm_dict_type_ptr); llvm::Value* globals_v = getNullPtr(g.llvm_dict_type_ptr);
// We know this function call can't throw, so it's safe to use emitter.getBuilder()->CreateCall() rather than // We know this function call can't throw, so it's safe to use emitter.getBuilder()->CreateCall() rather than
// emitter.createCall(). // emitter.createCall().
llvm::Value* boxed = emitter.getBuilder()->CreateCall( llvm::Value* boxed = emitter.getBuilder()->CreateCall(
g.funcs.boxCLFunction, g.funcs.boxCLFunction,
std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, globals_v, std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v,
scratch, getConstantInt(defaults.size(), g.i64) }); globals_v, scratch, getConstantInt(defaults.size(), g.i64) });
if (convertedClosure) if (convertedClosure)
convertedClosure->decvref(emitter); convertedClosure->decvref(emitter);
...@@ -1339,7 +1340,7 @@ ConcreteCompilerVariable* makeFloat(double d) { ...@@ -1339,7 +1340,7 @@ ConcreteCompilerVariable* makeFloat(double d) {
ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string& n_long) { ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string& n_long) {
llvm::Value* v llvm::Value* v
= emitter.getBuilder()->CreateCall(g.funcs.createLong, embedConstantPtr(&n_long, g.llvm_str_type_ptr)); = emitter.getBuilder()->CreateCall(g.funcs.createLong, embedRelocatablePtr(&n_long, g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(LONG, v, true); return new ConcreteCompilerVariable(LONG, v, true);
} }
...@@ -1481,7 +1482,7 @@ public: ...@@ -1481,7 +1482,7 @@ public:
ASSERT(rtattr, "%s.%s", debugName().c_str(), attr->c_str()); ASSERT(rtattr, "%s.%s", debugName().c_str(), attr->c_str());
if (rtattr->cls == function_cls) { if (rtattr->cls == function_cls) {
CompilerVariable* clattr = new ConcreteCompilerVariable( CompilerVariable* clattr = new ConcreteCompilerVariable(
typeFromClass(function_cls), embedConstantPtr(rtattr, g.llvm_value_type_ptr), false); typeFromClass(function_cls), embedRelocatablePtr(rtattr, g.llvm_value_type_ptr), false);
return InstanceMethodType::makeIM(var, clattr); return InstanceMethodType::makeIM(var, clattr);
} }
} }
...@@ -1587,7 +1588,11 @@ public: ...@@ -1587,7 +1588,11 @@ public:
} }
llvm::FunctionType* ft = llvm::FunctionType::get(cf->spec->rtn_type->llvmType(), arg_types, false); llvm::FunctionType* ft = llvm::FunctionType::get(cf->spec->rtn_type->llvmType(), arg_types, false);
llvm::Value* linked_function = embedConstantPtr(cf->code, ft->getPointerTo()); llvm::Value* linked_function;
if (cf->func) // for JITed functions we need to make the desination address relocatable.
linked_function = embedRelocatablePtr(cf->code, ft->getPointerTo());
else
linked_function = embedConstantPtr(cf->code, ft->getPointerTo());
std::vector<CompilerVariable*> new_args; std::vector<CompilerVariable*> new_args;
new_args.push_back(var); new_args.push_back(var);
...@@ -1595,10 +1600,14 @@ public: ...@@ -1595,10 +1600,14 @@ public:
for (int i = args.size() + 1; i < cl->num_args; i++) { for (int i = args.size() + 1; i < cl->num_args; i++) {
// TODO should _call() be able to take llvm::Value's directly? // TODO should _call() be able to take llvm::Value's directly?
new_args.push_back(new ConcreteCompilerVariable( auto value = rtattr_func->defaults->elts[i - cl->num_args + cl->num_defaults];
UNKNOWN, embedConstantPtr(rtattr_func->defaults->elts[i - cl->num_args + cl->num_defaults], llvm::Value* llvm_value;
g.llvm_value_type_ptr), if (value)
true)); llvm_value = embedRelocatablePtr(value, g.llvm_value_type_ptr);
else
llvm_value = getNullPtr(g.llvm_value_type_ptr);
new_args.push_back(new ConcreteCompilerVariable(UNKNOWN, llvm_value, true));
} }
std::vector<llvm::Value*> other_args; std::vector<llvm::Value*> other_args;
...@@ -1873,8 +1882,8 @@ public: ...@@ -1873,8 +1882,8 @@ public:
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override { ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override {
assert(other_type == STR || other_type == UNKNOWN); assert(other_type == STR || other_type == UNKNOWN);
llvm::Value* boxed = emitter.getBuilder()->CreateCall(g.funcs.boxStringPtr, llvm::Value* boxed = emitter.getBuilder()->CreateCall(
embedConstantPtr(var->getValue(), g.llvm_str_type_ptr)); g.funcs.boxStringPtr, embedRelocatablePtr(var->getValue(), g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(other_type, boxed, true); return new ConcreteCompilerVariable(other_type, boxed, true);
} }
...@@ -1928,7 +1937,7 @@ public: ...@@ -1928,7 +1937,7 @@ public:
} }
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override { void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override {
stackmap_args.push_back(embedConstantPtr(var->getValue(), g.i8_ptr)); stackmap_args.push_back(embedRelocatablePtr(var->getValue(), g.i8_ptr));
} }
Box* deserializeFromFrame(const FrameVals& vals) override { Box* deserializeFromFrame(const FrameVals& vals) override {
...@@ -1947,7 +1956,7 @@ CompilerVariable* makeStr(const std::string* s) { ...@@ -1947,7 +1956,7 @@ CompilerVariable* makeStr(const std::string* s) {
CompilerVariable* makeUnicode(IREmitter& emitter, const std::string* s) { CompilerVariable* makeUnicode(IREmitter& emitter, const std::string* s) {
llvm::Value* boxed llvm::Value* boxed
= emitter.getBuilder()->CreateCall(g.funcs.decodeUTF8StringPtr, embedConstantPtr(s, g.llvm_str_type_ptr)); = emitter.getBuilder()->CreateCall(g.funcs.decodeUTF8StringPtr, embedRelocatablePtr(s, g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(typeFromClass(unicode_cls), boxed, true); return new ConcreteCompilerVariable(typeFromClass(unicode_cls), boxed, true);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <openssl/evp.h>
#include <unordered_map> #include <unordered_map>
#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Passes.h"
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h" #include "llvm/Support/TargetSelect.h"
#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Cloning.h"
...@@ -118,54 +120,130 @@ static llvm::Module* loadStdlib() { ...@@ -118,54 +120,130 @@ static llvm::Module* loadStdlib() {
return m; return m;
} }
class MyObjectCache : public llvm::ObjectCache { class PystonObjectCache : public llvm::ObjectCache {
private: private:
bool loaded; // Stream which calculates the SHA256 hash of the data writen to.
class HashOStream : public llvm::raw_ostream {
EVP_MD_CTX* md_ctx;
void write_impl(const char* ptr, size_t size) override { EVP_DigestUpdate(md_ctx, ptr, size); }
uint64_t current_pos() const override { return 0; }
public:
HashOStream() {
md_ctx = EVP_MD_CTX_create();
RELEASE_ASSERT(md_ctx, "");
int ret = EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
RELEASE_ASSERT(ret == 1, "");
}
~HashOStream() { EVP_MD_CTX_destroy(md_ctx); }
std::string getHash() {
flush();
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len = 0;
int ret = EVP_DigestFinal_ex(md_ctx, md_value, &md_len);
RELEASE_ASSERT(ret == 1, "");
std::string str;
str.reserve(md_len * 2 + 1);
llvm::raw_string_ostream stream(str);
for (int i = 0; i < md_len; ++i)
stream.write_hex(md_value[i]);
return stream.str();
}
};
llvm::SmallString<128> cache_dir;
std::string module_identifier;
std::string hash_before_codegen;
public: public:
MyObjectCache() : loaded(false) {} PystonObjectCache() {
llvm::sys::fs::current_path(cache_dir);
llvm::sys::path::append(cache_dir, "pyston_object_cache");
}
#if LLVMREV < 216002 #if LLVMREV < 216002
virtual void notifyObjectCompiled(const llvm::Module* M, const llvm::MemoryBuffer* Obj) {} virtual void notifyObjectCompiled(const llvm::Module* M, const llvm::MemoryBuffer* Obj)
#else #else
virtual void notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj) {} virtual void notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj)
#endif #endif
{
RELEASE_ASSERT(module_identifier == M->getModuleIdentifier(), "");
RELEASE_ASSERT(!hash_before_codegen.empty(), "");
llvm::SmallString<128> cache_file = cache_dir;
llvm::sys::path::append(cache_file, hash_before_codegen);
if (!llvm::sys::fs::exists(cache_dir.str()) && llvm::sys::fs::create_directory(cache_dir.str())) {
fprintf(stderr, "Unable to create cache directory\n");
return;
}
std::error_code error_code;
llvm::raw_fd_ostream IRObjectFile(cache_file.c_str(), error_code, llvm::sys::fs::F_RW);
RELEASE_ASSERT(!error_code, "");
IRObjectFile << Obj.getBuffer();
}
#if LLVMREV < 215566 #if LLVMREV < 215566
virtual llvm::MemoryBuffer* getObject(const llvm::Module* M){ virtual llvm::MemoryBuffer* getObject(const llvm::Module* M)
#else #else
virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M) { virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M)
#endif #endif
assert(!loaded); {
loaded = true; static StatCounter jit_objectcache_hits("num_jit_objectcache_hits");
g.engine->setObjectCache(NULL); static StatCounter jit_objectcache_misses("num_jit_objectcache_misses");
std::unique_ptr<MyObjectCache> del_at_end(this);
module_identifier = M->getModuleIdentifier();
// Generate a hash for the module
HashOStream hash_stream;
M->print(hash_stream, 0);
hash_before_codegen = hash_stream.getHash();
llvm::SmallString<128> cache_file = cache_dir;
llvm::sys::path::append(cache_file, hash_before_codegen);
if (!llvm::sys::fs::exists(cache_file.str())) {
#if 0 #if 0
if (!USE_STRIPPED_STDLIB) { // This code helps with identifying why we got a cache miss for a file.
stajt = STDLIB_CACHE_START; // - clear the cache directory
size = (intptr_t)&STDLIB_CACHE_SIZE; // - run pyston
} else { // - run pyston a second time
start = STRIPPED_STDLIB_CACHE_START; // - Now look for "*_second" files in the cache directory and compare them to the "*_first" IR dump
size = (intptr_t)&STRIPPED_STDLIB_CACHE_SIZE; std::string llvm_ir;
} llvm::raw_string_ostream sstr(llvm_ir);
#else M->print(sstr, 0);
RELEASE_ASSERT(0, ""); sstr.flush();
char* start = NULL;
intptr_t size = 0; std::string filename = cache_dir.str().str() + "/" + module_identifier + "_first";
if (llvm::sys::fs::exists(filename))
filename = cache_dir.str().str() + "/" + module_identifier + "_second";
FILE* f = fopen(filename.c_str(), "wt");
fwrite(llvm_ir.c_str(), 1, llvm_ir.size(), f);
fclose(f);
#endif #endif
// Make sure the stdlib got linked in correctly; check the magic number at the beginning: // This file isn't in our cache
assert(start[0] == 0x7f); jit_objectcache_misses.log();
assert(start[1] == 'E'); return NULL;
assert(start[2] == 'L'); }
assert(start[3] == 'F');
assert(size > 0 && size < 1 << 30); // make sure the size is being loaded correctly auto rtn = llvm::MemoryBuffer::getFile(cache_file.str(), -1, false);
if (!rtn) {
jit_objectcache_misses.log();
return NULL;
}
llvm::StringRef data(start, size); jit_objectcache_hits.log();
return llvm::MemoryBuffer::getMemBufferCopy(data, "");
} // MCJIT will want to write into this buffer, and we don't want that
// because the file has probably just been mmapped. Instead we make
// a copy. The filed-based buffer will be released when it goes
// out of scope.
return llvm::MemoryBuffer::getMemBufferCopy((*rtn)->getBuffer());
}
}; };
static void handle_sigusr1(int signum) { static void handle_sigusr1(int signum) {
...@@ -223,7 +301,8 @@ void initCodegen() { ...@@ -223,7 +301,8 @@ void initCodegen() {
g.engine = eb.create(g.tm); g.engine = eb.create(g.tm);
assert(g.engine && "engine creation failed?"); assert(g.engine && "engine creation failed?");
// g.engine->setObjectCache(new MyObjectCache()); if (ENABLE_JIT_OBJECT_CACHE)
g.engine->setObjectCache(new PystonObjectCache());
g.i1 = llvm::Type::getInt1Ty(g.context); g.i1 = llvm::Type::getInt1Ty(g.context);
g.i8 = llvm::Type::getInt8Ty(g.context); g.i8 = llvm::Type::getInt8Ty(g.context);
......
...@@ -541,7 +541,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -541,7 +541,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction()); llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction());
emitter->getBuilder()->SetInsertPoint(preentry_bb); emitter->getBuilder()->SetInsertPoint(preentry_bb);
llvm::Value* call_count_ptr = embedConstantPtr(&cf->times_called, g.i64->getPointerTo()); llvm::Value* call_count_ptr = embedRelocatablePtr(&cf->times_called, g.i64->getPointerTo());
llvm::Value* cur_call_count = emitter->getBuilder()->CreateLoad(call_count_ptr); llvm::Value* cur_call_count = emitter->getBuilder()->CreateLoad(call_count_ptr);
llvm::Value* new_call_count llvm::Value* new_call_count
= emitter->getBuilder()->CreateAdd(cur_call_count, getConstantInt(1, g.i64)); = emitter->getBuilder()->CreateAdd(cur_call_count, getConstantInt(1, g.i64));
...@@ -569,7 +569,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -569,7 +569,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
emitter->getBuilder()->SetInsertPoint(reopt_bb); emitter->getBuilder()->SetInsertPoint(reopt_bb);
// emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1)); // emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1));
llvm::Value* r = emitter->getBuilder()->CreateCall(g.funcs.reoptCompiledFunc, llvm::Value* r = emitter->getBuilder()->CreateCall(g.funcs.reoptCompiledFunc,
embedConstantPtr(cf, g.i8->getPointerTo())); embedRelocatablePtr(cf, g.i8->getPointerTo()));
assert(r); assert(r);
assert(r->getType() == g.i8->getPointerTo()); assert(r->getType() == g.i8->getPointerTo());
...@@ -739,6 +739,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -739,6 +739,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// NB. This is where most `typical' phi nodes get added. // NB. This is where most `typical' phi nodes get added.
// And go through and add phi nodes: // And go through and add phi nodes:
ConcreteSymbolTable* pred_st = phi_ending_symbol_tables[pred]; ConcreteSymbolTable* pred_st = phi_ending_symbol_tables[pred];
for (auto it = pred_st->begin(); it != pred_st->end(); ++it) { for (auto it = pred_st->begin(); it != pred_st->end(); ++it) {
InternedString name = it->first; InternedString name = it->first;
ConcreteCompilerVariable* cv = it->second; // incoming CCV from predecessor block ConcreteCompilerVariable* cv = it->second; // incoming CCV from predecessor block
...@@ -959,6 +960,9 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O ...@@ -959,6 +960,9 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
source->cfg->print(); source->cfg->print();
assert(g.cur_module == NULL); assert(g.cur_module == NULL);
clearRelocatableSymsMap();
std::string name = getUniqueFunctionName(nameprefix, effort, entry_descriptor); std::string name = getUniqueFunctionName(nameprefix, effort, entry_descriptor);
g.cur_module = new llvm::Module(name, g.context); g.cur_module = new llvm::Module(name, g.context);
#if LLVMREV < 217070 // not sure if this is the right rev #if LLVMREV < 217070 // not sure if this is the right rev
...@@ -1010,7 +1014,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O ...@@ -1010,7 +1014,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
CompiledFunction* cf CompiledFunction* cf
= new CompiledFunction(NULL, spec, (effort == EffortLevel::INTERPRETED), NULL, NULL, effort, entry_descriptor); = new CompiledFunction(NULL, spec, (effort == EffortLevel::INTERPRETED), NULL, effort, entry_descriptor);
llvm::FunctionType* ft = llvm::FunctionType::get(cf->getReturnType()->llvmType(), llvm_arg_types, false /*vararg*/); llvm::FunctionType* ft = llvm::FunctionType::get(cf->getReturnType()->llvmType(), llvm_arg_types, false /*vararg*/);
......
...@@ -156,8 +156,6 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) { ...@@ -156,8 +156,6 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) {
assert(compiled); assert(compiled);
ASSERT(compiled == cf->code, "cf->code should have gotten filled in"); ASSERT(compiled == cf->code, "cf->code should have gotten filled in");
cf->llvm_code = embedConstantPtr(compiled, cf->func->getType());
long us = _t.end(); long us = _t.end();
static StatCounter us_jitting("us_compiling_jitting"); static StatCounter us_jitting("us_compiling_jitting");
us_jitting.log(us); us_jitting.log(us);
...@@ -243,7 +241,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E ...@@ -243,7 +241,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
CompiledFunction* cf = 0; CompiledFunction* cf = 0;
if (effort == EffortLevel::INTERPRETED) { if (effort == EffortLevel::INTERPRETED) {
assert(!entry_descriptor); assert(!entry_descriptor);
cf = new CompiledFunction(0, spec, true, NULL, NULL, effort, 0); cf = new CompiledFunction(0, spec, true, NULL, effort, 0);
} else { } else {
cf = doCompile(source, &f->param_names, entry_descriptor, effort, spec, name); cf = doCompile(source, &f->param_names, entry_descriptor, effort, spec, name);
compileIR(cf, effort); compileIR(cf, effort);
...@@ -651,21 +649,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, ...@@ -651,21 +649,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
#endif #endif
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types); FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
cl_f->addVersion(new CompiledFunction(NULL, spec, false, f, EffortLevel::MAXIMAL, NULL));
std::vector<llvm::Type*> llvm_arg_types;
int npassed_args = arg_types.size();
assert(npassed_args == cl_f->numReceivedArgs());
for (int i = 0; i < npassed_args; i++) {
if (i == 3) {
llvm_arg_types.push_back(g.i8_ptr->getPointerTo());
break;
}
llvm_arg_types.push_back(arg_types[i]->llvmType());
}
llvm::FunctionType* ft = llvm::FunctionType::get(g.llvm_value_type_ptr, llvm_arg_types, false);
cl_f->addVersion(new CompiledFunction(NULL, spec, false, f, embedConstantPtr(f, ft->getPointerTo()),
EffortLevel::MAXIMAL, NULL));
} }
} }
...@@ -159,11 +159,11 @@ llvm::Value* IRGenState::getFrameInfoVar() { ...@@ -159,11 +159,11 @@ llvm::Value* IRGenState::getFrameInfoVar() {
// The "normal" case // The "normal" case
// frame_info.exc.type = NULL // frame_info.exc.type = NULL
builder.CreateStore(embedConstantPtr(NULL, g.llvm_value_type_ptr), getExcinfoGep(builder, al)); builder.CreateStore(getNullPtr(g.llvm_value_type_ptr), getExcinfoGep(builder, al));
// frame_info.boxedLocals = NULL // frame_info.boxedLocals = NULL
llvm::Value* boxed_locals_gep = getBoxedLocalsGep(builder, al); llvm::Value* boxed_locals_gep = getBoxedLocalsGep(builder, al);
builder.CreateStore(embedConstantPtr(NULL, g.llvm_value_type_ptr), boxed_locals_gep); builder.CreateStore(getNullPtr(g.llvm_value_type_ptr), boxed_locals_gep);
if (getScopeInfo()->usesNameLookup()) { if (getScopeInfo()->usesNameLookup()) {
// frame_info.boxedLocals = createDict() // frame_info.boxedLocals = createDict()
...@@ -175,7 +175,7 @@ llvm::Value* IRGenState::getFrameInfoVar() { ...@@ -175,7 +175,7 @@ llvm::Value* IRGenState::getFrameInfoVar() {
// frame_info.frame_obj = NULL // frame_info.frame_obj = NULL
static llvm::Type* llvm_frame_obj_type_ptr static llvm::Type* llvm_frame_obj_type_ptr
= llvm::cast<llvm::StructType>(g.llvm_frame_info_type)->getElementType(2); = llvm::cast<llvm::StructType>(g.llvm_frame_info_type)->getElementType(2);
builder.CreateStore(embedConstantPtr(NULL, llvm_frame_obj_type_ptr), getFrameObjGep(builder, al)); builder.CreateStore(getNullPtr(llvm_frame_obj_type_ptr), getFrameObjGep(builder, al));
this->frame_info = al; this->frame_info = al;
} }
...@@ -229,14 +229,33 @@ private: ...@@ -229,14 +229,33 @@ private:
if (pp == NULL) if (pp == NULL)
assert(ic_stackmap_args.size() == 0); assert(ic_stackmap_args.size() == 0);
PatchpointInfo* info = PatchpointInfo::create(currentFunction(), pp, ic_stackmap_args.size()); // Retrieve address of called function, currently handles the IR
int64_t pp_id = reinterpret_cast<int64_t>(info); // embedConstantPtr() and embedRelocatablePtr() create.
void* func_addr = nullptr;
if (llvm::isa<llvm::ConstantExpr>(func)) {
llvm::ConstantExpr* cast = llvm::cast<llvm::ConstantExpr>(func);
auto opcode = cast->getOpcode();
if (opcode == llvm::Instruction::IntToPtr) {
auto operand = cast->getOperand(0);
if (llvm::isa<llvm::ConstantInt>(operand))
func_addr = (void*)llvm::cast<llvm::ConstantInt>(operand)->getZExtValue();
}
}
assert(func_addr);
PatchpointInfo* info = PatchpointInfo::create(currentFunction(), pp, ic_stackmap_args.size(), func_addr);
int64_t pp_id = info->getId();
int pp_size = pp ? pp->totalSize() : CALL_ONLY_SIZE; int pp_size = pp ? pp->totalSize() : CALL_ONLY_SIZE;
std::vector<llvm::Value*> pp_args; std::vector<llvm::Value*> pp_args;
pp_args.push_back(getConstantInt(pp_id, g.i64)); // pp_id: will fill this in later pp_args.push_back(getConstantInt(pp_id, g.i64)); // pp_id: will fill this in later
pp_args.push_back(getConstantInt(pp_size, g.i32)); pp_args.push_back(getConstantInt(pp_size, g.i32));
pp_args.push_back(func); if (ENABLE_JIT_OBJECT_CACHE)
// add fixed dummy dest pointer, we will replace it with the correct address during stackmap processing
pp_args.push_back(embedConstantPtr((void*)-1L, g.i8_ptr));
else
pp_args.push_back(func);
pp_args.push_back(getConstantInt(args.size(), g.i32)); pp_args.push_back(getConstantInt(args.size(), g.i32));
pp_args.insert(pp_args.end(), args.begin(), args.end()); pp_args.insert(pp_args.end(), args.begin(), args.end());
...@@ -452,7 +471,7 @@ private: ...@@ -452,7 +471,7 @@ private:
curblock = deopt_bb; curblock = deopt_bb;
emitter.getBuilder()->SetInsertPoint(curblock); emitter.getBuilder()->SetInsertPoint(curblock);
llvm::Value* v = emitter.createCall2(UnwindInfo(current_statement, NULL), g.funcs.deopt, llvm::Value* v = emitter.createCall2(UnwindInfo(current_statement, NULL), g.funcs.deopt,
embedConstantPtr(node, g.i8->getPointerTo()), node_value); embedRelocatablePtr(node, g.i8->getPointerTo()), node_value);
emitter.getBuilder()->CreateRet(v); emitter.getBuilder()->CreateRet(v);
curblock = success_bb; curblock = success_bb;
...@@ -509,13 +528,17 @@ private: ...@@ -509,13 +528,17 @@ private:
assert(personality_func); assert(personality_func);
llvm::LandingPadInst* landing_pad = emitter.getBuilder()->CreateLandingPad( llvm::LandingPadInst* landing_pad = emitter.getBuilder()->CreateLandingPad(
llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 }), personality_func, 1); llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 }), personality_func, 1);
landing_pad->addClause(embedConstantPtr(NULL, g.i8_ptr)); landing_pad->addClause(getNullPtr(g.i8_ptr));
llvm::Value* cxaexc_pointer = emitter.getBuilder()->CreateExtractValue(landing_pad, { 0 }); llvm::Value* cxaexc_pointer = emitter.getBuilder()->CreateExtractValue(landing_pad, { 0 });
if (irstate->getEffortLevel() != EffortLevel::INTERPRETED) { if (irstate->getEffortLevel() != EffortLevel::INTERPRETED) {
llvm::Value* excinfo_pointer llvm::Function* std_module_catch = g.stdlib_module->getFunction("__cxa_begin_catch");
= emitter.getBuilder()->CreateCall(g.funcs.__cxa_begin_catch, cxaexc_pointer); auto begin_catch_func = g.cur_module->getOrInsertFunction(std_module_catch->getName(),
std_module_catch->getFunctionType());
assert(begin_catch_func);
llvm::Value* excinfo_pointer = emitter.getBuilder()->CreateCall(begin_catch_func, cxaexc_pointer);
llvm::Value* excinfo_pointer_casted llvm::Value* excinfo_pointer_casted
= emitter.getBuilder()->CreateBitCast(excinfo_pointer, g.llvm_excinfo_type->getPointerTo()); = emitter.getBuilder()->CreateBitCast(excinfo_pointer, g.llvm_excinfo_type->getPointerTo());
...@@ -567,7 +590,7 @@ private: ...@@ -567,7 +590,7 @@ private:
assert(name.size()); assert(name.size());
llvm::Value* r = emitter.createCall2(unw_info, g.funcs.importFrom, converted_module->getValue(), llvm::Value* r = emitter.createCall2(unw_info, g.funcs.importFrom, converted_module->getValue(),
embedConstantPtr(&name, g.llvm_str_type_ptr)); embedRelocatablePtr(&name, g.llvm_str_type_ptr));
CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true); CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true);
...@@ -585,9 +608,8 @@ private: ...@@ -585,9 +608,8 @@ private:
ConcreteCompilerVariable* converted_module = module->makeConverted(emitter, module->getBoxType()); ConcreteCompilerVariable* converted_module = module->makeConverted(emitter, module->getBoxType());
module->decvref(emitter); module->decvref(emitter);
llvm::Value* r = emitter.createCall2( llvm::Value* r = emitter.createCall2(unw_info, g.funcs.importStar, converted_module->getValue(),
unw_info, g.funcs.importStar, converted_module->getValue(), embedParentModulePtr());
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr));
CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true); CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true);
converted_module->decvref(emitter); converted_module->decvref(emitter);
...@@ -612,7 +634,7 @@ private: ...@@ -612,7 +634,7 @@ private:
llvm::Value* imported = emitter.createCall3(unw_info, g.funcs.import, getConstantInt(level, g.i32), llvm::Value* imported = emitter.createCall3(unw_info, g.funcs.import, getConstantInt(level, g.i32),
converted_froms->getValue(), converted_froms->getValue(),
embedConstantPtr(&module_name, g.llvm_str_type_ptr)); embedRelocatablePtr(&module_name, g.llvm_str_type_ptr));
ConcreteCompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, imported, true); ConcreteCompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, imported, true);
converted_froms->decvref(emitter); converted_froms->decvref(emitter);
...@@ -671,7 +693,7 @@ private: ...@@ -671,7 +693,7 @@ private:
llvm::Value* exc_info = builder->CreateConstInBoundsGEP2_32(frame_info, 0, 0); llvm::Value* exc_info = builder->CreateConstInBoundsGEP2_32(frame_info, 0, 0);
assert(exc_info->getType() == g.llvm_excinfo_type->getPointerTo()); assert(exc_info->getType() == g.llvm_excinfo_type->getPointerTo());
llvm::Constant* v = embedConstantPtr(0, g.llvm_value_type_ptr); llvm::Constant* v = getNullPtr(g.llvm_value_type_ptr);
builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 0)); builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 0));
builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 1)); builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 1));
builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 2)); builder->CreateStore(v, builder->CreateConstInBoundsGEP2_32(exc_info, 0, 2));
...@@ -889,10 +911,15 @@ private: ...@@ -889,10 +911,15 @@ private:
ConcreteCompilerVariable* getNone() { ConcreteCompilerVariable* getNone() {
ConcreteCompilerVariable* v = new ConcreteCompilerVariable( ConcreteCompilerVariable* v = new ConcreteCompilerVariable(
typeFromClass(none_cls), embedConstantPtr(None, g.llvm_value_type_ptr), false); typeFromClass(none_cls), embedRelocatablePtr(None, g.llvm_value_type_ptr), false);
return v; return v;
} }
llvm::Constant* embedParentModulePtr() {
// TODO: We could reuse the name to reduce the number of relocatable pointers.
return embedRelocatablePtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr);
}
ConcreteCompilerVariable* _getGlobal(AST_Name* node, UnwindInfo unw_info) { ConcreteCompilerVariable* _getGlobal(AST_Name* node, UnwindInfo unw_info) {
if (node->id.str() == "None") if (node->id.str() == "None")
return getNone(); return getNone();
...@@ -902,17 +929,15 @@ private: ...@@ -902,17 +929,15 @@ private:
ICSetupInfo* pp = createGetGlobalIC(getOpInfoForNode(node, unw_info).getTypeRecorder()); ICSetupInfo* pp = createGetGlobalIC(getOpInfoForNode(node, unw_info).getTypeRecorder());
std::vector<llvm::Value*> llvm_args; std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr)); llvm_args.push_back(embedParentModulePtr());
llvm_args.push_back(embedConstantPtr(&node->id.str(), g.llvm_str_type_ptr)); llvm_args.push_back(embedRelocatablePtr(&node->id.str(), g.llvm_str_type_ptr));
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::getGlobal, llvm_args, unw_info); llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::getGlobal, llvm_args, unw_info);
llvm::Value* r = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr); llvm::Value* r = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
return new ConcreteCompilerVariable(UNKNOWN, r, true); return new ConcreteCompilerVariable(UNKNOWN, r, true);
} else { } else {
llvm::Value* r llvm::Value* r = emitter.createCall2(unw_info, g.funcs.getGlobal, embedParentModulePtr(),
= emitter.createCall2(unw_info, g.funcs.getGlobal, embedRelocatablePtr(&node->id.str(), g.llvm_str_type_ptr));
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr),
embedConstantPtr(&node->id.str(), g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, r, true); return new ConcreteCompilerVariable(UNKNOWN, r, true);
} }
} }
...@@ -959,7 +984,7 @@ private: ...@@ -959,7 +984,7 @@ private:
= llvm::BasicBlock::Create(g.context, "deref_undefined", irstate->getLLVMFunction()); = llvm::BasicBlock::Create(g.context, "deref_undefined", irstate->getLLVMFunction());
llvm::Value* check_val llvm::Value* check_val
= emitter.getBuilder()->CreateICmpEQ(lookupResult, embedConstantPtr(NULL, g.llvm_value_type_ptr)); = emitter.getBuilder()->CreateICmpEQ(lookupResult, getNullPtr(g.llvm_value_type_ptr));
llvm::BranchInst* non_null_check = emitter.getBuilder()->CreateCondBr(check_val, fail_bb, success_bb); llvm::BranchInst* non_null_check = emitter.getBuilder()->CreateCondBr(check_val, fail_bb, success_bb);
// Case that it is undefined: call the assert fail function. // Case that it is undefined: call the assert fail function.
...@@ -979,7 +1004,7 @@ private: ...@@ -979,7 +1004,7 @@ private:
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
llvm::Value* boxedLocals = irstate->getBoxedLocalsVar(); llvm::Value* boxedLocals = irstate->getBoxedLocalsVar();
llvm::Value* attr = getStringConstantPtr(node->id.str() + '\0'); llvm::Value* attr = getStringConstantPtr(node->id.str() + '\0');
llvm::Value* module = embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr); llvm::Value* module = embedParentModulePtr();
llvm::Value* r = emitter.createCall3(unw_info, g.funcs.boxedLocalsGet, boxedLocals, attr, module); llvm::Value* r = emitter.createCall3(unw_info, g.funcs.boxedLocalsGet, boxedLocals, attr, module);
return new ConcreteCompilerVariable(UNKNOWN, r, true); return new ConcreteCompilerVariable(UNKNOWN, r, true);
} else { } else {
...@@ -990,7 +1015,7 @@ private: ...@@ -990,7 +1015,7 @@ private:
llvm::CallSite call = emitter.createCall( llvm::CallSite call = emitter.createCall(
unw_info, g.funcs.assertNameDefined, unw_info, g.funcs.assertNameDefined,
{ getConstantInt(0, g.i1), getStringConstantPtr(node->id.str() + '\0'), { getConstantInt(0, g.i1), getStringConstantPtr(node->id.str() + '\0'),
embedConstantPtr(UnboundLocalError, g.llvm_class_type_ptr), getConstantInt(true, g.i1) }); embedRelocatablePtr(UnboundLocalError, g.llvm_class_type_ptr), getConstantInt(true, g.i1) });
call.setDoesNotReturn(); call.setDoesNotReturn();
return undefVariable(); return undefVariable();
} }
...@@ -1002,7 +1027,7 @@ private: ...@@ -1002,7 +1027,7 @@ private:
if (is_defined_var) { if (is_defined_var) {
emitter.createCall(unw_info, g.funcs.assertNameDefined, emitter.createCall(unw_info, g.funcs.assertNameDefined,
{ i1FromBool(emitter, is_defined_var), getStringConstantPtr(node->id.str() + '\0'), { i1FromBool(emitter, is_defined_var), getStringConstantPtr(node->id.str() + '\0'),
embedConstantPtr(UnboundLocalError, g.llvm_class_type_ptr), embedRelocatablePtr(UnboundLocalError, g.llvm_class_type_ptr),
getConstantInt(true, g.i1) }); getConstantInt(true, g.i1) });
// At this point we know the name must be defined (otherwise the assert would have fired): // At this point we know the name must be defined (otherwise the assert would have fired):
...@@ -1108,7 +1133,7 @@ private: ...@@ -1108,7 +1133,7 @@ private:
CompilerVariable* evalStr(AST_Str* node, UnwindInfo unw_info) { CompilerVariable* evalStr(AST_Str* node, UnwindInfo unw_info) {
if (node->str_type == AST_Str::STR) { if (node->str_type == AST_Str::STR) {
llvm::Value* rtn = embedConstantPtr( llvm::Value* rtn = embedRelocatablePtr(
irstate->getSourceInfo()->parent_module->getStringConstant(node->str_data), g.llvm_value_type_ptr); irstate->getSourceInfo()->parent_module->getStringConstant(node->str_data), g.llvm_value_type_ptr);
return new ConcreteCompilerVariable(STR, rtn, true); return new ConcreteCompilerVariable(STR, rtn, true);
...@@ -1239,7 +1264,7 @@ private: ...@@ -1239,7 +1264,7 @@ private:
attr_dict->decvref(emitter); attr_dict->decvref(emitter);
llvm::Value* classobj = emitter.createCall3(unw_info, g.funcs.createUserClass, llvm::Value* classobj = emitter.createCall3(unw_info, g.funcs.createUserClass,
embedConstantPtr(&node->name.str(), g.llvm_str_type_ptr), embedRelocatablePtr(&node->name.str(), g.llvm_str_type_ptr),
bases_tuple->getValue(), converted_attr_dict->getValue()); bases_tuple->getValue(), converted_attr_dict->getValue());
// Note: createuserClass is free to manufacture non-class objects // Note: createuserClass is free to manufacture non-class objects
...@@ -1502,8 +1527,8 @@ private: ...@@ -1502,8 +1527,8 @@ private:
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
// TODO do something special here so that it knows to only emit a monomorphic inline cache? // TODO do something special here so that it knows to only emit a monomorphic inline cache?
ConcreteCompilerVariable* module = new ConcreteCompilerVariable( auto parent_module = llvm::ConstantExpr::getPointerCast(embedParentModulePtr(), g.llvm_value_type_ptr);
MODULE, embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_value_type_ptr), false); ConcreteCompilerVariable* module = new ConcreteCompilerVariable(MODULE, parent_module, false);
module->setattr(emitter, getEmptyOpInfo(unw_info), &name.str(), val); module->setattr(emitter, getEmptyOpInfo(unw_info), &name.str(), val);
module->decvref(emitter); module->decvref(emitter);
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
...@@ -1627,7 +1652,7 @@ private: ...@@ -1627,7 +1652,7 @@ private:
assert(num->n_int == 0); assert(num->n_int == 0);
std::vector<llvm::Value*> llvm_args; std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr)); llvm_args.push_back(embedParentModulePtr());
ConcreteCompilerVariable* converted_msg = NULL; ConcreteCompilerVariable* converted_msg = NULL;
if (node->msg) { if (node->msg) {
...@@ -1636,7 +1661,7 @@ private: ...@@ -1636,7 +1661,7 @@ private:
msg->decvref(emitter); msg->decvref(emitter);
llvm_args.push_back(converted_msg->getValue()); llvm_args.push_back(converted_msg->getValue());
} else { } else {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr)); llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr));
} }
llvm::CallSite call = emitter.createCall(unw_info, g.funcs.assertFail, llvm_args); llvm::CallSite call = emitter.createCall(unw_info, g.funcs.assertFail, llvm_args);
call.setDoesNotReturn(); call.setDoesNotReturn();
...@@ -1707,9 +1732,8 @@ private: ...@@ -1707,9 +1732,8 @@ private:
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
// Can't use delattr since the errors are different: // Can't use delattr since the errors are different:
emitter.createCall2(unw_info, g.funcs.delGlobal, emitter.createCall2(unw_info, g.funcs.delGlobal, embedParentModulePtr(),
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr), embedRelocatablePtr(&target->id.str(), g.llvm_str_type_ptr));
embedConstantPtr(&target->id.str(), g.llvm_str_type_ptr));
return; return;
} }
...@@ -1725,10 +1749,11 @@ private: ...@@ -1725,10 +1749,11 @@ private:
assert(vst == ScopeInfo::VarScopeType::FAST); assert(vst == ScopeInfo::VarScopeType::FAST);
if (symbol_table.count(target->id) == 0) { if (symbol_table.count(target->id) == 0) {
llvm::CallSite call = emitter.createCall( llvm::CallSite call
unw_info, g.funcs.assertNameDefined, = emitter.createCall(unw_info, g.funcs.assertNameDefined,
{ getConstantInt(0, g.i1), getStringConstantPtr(target->id.str() + '\0'), { getConstantInt(0, g.i1), getStringConstantPtr(target->id.str() + '\0'),
embedConstantPtr(NameError, g.llvm_class_type_ptr), getConstantInt(true /*local_error_msg*/, g.i1) }); embedRelocatablePtr(NameError, g.llvm_class_type_ptr),
getConstantInt(true /*local_error_msg*/, g.i1) });
call.setDoesNotReturn(); call.setDoesNotReturn();
return; return;
} }
...@@ -1739,7 +1764,7 @@ private: ...@@ -1739,7 +1764,7 @@ private:
if (is_defined_var) { if (is_defined_var) {
emitter.createCall(unw_info, g.funcs.assertNameDefined, emitter.createCall(unw_info, g.funcs.assertNameDefined,
{ i1FromBool(emitter, is_defined_var), getStringConstantPtr(target->id.str() + '\0'), { i1FromBool(emitter, is_defined_var), getStringConstantPtr(target->id.str() + '\0'),
embedConstantPtr(NameError, g.llvm_class_type_ptr), embedRelocatablePtr(NameError, g.llvm_class_type_ptr),
getConstantInt(true /*local_error_msg*/, g.i1) }); getConstantInt(true /*local_error_msg*/, g.i1) });
_popFake(defined_name); _popFake(defined_name);
} }
...@@ -1758,7 +1783,7 @@ private: ...@@ -1758,7 +1783,7 @@ private:
vglobals = globals->makeConverted(emitter, globals->getBoxType())->getValue(); vglobals = globals->makeConverted(emitter, globals->getBoxType())->getValue();
globals->decvref(emitter); globals->decvref(emitter);
} else { } else {
vglobals = embedConstantPtr(NULL, g.llvm_value_type_ptr); vglobals = getNullPtr(g.llvm_value_type_ptr);
} }
llvm::Value* vlocals; llvm::Value* vlocals;
...@@ -1767,7 +1792,7 @@ private: ...@@ -1767,7 +1792,7 @@ private:
vlocals = locals->makeConverted(emitter, locals->getBoxType())->getValue(); vlocals = locals->makeConverted(emitter, locals->getBoxType())->getValue();
locals->decvref(emitter); locals->decvref(emitter);
} else { } else {
vlocals = embedConstantPtr(NULL, g.llvm_value_type_ptr); vlocals = getNullPtr(g.llvm_value_type_ptr);
} }
emitter.createCall3(unw_info, g.funcs.exec, vbody, vglobals, vlocals); emitter.createCall3(unw_info, g.funcs.exec, vbody, vglobals, vlocals);
...@@ -1855,7 +1880,7 @@ private: ...@@ -1855,7 +1880,7 @@ private:
return; return;
} }
val = new ConcreteCompilerVariable(NONE, embedConstantPtr(None, g.llvm_value_type_ptr), false); val = getNone();
} else { } else {
val = evalExpr(node->value, unw_info); val = evalExpr(node->value, unw_info);
} }
...@@ -1950,7 +1975,7 @@ private: ...@@ -1950,7 +1975,7 @@ private:
OSREntryDescriptor* entry = OSREntryDescriptor::create(irstate->getCurFunction(), osr_key); OSREntryDescriptor* entry = OSREntryDescriptor::create(irstate->getCurFunction(), osr_key);
OSRExit* exit = new OSRExit(irstate->getCurFunction(), entry); OSRExit* exit = new OSRExit(irstate->getCurFunction(), entry);
llvm::Value* partial_func = emitter.getBuilder()->CreateCall(g.funcs.compilePartialFunc, llvm::Value* partial_func = emitter.getBuilder()->CreateCall(g.funcs.compilePartialFunc,
embedConstantPtr(exit, g.i8->getPointerTo())); embedRelocatablePtr(exit, g.i8->getPointerTo()));
std::vector<llvm::Value*> llvm_args; std::vector<llvm::Value*> llvm_args;
std::vector<llvm::Type*> llvm_arg_types; std::vector<llvm::Type*> llvm_arg_types;
...@@ -2125,7 +2150,7 @@ private: ...@@ -2125,7 +2150,7 @@ private:
v->decvref(emitter); v->decvref(emitter);
args.push_back(converted->getValue()); args.push_back(converted->getValue());
} else { } else {
args.push_back(embedConstantPtr(None, g.llvm_value_type_ptr)); args.push_back(embedRelocatablePtr(None, g.llvm_value_type_ptr));
} }
} }
...@@ -2332,7 +2357,17 @@ public: ...@@ -2332,7 +2357,17 @@ public:
stackmap_args.push_back(irstate->getFrameInfoVar()); 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)); if (ENABLE_JIT_OBJECT_CACHE) {
llvm::Value* v;
if (current_stmt)
v = emitter.getBuilder()->CreatePtrToInt(embedRelocatablePtr(current_stmt, g.i8_ptr), g.i64);
else
v = getConstantInt(0, g.i64);
stackmap_args.push_back(v);
} else {
stackmap_args.push_back(getConstantInt((uint64_t)current_stmt, g.i64));
}
pp->addFrameVar("!current_stmt", INT); pp->addFrameVar("!current_stmt", INT);
if (ENABLE_FRAME_INTROSPECTION) { if (ENABLE_FRAME_INTROSPECTION) {
...@@ -2469,7 +2504,7 @@ public: ...@@ -2469,7 +2504,7 @@ public:
if (scope_info->createsClosure()) { if (scope_info->createsClosure()) {
if (!passed_closure) if (!passed_closure)
passed_closure = embedConstantPtr(nullptr, g.llvm_closure_type_ptr); passed_closure = getNullPtr(g.llvm_closure_type_ptr);
llvm::Value* new_closure = emitter.getBuilder()->CreateCall2( llvm::Value* new_closure = emitter.getBuilder()->CreateCall2(
g.funcs.createClosure, passed_closure, getConstantInt(scope_info->getClosureSize(), g.i64)); g.funcs.createClosure, passed_closure, getConstantInt(scope_info->getClosureSize(), g.i64));
......
...@@ -80,7 +80,7 @@ llvm::Constant* getStringConstantPtr(const std::string& str) { ...@@ -80,7 +80,7 @@ llvm::Constant* getStringConstantPtr(const std::string& str) {
strings[str] = buf; strings[str] = buf;
c = buf; c = buf;
} }
return embedConstantPtr(c, g.i8->getPointerTo()); return embedRelocatablePtr(c, g.i8->getPointerTo());
} }
// Returns a llvm::Constant char* to a global string constant // Returns a llvm::Constant char* to a global string constant
...@@ -92,6 +92,33 @@ llvm::Constant* getStringConstantPtr(const char* str) { ...@@ -92,6 +92,33 @@ llvm::Constant* getStringConstantPtr(const char* str) {
// to some associated compiler-level data structure. // to some associated compiler-level data structure.
// It's slightly easier to emit them as integers (there are primitive integer constants but not pointer constants), // It's slightly easier to emit them as integers (there are primitive integer constants but not pointer constants),
// but doing it this way makes it clearer what's going on. // but doing it this way makes it clearer what's going on.
static llvm::StringMap<const void*> relocatable_syms;
void clearRelocatableSymsMap() {
relocatable_syms.clear();
}
const void* getValueOfRelocatableSym(const std::string& str) {
auto it = relocatable_syms.find(str);
if (it != relocatable_syms.end())
return it->second;
return NULL;
}
llvm::Constant* embedRelocatablePtr(const void* addr, llvm::Type* type) {
assert(addr);
if (!ENABLE_JIT_OBJECT_CACHE)
return embedConstantPtr(addr, type);
std::string name = (llvm::Twine("c") + llvm::Twine(relocatable_syms.size())).str();
relocatable_syms[name] = addr;
llvm::Type* var_type = type->getPointerElementType();
return new llvm::GlobalVariable(*g.cur_module, var_type, true, llvm::GlobalVariable::ExternalLinkage, 0, name);
}
llvm::Constant* embedConstantPtr(const void* addr, llvm::Type* type) { llvm::Constant* embedConstantPtr(const void* addr, llvm::Type* type) {
assert(type); assert(type);
llvm::Constant* int_val = llvm::ConstantInt::get(g.i64, reinterpret_cast<uintptr_t>(addr), false); llvm::Constant* int_val = llvm::ConstantInt::get(g.i64, reinterpret_cast<uintptr_t>(addr), false);
...@@ -99,6 +126,11 @@ llvm::Constant* embedConstantPtr(const void* addr, llvm::Type* type) { ...@@ -99,6 +126,11 @@ llvm::Constant* embedConstantPtr(const void* addr, llvm::Type* type) {
return ptr_val; return ptr_val;
} }
llvm::Constant* getNullPtr(llvm::Type* t) {
assert(llvm::isa<llvm::PointerType>(t));
return llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(t));
}
llvm::Constant* getConstantInt(int64_t n, llvm::Type* t) { llvm::Constant* getConstantInt(int64_t n, llvm::Type* t) {
return llvm::ConstantInt::get(t, n); return llvm::ConstantInt::get(t, n);
} }
......
...@@ -27,10 +27,15 @@ namespace pyston { ...@@ -27,10 +27,15 @@ namespace pyston {
llvm::Constant* getStringConstantPtr(const std::string& str); llvm::Constant* getStringConstantPtr(const std::string& str);
llvm::Constant* getStringConstantPtr(const char* str); llvm::Constant* getStringConstantPtr(const char* str);
llvm::Constant* embedRelocatablePtr(const void* addr, llvm::Type*);
llvm::Constant* embedConstantPtr(const void* addr, llvm::Type*); llvm::Constant* embedConstantPtr(const void* addr, llvm::Type*);
llvm::Constant* getConstantInt(int64_t val); llvm::Constant* getConstantInt(int64_t val);
llvm::Constant* getConstantDouble(double val); llvm::Constant* getConstantDouble(double val);
llvm::Constant* getConstantInt(int64_t val, llvm::Type*); llvm::Constant* getConstantInt(int64_t val, llvm::Type*);
llvm::Constant* getNullPtr(llvm::Type* t);
void clearRelocatableSymsMap();
const void* getValueOfRelocatableSym(const std::string& str);
void dumpPrettyIR(llvm::Function* f); void dumpPrettyIR(llvm::Function* f);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h" #include "llvm/Support/Memory.h"
#include "codegen/irgen/util.h"
#include "core/common.h" #include "core/common.h"
#include "core/stats.h" #include "core/stats.h"
#include "core/util.h" #include "core/util.h"
...@@ -206,7 +207,11 @@ void PystonMemoryManager::invalidateInstructionCache() { ...@@ -206,7 +207,11 @@ void PystonMemoryManager::invalidateInstructionCache() {
} }
uint64_t PystonMemoryManager::getSymbolAddress(const std::string& name) { uint64_t PystonMemoryManager::getSymbolAddress(const std::string& name) {
uint64_t base = RTDyldMemoryManager::getSymbolAddress(name); uint64_t base = (uint64_t)getValueOfRelocatableSym(name);
if (base)
return base;
base = RTDyldMemoryManager::getSymbolAddress(name);
if (base) if (base)
return base; return base;
...@@ -214,7 +219,7 @@ uint64_t PystonMemoryManager::getSymbolAddress(const std::string& name) { ...@@ -214,7 +219,7 @@ uint64_t PystonMemoryManager::getSymbolAddress(const std::string& name) {
return getSymbolAddress(".L" + name); return getSymbolAddress(".L" + name);
} }
printf("getSymbolAddress(%s); %lx\n", name.c_str(), base); RELEASE_ASSERT(0, "Could not find sym: %s", name.c_str());
return 0; return 0;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "asm_writing/icinfo.h" #include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h" #include "asm_writing/rewriter.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "codegen/irgen/util.h"
#include "codegen/stackmaps.h" #include "codegen/stackmaps.h"
#include "core/common.h" #include "core/common.h"
#include "core/options.h" #include "core/options.h"
...@@ -41,7 +42,7 @@ int ICSetupInfo::totalSize() const { ...@@ -41,7 +42,7 @@ int ICSetupInfo::totalSize() const {
return num_slots * slot_size + call_size; return num_slots * slot_size + call_size;
} }
static std::vector<PatchpointInfo*> new_patchpoints; static std::vector<std::pair<PatchpointInfo*, void* /* addr of func to call */>> new_patchpoints;
ICSetupInfo* ICSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size, ICType type, ICSetupInfo* ICSetupInfo::initialize(bool has_return_value, int num_slots, int slot_size, ICType type,
TypeRecorder* type_recorder) { TypeRecorder* type_recorder) {
...@@ -165,9 +166,12 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -165,9 +166,12 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
const StackMap::StackSizeRecord& stack_size_record = stackmap->stack_size_records[0]; const StackMap::StackSizeRecord& stack_size_record = stackmap->stack_size_records[0];
int stack_size = stack_size_record.stack_size; int stack_size = stack_size_record.stack_size;
PatchpointInfo* pp = reinterpret_cast<PatchpointInfo*>(r->id);
RELEASE_ASSERT(new_patchpoints.size() > r->id, "");
PatchpointInfo* pp = new_patchpoints[r->id].first;
assert(pp); assert(pp);
void* dst_func = new_patchpoints[r->id].second;
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());
...@@ -183,6 +187,9 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -183,6 +187,9 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
uint8_t* start_addr = (uint8_t*)pp->parentFunction()->code + r->offset; uint8_t* start_addr = (uint8_t*)pp->parentFunction()->code + r->offset;
uint8_t* end_addr = start_addr + pp->patchpointSize(); 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 // TODO shouldn't have to do it this way
void* slowpath_func = extractSlowpathFunc(start_addr); void* slowpath_func = extractSlowpathFunc(start_addr);
...@@ -270,7 +277,8 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -270,7 +277,8 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
cf->ics.push_back(icinfo.release()); cf->ics.push_back(icinfo.release());
} }
for (PatchpointInfo* pp : new_patchpoints) { for (auto& e : new_patchpoints) {
PatchpointInfo* pp = e.first;
const ICSetupInfo* ic = pp->getICInfo(); const ICSetupInfo* ic = pp->getICInfo();
if (ic) if (ic)
delete ic; delete ic;
...@@ -279,13 +287,14 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) { ...@@ -279,13 +287,14 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
new_patchpoints.clear(); new_patchpoints.clear();
} }
PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args,
int num_ic_stackmap_args) { void* func_addr) {
if (icinfo == NULL) if (icinfo == NULL)
assert(num_ic_stackmap_args == 0); assert(num_ic_stackmap_args == 0);
auto* r = new PatchpointInfo(parent_cf, icinfo, num_ic_stackmap_args); auto* r = new PatchpointInfo(parent_cf, icinfo, num_ic_stackmap_args);
new_patchpoints.push_back(r); r->id = new_patchpoints.size();
new_patchpoints.push_back(std::make_pair(r, func_addr));
return r; return r;
} }
......
...@@ -53,10 +53,12 @@ private: ...@@ -53,10 +53,12 @@ private:
int num_frame_stackmap_args; int num_frame_stackmap_args;
std::vector<FrameVarInfo> frame_vars; std::vector<FrameVarInfo> frame_vars;
unsigned int id;
PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args) PatchpointInfo(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args)
: parent_cf(parent_cf), icinfo(icinfo), num_ic_stackmap_args(num_ic_stackmap_args), : parent_cf(parent_cf), icinfo(icinfo), num_ic_stackmap_args(num_ic_stackmap_args), num_frame_stackmap_args(-1),
num_frame_stackmap_args(-1) {} id(0) {}
public: public:
const ICSetupInfo* getICInfo() { return icinfo; } const ICSetupInfo* getICInfo() { return icinfo; }
...@@ -84,11 +86,14 @@ public: ...@@ -84,11 +86,14 @@ public:
return num_frame_stackmap_args; return num_frame_stackmap_args;
} }
unsigned int getId() const { return id; }
void parseLocationMap(StackMap::Record* r, LocationMap* map); void parseLocationMap(StackMap::Record* r, LocationMap* map);
int totalStackmapArgs() { return frameStackmapArgsStart() + numFrameStackmapArgs(); } int totalStackmapArgs() { return frameStackmapArgsStart() + numFrameStackmapArgs(); }
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);
}; };
class ICSetupInfo { class ICSetupInfo {
......
...@@ -261,7 +261,6 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -261,7 +261,6 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr); g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr); g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
GET(__cxa_begin_catch);
g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_); g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_);
GET(raise0); GET(raise0);
GET(raise3); GET(raise3);
......
...@@ -49,7 +49,7 @@ struct GlobalFuncs { ...@@ -49,7 +49,7 @@ struct GlobalFuncs {
llvm::Value* exec; llvm::Value* exec;
llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel; llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel;
llvm::Value* __cxa_begin_catch, *__cxa_end_catch; llvm::Value* __cxa_end_catch;
llvm::Value* raise0, *raise3; llvm::Value* raise0, *raise3;
llvm::Value* deopt; llvm::Value* deopt;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
namespace pyston { namespace pyston {
#ifndef NDEBUG #ifdef DEBUG_LINE_NUMBERS
int AST::next_lineno = 100000; int AST::next_lineno = 100000;
AST::AST(AST_TYPE::AST_TYPE type) : type(type), lineno(++next_lineno) { AST::AST(AST_TYPE::AST_TYPE type) : type(type), lineno(++next_lineno) {
......
...@@ -154,16 +154,17 @@ public: ...@@ -154,16 +154,17 @@ public:
virtual void accept(ASTVisitor* v) = 0; virtual void accept(ASTVisitor* v) = 0;
#ifndef NDEBUG // #define DEBUG_LINE_NUMBERS 1
#ifdef DEBUG_LINE_NUMBERS
private: private:
// In debug mode, initialize lineno to something unique, so that if we see something ridiculous // Initialize lineno to something unique, so that if we see something ridiculous
// appear in the traceback, we can isolate the allocation which created it. // appear in the traceback, we can isolate the allocation which created it.
static int next_lineno; static int next_lineno;
public: public:
AST(AST_TYPE::AST_TYPE type); AST(AST_TYPE::AST_TYPE type);
#else #else
AST(AST_TYPE::AST_TYPE type) : type(type) {} AST(AST_TYPE::AST_TYPE type) : type(type), lineno(0), col_offset(0) {}
#endif #endif
AST(AST_TYPE::AST_TYPE type, uint32_t lineno, uint32_t col_offset = 0) AST(AST_TYPE::AST_TYPE type, uint32_t lineno, uint32_t col_offset = 0)
: type(type), lineno(lineno), col_offset(col_offset) {} : type(type), lineno(lineno), col_offset(col_offset) {}
......
...@@ -172,6 +172,8 @@ private: ...@@ -172,6 +172,8 @@ private:
std::vector<ContInfo> continuations; std::vector<ContInfo> continuations;
std::vector<ExcBlockInfo> exc_handlers; std::vector<ExcBlockInfo> exc_handlers;
unsigned int next_var_index = 0;
friend CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body); friend CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body);
public: public:
...@@ -196,6 +198,11 @@ private: ...@@ -196,6 +198,11 @@ private:
return source->getInternedStrings().get(std::forward<T>(s)); return source->getInternedStrings().get(std::forward<T>(s));
} }
InternedString createUniqueName(llvm::Twine prefix) {
std::string name = (prefix + llvm::Twine(next_var_index++)).str();
return source->getInternedStrings().get(std::move(name));
}
AST_Name* makeName(InternedString id, AST_TYPE::AST_TYPE ctx_type, int lineno, int col_offset = 0) { AST_Name* makeName(InternedString id, AST_TYPE::AST_TYPE ctx_type, int lineno, int col_offset = 0) {
AST_Name* name = new AST_Name(id, ctx_type, lineno, col_offset); AST_Name* name = new AST_Name(id, ctx_type, lineno, col_offset);
return name; return name;
...@@ -600,36 +607,14 @@ private: ...@@ -600,36 +607,14 @@ private:
return stmt; return stmt;
} }
InternedString nodeName(AST* node) { InternedString nodeName(AST* node) { return createUniqueName("#"); }
char buf[40];
int bytes = snprintf(buf, 40, "#%p", node);
assert(bytes < 40); // double-check
// Uncomment this line to check to make sure we never reuse the same nodeName() accidentally.
// This check is potentially too expensive for even debug mode, since it never frees any memory.
// #define VALIDATE_FAKE_NAMES
#ifdef VALIDATE_FAKE_NAMES
std::string r(buf);
static std::unordered_set<std::string> made;
assert(made.count(r) == 0);
made.insert(r);
return internString(std::move(r));
#else
return internString(buf);
#endif
}
InternedString nodeName(AST* node, const std::string& suffix) { InternedString nodeName(AST* node, const std::string& suffix) {
char buf[50]; return createUniqueName(llvm::Twine("#") + suffix + "_");
int bytes = snprintf(buf, 50, "#%p_%s", node, suffix.c_str());
assert(bytes < 50); // double-check
return internString(std::string(buf));
} }
InternedString nodeName(AST* node, const std::string& suffix, int idx) { InternedString nodeName(AST* node, const std::string& suffix, int idx) {
char buf[50]; return createUniqueName(llvm::Twine("#") + suffix + "_" + llvm::Twine(idx) + "_");
int bytes = snprintf(buf, 50, "#%p_%s_%d", node, suffix.c_str(), idx);
assert(bytes < 50); // double-check
return internString(std::string(buf));
} }
AST_expr* remapAttribute(AST_Attribute* node) { AST_expr* remapAttribute(AST_Attribute* node) {
...@@ -2005,9 +1990,7 @@ public: ...@@ -2005,9 +1990,7 @@ public:
AST_LangPrimitive* iter_call = new AST_LangPrimitive(AST_LangPrimitive::GET_ITER); AST_LangPrimitive* iter_call = new AST_LangPrimitive(AST_LangPrimitive::GET_ITER);
iter_call->args.push_back(remapped_iter); iter_call->args.push_back(remapped_iter);
char itername_buf[80]; InternedString itername = createUniqueName("#iter_");
snprintf(itername_buf, 80, "#iter_%p", node);
InternedString itername = internString(itername_buf);
pushAssign(itername, iter_call); pushAssign(itername, iter_call);
AST_expr* next_attr = makeLoadAttribute(makeLoad(itername, node), internString("next"), true); AST_expr* next_attr = makeLoadAttribute(makeLoad(itername, node), internString("next"), true);
......
...@@ -71,6 +71,7 @@ bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE; ...@@ -71,6 +71,7 @@ bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE;
bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE; bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE;
bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE; bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE;
bool ENABLE_RUNTIME_ICS = 1 && _GLOBAL_ENABLE; bool ENABLE_RUNTIME_ICS = 1 && _GLOBAL_ENABLE;
bool ENABLE_JIT_OBJECT_CACHE = 1 && _GLOBAL_ENABLE;
bool ENABLE_FRAME_INTROSPECTION = 1; bool ENABLE_FRAME_INTROSPECTION = 1;
bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION; bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION;
......
...@@ -42,7 +42,7 @@ extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TR ...@@ -42,7 +42,7 @@ extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TR
extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICDELITEMS, ENABLE_ICBINEXPS, extern bool ENABLE_ICS, ENABLE_ICGENERICS, ENABLE_ICGETITEMS, ENABLE_ICSETITEMS, ENABLE_ICDELITEMS, ENABLE_ICBINEXPS,
ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENALBE_ICDELATTRS, ENABLE_ICGETGLOBALS, ENABLE_ICNONZEROS, ENABLE_ICCALLSITES, ENABLE_ICSETATTRS, ENABLE_ICGETATTRS, ENALBE_ICDELATTRS, ENABLE_ICGETGLOBALS,
ENABLE_SPECULATION, ENABLE_OSR, ENABLE_LLVMOPTS, ENABLE_INLINING, ENABLE_REOPT, ENABLE_PYSTON_PASSES, ENABLE_SPECULATION, ENABLE_OSR, ENABLE_LLVMOPTS, ENABLE_INLINING, ENABLE_REOPT, ENABLE_PYSTON_PASSES,
ENABLE_TYPE_FEEDBACK, ENABLE_FRAME_INTROSPECTION, ENABLE_RUNTIME_ICS; ENABLE_TYPE_FEEDBACK, ENABLE_FRAME_INTROSPECTION, ENABLE_RUNTIME_ICS, ENABLE_JIT_OBJECT_CACHE;
// Due to a temporary LLVM limitation, represent bools as i64's instead of i1's. // Due to a temporary LLVM limitation, represent bools as i64's instead of i1's.
extern bool BOOLS_AS_I64; extern bool BOOLS_AS_I64;
......
...@@ -188,7 +188,6 @@ public: ...@@ -188,7 +188,6 @@ public:
uintptr_t code_start; uintptr_t code_start;
}; };
int code_size; int code_size;
llvm::Value* llvm_code; // the llvm callable.
EffortLevel effort; EffortLevel effort;
...@@ -200,10 +199,9 @@ public: ...@@ -200,10 +199,9 @@ public:
std::vector<ICInfo*> ics; std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, bool is_interpreted, void* code, CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, bool is_interpreted, void* code,
llvm::Value* llvm_code, EffortLevel effort, const OSREntryDescriptor* entry_descriptor) EffortLevel effort, const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL), func(func), spec(spec), entry_descriptor(entry_descriptor), is_interpreted(is_interpreted), : 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), times_speculation_failed(0), code(code), effort(effort), times_called(0), times_speculation_failed(0), location_map(nullptr) {
location_map(nullptr) {
assert((spec != NULL) + (entry_descriptor != NULL) == 1); assert((spec != NULL) + (entry_descriptor != NULL) == 1);
} }
...@@ -307,7 +305,6 @@ public: ...@@ -307,7 +305,6 @@ public:
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1); assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
assert(compiled->clfunc == NULL); assert(compiled->clfunc == NULL);
assert(compiled->is_interpreted == (compiled->code == NULL)); assert(compiled->is_interpreted == (compiled->code == NULL));
assert(compiled->is_interpreted == (compiled->llvm_code == NULL));
compiled->clfunc = this; compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) { if (compiled->entry_descriptor == NULL) {
......
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