Commit 691b8d69 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #433 from undingen/objectcache

Add a cache for JITed object code
parents 59d38882 729a81c5
......@@ -10,3 +10,6 @@
[submodule "test/integration/virtualenv"]
path = test/integration/virtualenv
url = https://github.com/dropbox/virtualenv
[submodule "lz4"]
path = lz4
url = git://github.com/Cyan4973/lz4.git
......@@ -116,6 +116,10 @@ ExternalProject_Add(libunwind
add_subdirectory(libpypa)
add_dependencies(pypa gitsubmodules)
# lz4
add_subdirectory(lz4/cmake_unofficial)
add_dependencies(lz4 gitsubmodules)
# valgrind
if(ENABLE_VALGRIND)
find_package(Valgrind REQUIRED)
......@@ -182,7 +186,7 @@ add_subdirectory(tools)
add_executable(pyston $<TARGET_OBJECTS:PYSTON_MAIN_OBJECT> $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON>)
# Wrap the stdlib in --whole-archive to force all the symbols to be included and eventually exported
target_link_libraries(pyston -Wl,--whole-archive stdlib -Wl,--no-whole-archive pthread m readline sqlite3 gmp ssl crypto unwind pypa double-conversion ${LLVM_LIBS} ${LIBLZMA_LIBRARIES} ${OPTIONAL_LIBRARIES})
target_link_libraries(pyston -Wl,--whole-archive stdlib -Wl,--no-whole-archive pthread m readline sqlite3 gmp ssl crypto unwind pypa liblz4 double-conversion ${LLVM_LIBS} ${LIBLZMA_LIBRARIES} ${OPTIONAL_LIBRARIES})
# copy src/codegen/parse_ast.py to the build directory
add_custom_command(TARGET pyston POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/codegen/parse_ast.py ${CMAKE_BINARY_DIR}/src/codegen/parse_ast.py)
......
......@@ -88,3 +88,32 @@ products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
------
LZ4 Library
Copyright (c) 2011-2014, Yann Collet
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------
......@@ -155,6 +155,7 @@ COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS += -Wno-invalid-offsetof # allow the use of "offsetof", and we'll just have to make sure to only use it legally.
COMMON_CXXFLAGS += -DENABLE_INTEL_JIT_EVENTS=$(ENABLE_INTEL_JIT_EVENTS)
COMMON_CXXFLAGS += -I$(DEPS_DIR)/pypa-install/include
COMMON_CXXFLAGS += -I$(DEPS_DIR)/lz4-install/include
ifeq ($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS += -DNVALGRIND
......@@ -170,6 +171,7 @@ COMMON_CXXFLAGS += -DDEFAULT_PYTHON_MAJOR_VERSION=$(PYTHON_MAJOR_VERSION) -DDEFA
# Use our "custom linker" that calls gold if available
COMMON_LDFLAGS := -B$(TOOLS_DIR)/build_system -L/usr/local/lib -lpthread -lm -lunwind -llzma -L$(DEPS_DIR)/gcc-4.8.2-install/lib64 -lreadline -lgmp -lssl -lcrypto -lsqlite3
COMMON_LDFLAGS += $(DEPS_DIR)/pypa-install/lib/libpypa.a
COMMON_LDFLAGS += $(DEPS_DIR)/lz4-install/lib/liblz4.a
# Conditionally add libtinfo if available - otherwise nothing will be added
COMMON_LDFLAGS += `pkg-config tinfo 2>/dev/null && pkg-config tinfo --libs || echo ""`
......
......@@ -140,6 +140,15 @@ cd gtest-1.7.0
make -j4
```
### LZ4
```
cd ~/pyston_deps
git clone git://github.com/Cyan4973/lz4.git
mkdir lz4-install
cd lz4/lib
DESTDIR="$HOME/pyston_deps/lz4-install" PREFIX="/" make install
```
---
At this point you should be able to run `make check` (in the `~/pyston` directory) and pass the tests. See the main README for more information about available targets and options.
......
From a27e2f111d85c2e55c5a9672b9ef39494b4d7fd8 Mon Sep 17 00:00:00 2001
From: Marius Wachtler <undingen@gmail.com>
Date: Wed, 15 Apr 2015 09:40:51 +0200
Subject: [PATCH] Add support for symbolic entries in the stackmap constant
table
---
include/llvm/CodeGen/StackMaps.h | 18 ++++++++++--
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 ++++++
lib/CodeGen/StackMaps.cpp | 36 +++++++++++++++++++++---
test/CodeGen/X86/stackmap.ll | 26 +++++++++++++++--
4 files changed, 79 insertions(+), 10 deletions(-)
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 4e48afe..30cae3b 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -136,9 +136,13 @@ public:
unsigned Size;
unsigned Reg;
int64_t Offset;
- Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {}
+ const MCSymbol *Sym;
+ Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0), Sym(0) {}
Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset)
- : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
+ : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset), Sym(0) {}
+ Location(const MCSymbol *Sym)
+ : LocType(LocationType::Constant), Size(sizeof(int64_t)), Reg(0),
+ Offset(0), Sym(Sym) {}
};
struct LiveOutReg {
@@ -160,13 +164,19 @@ public:
// OpTypes are used to encode information about the following logical
// operand (which may consist of several MachineOperands) for the
// OpParser.
- typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;
+ typedef enum {
+ DirectMemRefOp,
+ IndirectMemRefOp,
+ ConstantOp,
+ ConstantGVOp
+ } OpType;
StackMaps(AsmPrinter &AP);
void reset() {
CSInfos.clear();
ConstPool.clear();
+ ConstSymPool.clear();
FnStackSize.clear();
}
@@ -191,6 +201,7 @@ private:
typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<uint64_t, uint64_t> ConstantPool;
+ typedef MapVector<const MCSymbol *, const MCSymbol *> ConstantSymMap;
typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
struct CallsiteInfo {
@@ -210,6 +221,7 @@ private:
AsmPrinter &AP;
CallsiteInfoList CSInfos;
ConstantPool ConstPool;
+ ConstantSymMap ConstSymPool;
FnStackSizeMap FnStackSize;
MachineInstr::const_mop_iterator
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c0a8299..98cc692 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7122,6 +7122,15 @@ static void addStackMapLiveVars(ImmutableCallSite CS, unsigned StartIdx,
const TargetLowering &TLI = Builder.DAG.getTargetLoweringInfo();
Ops.push_back(
Builder.DAG.getTargetFrameIndex(FI->getIndex(), TLI.getPointerTy()));
+ } else if (auto *GA = dyn_cast<GlobalAddressSDNode>(OpVal)) {
+ if (GA->getValueType(0) != MVT::i64)
+ Ops.push_back(OpVal);
+ else {
+ Ops.push_back(
+ Builder.DAG.getTargetConstant(StackMaps::ConstantGVOp, MVT::i64));
+ Ops.push_back(Builder.DAG.getTargetGlobalAddress(GA->getGlobal(),
+ SDLoc(GA), MVT::i64));
+ }
} else
Ops.push_back(OpVal);
}
diff --git a/lib/CodeGen/StackMaps.cpp b/lib/CodeGen/StackMaps.cpp
index 0797d56..7151166 100644
--- a/lib/CodeGen/StackMaps.cpp
+++ b/lib/CodeGen/StackMaps.cpp
@@ -107,6 +107,16 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
Locs.push_back(Location(Location::Constant, sizeof(int64_t), 0, Imm));
break;
}
+ case StackMaps::ConstantGVOp: {
+ ++MOI;
+ assert(MOI->isGlobal() && "Expected a global value operand.");
+ const GlobalValue *GV = MOI->getGlobal();
+ assert(GV);
+ MCSymbol *Sym = AP.TM.getSymbol(GV, *AP.Mang);
+ assert(Sym);
+ Locs.push_back(Location(Sym));
+ break;
+ }
}
return ++MOI;
}
@@ -226,7 +236,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
I != E; ++I) {
// Constants are encoded as sign-extended integers.
// -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
- if (I->LocType == Location::Constant && !isInt<32>(I->Offset)) {
+ if (I->LocType == Location::Constant && !isInt<32>(I->Offset) && !I->Sym) {
I->LocType = Location::ConstantIndex;
// ConstPool is intentionally a MapVector of 'uint64_t's (as
// opposed to 'int64_t's). We should never be in a situation
@@ -243,6 +253,17 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
}
}
+ // Convert constant symbols to ConstantIndex entries.
+ for (LocationVec::iterator I = Locations.begin(), E = Locations.end(); I != E;
+ ++I) {
+ if (I->LocType == Location::Constant && I->Sym) {
+ I->LocType = Location::ConstantIndex;
+ auto Result = ConstSymPool.insert(std::make_pair(I->Sym, I->Sym));
+ // The symbolic entries will be emitted after the ConstPool entries.
+ I->Offset = ConstPool.size() + Result.first - ConstSymPool.begin();
+ }
+ }
+
// Create an expression to calculate the offset of the callsite from function
// entry.
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
@@ -325,8 +346,9 @@ void StackMaps::emitStackmapHeader(MCStreamer &OS) {
DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
OS.EmitIntValue(FnStackSize.size(), 4);
// Num constants.
- DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
- OS.EmitIntValue(ConstPool.size(), 4);
+ auto NumConst = ConstPool.size() + ConstSymPool.size();
+ DEBUG(dbgs() << WSMP << "#constants = " << NumConst << '\n');
+ OS.EmitIntValue(NumConst, 4);
// Num callsites.
DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
OS.EmitIntValue(CSInfos.size(), 4);
@@ -359,6 +381,10 @@ void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
OS.EmitIntValue(ConstEntry.second, 8);
}
+ for (auto ConstEntry : ConstSymPool) {
+ DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
+ OS.EmitSymbolValue(ConstEntry.second, 8);
+ }
}
/// Emit the callsite info for each callsite.
@@ -511,7 +537,8 @@ void StackMaps::emitCallsiteEntries(MCStreamer &OS,
void StackMaps::serializeToStackMapSection() {
(void) WSMP;
// Bail out if there's no stack map data.
- assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) &&
+ assert((!CSInfos.empty() ||
+ (CSInfos.empty() && ConstPool.empty() && ConstSymPool.empty())) &&
"Expected empty constant pool too!");
assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) &&
"Expected empty function record too!");
@@ -541,4 +568,5 @@ void StackMaps::serializeToStackMapSection() {
// Clean up.
CSInfos.clear();
ConstPool.clear();
+ ConstSymPool.clear();
}
diff --git a/test/CodeGen/X86/stackmap.ll b/test/CodeGen/X86/stackmap.ll
index 5e356f3..59fa50f 100644
--- a/test/CodeGen/X86/stackmap.ll
+++ b/test/CodeGen/X86/stackmap.ll
@@ -11,7 +11,7 @@
; Num Functions
; CHECK-NEXT: .long 16
; Num LargeConstants
-; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 5
; Num Callsites
; CHECK-NEXT: .long 20
@@ -53,6 +53,8 @@
; CHECK-NEXT: .quad 2147483648
; CHECK-NEXT: .quad 4294967295
; CHECK-NEXT: .quad 4294967296
+; CHECK-NEXT: .quad _constSym1
+; CHECK-NEXT: .quad _constSym2
; Callsites
; Constant arguments
@@ -60,7 +62,7 @@
; CHECK-NEXT: .quad 1
; CHECK-NEXT: .long L{{.*}}-_constantargs
; CHECK-NEXT: .short 0
-; CHECK-NEXT: .short 12
+; CHECK-NEXT: .short 15
; SmallConstant
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 8
@@ -116,16 +118,34 @@
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 2
+; LargeConstant at index 3
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 3
+; LargeConstant at index 3
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 3
+; LargeConstant at index 4
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 4
; SmallConstant
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long -1
+
+@constSym1 = external constant i64
+@constSym2 = external constant i64
define void @constantargs() {
entry:
%0 = inttoptr i64 12345 to i8*
- tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64 -1)
+ tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64* @constSym1, i64* @constSym1, i64* @constSym2, i64 -1)
ret void
}
--
2.1.0
Subproject commit 160661c7a4cbf805f4af74d2e3932a17a66e6ce7
......@@ -8,6 +8,7 @@ set_source_files_properties(jit.cpp PROPERTIES COMPILE_DEFINITIONS "GITREV=${GIT
include_directories(${CMAKE_BINARY_DIR})
include_directories(${CMAKE_BINARY_DIR}/libunwind/include)
include_directories(${CMAKE_SOURCE_DIR}/libpypa/src)
include_directories(${CMAKE_SOURCE_DIR}/lz4/lib)
if(ENABLE_GPERFTOOLS)
set(OPTIONAL_SRCS ${OPTIONAL_SRCS} codegen/profiling/pprof.cpp)
......@@ -109,7 +110,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
add_dependencies(PYSTON_OBJECTS libunwind pypa ${LLVM_LIBS})
add_library(PYSTON_MAIN_OBJECT OBJECT jit.cpp)
add_dependencies(PYSTON_MAIN_OBJECT libunwind pypa ${LLVM_LIBS})
add_dependencies(PYSTON_MAIN_OBJECT libunwind pypa liblz4 ${LLVM_LIBS})
# build stdlib
add_subdirectory(runtime/inline)
......
......@@ -283,8 +283,12 @@ public:
assert(usage);
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;
for (auto& p : usage->referenced_from_nested) {
for (auto& p : referenced_from_nested_sorted) {
closure_offsets[p] = i;
i++;
}
......
......@@ -1555,6 +1555,27 @@ void* extractSlowpathFunc(uint8_t* pp_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,
int scratch_offset, int scratch_size,
const std::unordered_set<int>& live_outs, SpillMap& remapped) {
......
......@@ -476,6 +476,7 @@ public:
};
void* extractSlowpathFunc(uint8_t* pp_addr);
void setSlowpathFunc(uint8_t* pp_addr, void* func);
struct GRCompare {
bool operator()(assembler::GenericRegister gr1, assembler::GenericRegister gr2) const {
......
......@@ -293,7 +293,8 @@ public:
llvm::Value* cls_value = emitter.getBuilder()->CreateLoad(cls_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;
}
......@@ -367,8 +368,8 @@ public:
}
// 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(),
embedConstantPtr(0, g.llvm_value_type_ptr));
llvm::Value* cmp
= emitter.getBuilder()->CreateICmpNE(converted_iter_call->getValue(), getNullPtr(g.llvm_value_type_ptr));
llvm::BasicBlock* bb_has_iter = emitter.createBasicBlock("has_iter");
bb_has_iter->moveAfter(emitter.currentBasicBlock());
......@@ -529,19 +530,19 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
if (args.size() >= 1) {
llvm_args.push_back(converted_args[0]->getValue());
} 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) {
llvm_args.push_back(converted_args[1]->getValue());
} 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) {
llvm_args.push_back(converted_args[2]->getValue());
} 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;
......@@ -569,10 +570,10 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
llvm_args.push_back(arg_array);
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) {
llvm_args.push_back(embedConstantPtr(NULL, g.llvm_value_type_ptr->getPointerTo()));
llvm_args.push_back(embedConstantPtr(keyword_names, g.vector_ptr));
llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr->getPointerTo()));
llvm_args.push_back(embedRelocatablePtr(keyword_names, g.vector_ptr));
}
// f->dump();
......@@ -683,7 +684,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
std::vector<llvm::Value*> other_args;
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));
llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false);
......@@ -737,7 +738,7 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
convertedClosure = closure->makeConverted(emitter, closure->getConcreteType());
closure_v = convertedClosure->getValue();
} else {
closure_v = embedConstantPtr(nullptr, g.llvm_closure_type_ptr);
closure_v = getNullPtr(g.llvm_closure_type_ptr);
}
llvm::Value* scratch;
......@@ -752,20 +753,20 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
i++;
}
} 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);
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
// emitter.createCall().
llvm::Value* boxed = emitter.getBuilder()->CreateCall(
g.funcs.boxCLFunction,
std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, globals_v,
scratch, getConstantInt(defaults.size(), g.i64) });
std::vector<llvm::Value*>{ embedRelocatablePtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v,
globals_v, scratch, getConstantInt(defaults.size(), g.i64) });
if (convertedClosure)
convertedClosure->decvref(emitter);
......@@ -1339,7 +1340,7 @@ ConcreteCompilerVariable* makeFloat(double d) {
ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string& n_long) {
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);
}
......@@ -1481,7 +1482,7 @@ public:
ASSERT(rtattr, "%s.%s", debugName().c_str(), attr->c_str());
if (rtattr->cls == function_cls) {
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);
}
}
......@@ -1587,7 +1588,11 @@ public:
}
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;
new_args.push_back(var);
......@@ -1595,10 +1600,14 @@ public:
for (int i = args.size() + 1; i < cl->num_args; i++) {
// TODO should _call() be able to take llvm::Value's directly?
new_args.push_back(new ConcreteCompilerVariable(
UNKNOWN, embedConstantPtr(rtattr_func->defaults->elts[i - cl->num_args + cl->num_defaults],
g.llvm_value_type_ptr),
true));
auto value = rtattr_func->defaults->elts[i - cl->num_args + cl->num_defaults];
llvm::Value* llvm_value;
if (value)
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;
......@@ -1873,8 +1882,8 @@ public:
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override {
assert(other_type == STR || other_type == UNKNOWN);
llvm::Value* boxed = emitter.getBuilder()->CreateCall(g.funcs.boxStringPtr,
embedConstantPtr(var->getValue(), g.llvm_str_type_ptr));
llvm::Value* boxed = emitter.getBuilder()->CreateCall(
g.funcs.boxStringPtr, embedRelocatablePtr(var->getValue(), g.llvm_str_type_ptr));
return new ConcreteCompilerVariable(other_type, boxed, true);
}
......@@ -1928,7 +1937,7 @@ public:
}
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 {
......@@ -1947,7 +1956,7 @@ CompilerVariable* makeStr(const std::string* s) {
CompilerVariable* makeUnicode(IREmitter& emitter, const std::string* s) {
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);
}
......
This diff is collapsed.
......@@ -16,6 +16,7 @@
#include <cstdio>
#include <iostream>
#include <set>
#include <sstream>
#include <stdint.h>
......@@ -541,7 +542,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction());
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* new_call_count
= emitter->getBuilder()->CreateAdd(cur_call_count, getConstantInt(1, g.i64));
......@@ -569,7 +570,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
emitter->getBuilder()->SetInsertPoint(reopt_bb);
// emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1));
llvm::Value* r = emitter->getBuilder()->CreateCall(g.funcs.reoptCompiledFunc,
embedConstantPtr(cf, g.i8->getPointerTo()));
embedRelocatablePtr(cf, g.i8->getPointerTo()));
assert(r);
assert(r->getType() == g.i8->getPointerTo());
......@@ -632,7 +633,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
}
std::unordered_set<InternedString> names;
std::set<InternedString> names;
for (const auto& s : source->phis->getAllRequiredFor(block)) {
names.insert(s);
if (source->phis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) {
......@@ -739,9 +740,17 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// NB. This is where most `typical' phi nodes get added.
// And go through and add phi nodes:
ConcreteSymbolTable* pred_st = phi_ending_symbol_tables[pred];
for (auto it = pred_st->begin(); it != pred_st->end(); ++it) {
InternedString name = it->first;
ConcreteCompilerVariable* cv = it->second; // incoming CCV from predecessor block
// We have to sort the phi table by name in order to a get a deterministic ordering for the JIT object
// cache.
typedef std::pair<InternedString, ConcreteCompilerVariable*> Entry;
std::vector<Entry> sorted_pred_st(pred_st->begin(), pred_st->end());
std::sort(sorted_pred_st.begin(), sorted_pred_st.end(),
[](const Entry& lhs, const Entry& rhs) { return lhs.first < rhs.first; });
for (auto& entry : sorted_pred_st) {
InternedString name = entry.first;
ConcreteCompilerVariable* cv = entry.second; // incoming CCV from predecessor block
// printf("block %d: adding phi for %s from pred %d\n", block->idx, name.c_str(), pred->idx);
llvm::PHINode* phi = emitter->getBuilder()->CreatePHI(cv->getType()->llvmType(),
block->predecessors.size(), name.str());
......@@ -749,7 +758,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
ConcreteCompilerVariable* var = new ConcreteCompilerVariable(cv->getType(), phi, true);
generator->giveLocalSymbol(name, var);
(*phis)[it->first] = std::make_pair(it->second->getType(), phi);
(*phis)[name] = std::make_pair(cv->getType(), phi);
}
}
}
......@@ -959,6 +968,9 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
source->cfg->print();
assert(g.cur_module == NULL);
clearRelocatableSymsMap();
std::string name = getUniqueFunctionName(nameprefix, effort, entry_descriptor);
g.cur_module = new llvm::Module(name, g.context);
#if LLVMREV < 217070 // not sure if this is the right rev
......@@ -1010,7 +1022,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
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*/);
......
......@@ -156,8 +156,6 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) {
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();
static StatCounter us_jitting("us_compiling_jitting");
us_jitting.log(us);
......@@ -243,7 +241,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
CompiledFunction* cf = 0;
if (effort == EffortLevel::INTERPRETED) {
assert(!entry_descriptor);
cf = new CompiledFunction(0, spec, true, NULL, NULL, effort, 0);
cf = new CompiledFunction(0, spec, true, NULL, effort, 0);
} else {
cf = doCompile(source, &f->param_names, entry_descriptor, effort, spec, name);
compileIR(cf, effort);
......@@ -651,21 +649,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
#endif
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
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));
cl_f->addVersion(new CompiledFunction(NULL, spec, false, f, EffortLevel::MAXIMAL, NULL));
}
}
This diff is collapsed.
......@@ -80,7 +80,7 @@ llvm::Constant* getStringConstantPtr(const std::string& str) {
strings[str] = 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
......@@ -92,6 +92,33 @@ llvm::Constant* getStringConstantPtr(const char* str) {
// 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),
// 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) {
assert(type);
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) {
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) {
return llvm::ConstantInt::get(t, n);
}
......
......@@ -27,10 +27,15 @@ namespace pyston {
llvm::Constant* getStringConstantPtr(const std::string& 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* getConstantInt(int64_t val);
llvm::Constant* getConstantDouble(double val);
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);
}
......
......@@ -20,6 +20,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
#include "codegen/irgen/util.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/util.h"
......@@ -206,7 +207,11 @@ void PystonMemoryManager::invalidateInstructionCache() {
}
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)
return base;
......@@ -214,7 +219,7 @@ uint64_t PystonMemoryManager::getSymbolAddress(const std::string& 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;
}
......
......@@ -20,6 +20,7 @@
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "codegen/compvars.h"
#include "codegen/irgen/util.h"
#include "codegen/stackmaps.h"
#include "core/common.h"
#include "core/options.h"
......@@ -41,7 +42,7 @@ int ICSetupInfo::totalSize() const {
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,
TypeRecorder* type_recorder) {
......@@ -165,9 +166,12 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
const StackMap::StackSizeRecord& stack_size_record = stackmap->stack_size_records[0];
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);
void* dst_func = new_patchpoints[r->id].second;
if (VERBOSITY() >= 2) {
printf("Processing pp %ld; [%d, %d)\n", reinterpret_cast<int64_t>(pp), r->offset,
r->offset + pp->patchpointSize());
......@@ -183,6 +187,9 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
uint8_t* start_addr = (uint8_t*)pp->parentFunction()->code + r->offset;
uint8_t* end_addr = start_addr + pp->patchpointSize();
if (ENABLE_JIT_OBJECT_CACHE)
setSlowpathFunc(start_addr, dst_func);
// TODO shouldn't have to do it this way
void* slowpath_func = extractSlowpathFunc(start_addr);
......@@ -270,7 +277,8 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
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();
if (ic)
delete ic;
......@@ -279,13 +287,14 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
new_patchpoints.clear();
}
PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo,
int num_ic_stackmap_args) {
PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetupInfo* icinfo, int num_ic_stackmap_args,
void* func_addr) {
if (icinfo == NULL)
assert(num_ic_stackmap_args == 0);
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;
}
......
......@@ -53,10 +53,12 @@ private:
int num_frame_stackmap_args;
std::vector<FrameVarInfo> frame_vars;
unsigned int id;
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),
num_frame_stackmap_args(-1) {}
: parent_cf(parent_cf), icinfo(icinfo), num_ic_stackmap_args(num_ic_stackmap_args), num_frame_stackmap_args(-1),
id(0) {}
public:
const ICSetupInfo* getICInfo() { return icinfo; }
......@@ -84,11 +86,14 @@ public:
return num_frame_stackmap_args;
}
unsigned int getId() const { return id; }
void parseLocationMap(StackMap::Record* r, LocationMap* map);
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 {
......
......@@ -261,7 +261,6 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, 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_);
GET(raise0);
GET(raise3);
......
......@@ -49,7 +49,7 @@ struct GlobalFuncs {
llvm::Value* exec;
llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel;
llvm::Value* __cxa_begin_catch, *__cxa_end_catch;
llvm::Value* __cxa_end_catch;
llvm::Value* raise0, *raise3;
llvm::Value* deopt;
......
......@@ -32,11 +32,113 @@
namespace pyston {
// TODO shouldn't be recording this in a global variable
static StackMap* cur_map = NULL;
static uint64_t stackmap_address = 0;
StackMap* parseStackMap() {
StackMap* rtn = cur_map;
cur_map = NULL;
return rtn;
if (!stackmap_address)
return NULL;
if (VERBOSITY() >= 3)
printf("Found the stackmaps at stackmap_address 0x%lx\n", stackmap_address);
StackMap* cur_map = new StackMap();
union {
const int8_t* i8;
const int16_t* i16;
const int32_t* i32;
const int64_t* i64;
const uint8_t* u8;
const uint16_t* u16;
const uint32_t* u32;
const uint64_t* u64;
const StackMap::Record::Location* record_loc;
const StackMap::Record::LiveOut* record_liveout;
const StackMap::StackSizeRecord* size_record;
} ptr;
const int8_t* start_ptr = ptr.i8 = (const int8_t*)stackmap_address;
cur_map->header = *ptr.u32++; // header
#if LLVMREV < 200481
int nfunctions = 0;
#else
int nfunctions = *ptr.u32++;
#endif
int nconstants = *ptr.u32++;
int nrecords = *ptr.u32++;
if (VERBOSITY() >= 3)
printf("%d functions\n", nfunctions);
for (int i = 0; i < nfunctions; i++) {
const StackMap::StackSizeRecord& size_record = *ptr.size_record++;
cur_map->stack_size_records.push_back(size_record);
if (VERBOSITY() >= 3)
printf("function %d: offset 0x%lx, stack size 0x%lx\n", i, size_record.offset, size_record.stack_size);
}
if (VERBOSITY() >= 3)
printf("%d constants\n", nconstants);
for (int i = 0; i < nconstants; i++) {
uint64_t constant = *ptr.u64++;
if (VERBOSITY() >= 3)
printf("Constant %d: %ld\n", i, constant);
cur_map->constants.push_back(constant);
}
if (VERBOSITY() >= 3)
printf("%d records\n", nrecords);
for (int i = 0; i < nrecords; i++) {
StackMap::Record* record = new StackMap::Record();
cur_map->records.push_back(record);
record->id = *ptr.u64++;
record->offset = *ptr.u32++;
record->flags = *ptr.u16++; // reserved (record flags)
int numlocations = *ptr.u16++;
if (VERBOSITY() >= 3)
printf("Stackmap record %ld at 0x%x has %d locations:\n", record->id, record->offset, numlocations);
for (int j = 0; j < numlocations; j++) {
assert(sizeof(StackMap::Record::Location) == sizeof(*ptr.u64));
const StackMap::Record::Location& r = *ptr.record_loc++;
record->locations.push_back(r);
// from http://lxr.free-electrons.com/source/tools/perf/arch/x86/util/dwarf-regs.c
// TODO this probably can be fetched more portably from the llvm target files
const char* dwarf_reg_names[] = {
"%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
};
if (VERBOSITY() >= 3) {
if (r.type == 1) {
printf("Location %d: type %d (reg), reg %d (%s), offset %d\n", j, r.type, r.regnum,
dwarf_reg_names[r.regnum], r.offset);
} else {
printf("Location %d: type %d, reg %d, offset %d\n", j, r.type, r.regnum, r.offset);
}
}
}
ptr.u16++; // padding
int num_live_outs = *ptr.u16++;
for (int i = 0; i < num_live_outs; i++) {
const StackMap::Record::LiveOut& r = *ptr.record_liveout++;
record->live_outs.push_back(r);
if (VERBOSITY() >= 3) {
printf("Live out %d: reg #%d (?), size %d\n", i, r.regnum, r.size);
}
}
if (num_live_outs % 2 == 0)
ptr.u32++; // pad to 8-byte boundary
}
stackmap_address = 0;
return cur_map;
}
class StackmapJITEventListener : public llvm::JITEventListener {
......@@ -68,112 +170,9 @@ void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFil
assert(!code);
if (name == ".llvm_stackmaps") {
uint64_t stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address == 0);
stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address > 0);
if (VERBOSITY() >= 3)
printf("Found the stackmaps at stackmap_address 0x%lx\n", stackmap_address);
assert(cur_map == NULL);
cur_map = new StackMap();
union {
const int8_t* i8;
const int16_t* i16;
const int32_t* i32;
const int64_t* i64;
const uint8_t* u8;
const uint16_t* u16;
const uint32_t* u32;
const uint64_t* u64;
const StackMap::Record::Location* record_loc;
const StackMap::Record::LiveOut* record_liveout;
const StackMap::StackSizeRecord* size_record;
} ptr;
const int8_t* start_ptr = ptr.i8 = (const int8_t*)stackmap_address;
cur_map->header = *ptr.u32++; // header
#if LLVMREV < 200481
int nfunctions = 0;
#else
int nfunctions = *ptr.u32++;
#endif
int nconstants = *ptr.u32++;
int nrecords = *ptr.u32++;
if (VERBOSITY() >= 3)
printf("%d functions\n", nfunctions);
for (int i = 0; i < nfunctions; i++) {
const StackMap::StackSizeRecord& size_record = *ptr.size_record++;
cur_map->stack_size_records.push_back(size_record);
if (VERBOSITY() >= 3)
printf("function %d: offset 0x%lx, stack size 0x%lx\n", i, size_record.offset,
size_record.stack_size);
}
if (VERBOSITY() >= 3)
printf("%d constants\n", nconstants);
for (int i = 0; i < nconstants; i++) {
uint64_t constant = *ptr.u64++;
if (VERBOSITY() >= 3)
printf("Constant %d: %ld\n", i, constant);
cur_map->constants.push_back(constant);
}
if (VERBOSITY() >= 3)
printf("%d records\n", nrecords);
for (int i = 0; i < nrecords; i++) {
StackMap::Record* record = new StackMap::Record();
cur_map->records.push_back(record);
record->id = *ptr.u64++;
record->offset = *ptr.u32++;
record->flags = *ptr.u16++; // reserved (record flags)
int numlocations = *ptr.u16++;
if (VERBOSITY() >= 3)
printf("Stackmap record %ld at 0x%x has %d locations:\n", record->id, record->offset, numlocations);
for (int j = 0; j < numlocations; j++) {
assert(sizeof(StackMap::Record::Location) == sizeof(*ptr.u64));
const StackMap::Record::Location& r = *ptr.record_loc++;
record->locations.push_back(r);
// from http://lxr.free-electrons.com/source/tools/perf/arch/x86/util/dwarf-regs.c
// TODO this probably can be fetched more portably from the llvm target files
const char* dwarf_reg_names[] = {
"%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
};
if (VERBOSITY() >= 3) {
if (r.type == 1) {
printf("Location %d: type %d (reg), reg %d (%s), offset %d\n", j, r.type, r.regnum,
dwarf_reg_names[r.regnum], r.offset);
} else {
printf("Location %d: type %d, reg %d, offset %d\n", j, r.type, r.regnum, r.offset);
}
}
}
ptr.u16++; // padding
int num_live_outs = *ptr.u16++;
for (int i = 0; i < num_live_outs; i++) {
const StackMap::Record::LiveOut& r = *ptr.record_liveout++;
record->live_outs.push_back(r);
if (VERBOSITY() >= 3) {
printf("Live out %d: reg #%d (?), size %d\n", i, r.regnum, r.size);
}
}
if (num_live_outs % 2 == 0)
ptr.u32++; // pad to 8-byte boundary
}
uint64_t stackmap_size = sec.getSize();
ASSERT(ptr.i8 - start_ptr == stackmap_size, "%ld %ld", ptr.i8 - start_ptr, stackmap_size);
}
}
}
......
......@@ -24,7 +24,7 @@
namespace pyston {
#ifndef NDEBUG
#ifdef DEBUG_LINE_NUMBERS
int AST::next_lineno = 100000;
AST::AST(AST_TYPE::AST_TYPE type) : type(type), lineno(++next_lineno) {
......@@ -1655,7 +1655,12 @@ bool PrintVisitor::visit_return(AST_Return* node) {
}
bool PrintVisitor::visit_set(AST_Set* node) {
assert(node->elts.size());
// An empty set literal is not writeable in Python (it's a dictionary),
// but we sometimes generate it (ex in set comprehension lowering).
// Just to make it clear when printing, print empty set literals as "SET{}".
if (!node->elts.size())
printf("SET");
printf("{");
bool first = true;
......
......@@ -154,16 +154,17 @@ public:
virtual void accept(ASTVisitor* v) = 0;
#ifndef NDEBUG
// #define DEBUG_LINE_NUMBERS 1
#ifdef DEBUG_LINE_NUMBERS
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.
static int next_lineno;
public:
AST(AST_TYPE::AST_TYPE type);
#else
AST(AST_TYPE::AST_TYPE type) : type(type) {}
AST(AST_TYPE::AST_TYPE type) : type(type), lineno(0), col_offset(0) {}
#endif
AST(AST_TYPE::AST_TYPE type, uint32_t lineno, uint32_t col_offset = 0)
: type(type), lineno(lineno), col_offset(col_offset) {}
......
This diff is collapsed.
......@@ -50,6 +50,8 @@ int OSR_THRESHOLD_T2 = 10000;
int REOPT_THRESHOLD_T2 = 10000;
int SPECULATION_THRESHOLD = 100;
int MAX_OBJECT_CACHE_ENTRIES = 500;
static bool _GLOBAL_ENABLE = 1;
bool ENABLE_ICS = 1 && _GLOBAL_ENABLE;
bool ENABLE_ICGENERICS = 1 && ENABLE_ICS;
......@@ -71,6 +73,7 @@ bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE;
bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE;
bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE;
bool ENABLE_RUNTIME_ICS = 1 && _GLOBAL_ENABLE;
bool ENABLE_JIT_OBJECT_CACHE = 1 && _GLOBAL_ENABLE;
bool ENABLE_FRAME_INTROSPECTION = 1;
bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION;
......
......@@ -35,6 +35,7 @@ extern int OSR_THRESHOLD_INTERPRETER, REOPT_THRESHOLD_INTERPRETER;
extern int OSR_THRESHOLD_BASELINE, REOPT_THRESHOLD_BASELINE;
extern int OSR_THRESHOLD_T2, REOPT_THRESHOLD_T2;
extern int SPECULATION_THRESHOLD;
extern int MAX_OBJECT_CACHE_ENTRIES;
extern bool SHOW_DISASM, FORCE_INTERPRETER, FORCE_OPTIMIZE, PROFILE, DUMPJIT, TRAP, USE_STRIPPED_STDLIB,
CONTINUE_AFTER_FATAL, ENABLE_INTERPRETER, ENABLE_PYPA_PARSER, USE_REGALLOC_BASIC, PAUSE_AT_ABORT;
......@@ -42,7 +43,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,
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_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.
extern bool BOOLS_AS_I64;
......
......@@ -73,10 +73,11 @@ public:
return this->_str == rhs._str;
}
// This function is slow because it does a string < string comparison and should be avoided.
bool operator<(InternedString rhs) const {
assert(this->_str);
assert(this->pool == rhs.pool);
return this->_str < rhs._str;
return *this->_str < *rhs._str;
}
friend class InternedStringPool;
......
......@@ -188,7 +188,6 @@ public:
uintptr_t code_start;
};
int code_size;
llvm::Value* llvm_code; // the llvm callable.
EffortLevel effort;
......@@ -200,10 +199,9 @@ public:
std::vector<ICInfo*> ics;
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),
code(code), llvm_code(llvm_code), effort(effort), times_called(0), times_speculation_failed(0),
location_map(nullptr) {
code(code), effort(effort), times_called(0), times_speculation_failed(0), location_map(nullptr) {
assert((spec != NULL) + (entry_descriptor != NULL) == 1);
}
......@@ -307,7 +305,6 @@ public:
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
assert(compiled->clfunc == NULL);
assert(compiled->is_interpreted == (compiled->code == NULL));
assert(compiled->is_interpreted == (compiled->llvm_code == NULL));
compiled->clfunc = this;
if (compiled->entry_descriptor == NULL) {
......
......@@ -9,7 +9,7 @@ add_custom_target(unittests)
macro(add_unittest unittest)
add_executable(${unittest}_unittest EXCLUDE_FROM_ALL ${unittest}.cpp $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON>)
target_link_libraries(${unittest}_unittest stdlib sqlite3 gmp ssl crypto readline pypa double-conversion unwind gtest gtest_main ${LLVM_LIBS} ${LIBLZMA_LIBRARIES})
target_link_libraries(${unittest}_unittest stdlib sqlite3 gmp ssl crypto readline pypa liblz4 double-conversion unwind gtest gtest_main ${LLVM_LIBS} ${LIBLZMA_LIBRARIES})
add_dependencies(unittests ${unittest}_unittest)
endmacro()
......
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