Commit daefbbb6 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Run clang-format ("make format") on the codebase

Changed the indentation of pretty much the entire codebase.

It did some things that I don't like that seem not configurable,
but overall it seems like an improvement, and nice to have a
canonical format going forward.
parent c0c916c4
...@@ -22,21 +22,20 @@ ...@@ -22,21 +22,20 @@
namespace pyston { namespace pyston {
template <typename T> template <typename T> class BBAnalyzer {
class BBAnalyzer { public:
public: typedef std::unordered_map<std::string, T> Map;
typedef std::unordered_map<std::string, T> Map; typedef std::unordered_map<CFGBlock*, Map> AllMap;
typedef std::unordered_map<CFGBlock*, Map> AllMap;
virtual ~BBAnalyzer() {} virtual ~BBAnalyzer() {}
virtual T merge(T from, T into) const = 0; virtual T merge(T from, T into) const = 0;
virtual T mergeBlank(T into) const = 0; virtual T mergeBlank(T into) const = 0;
virtual void processBB(Map &starting, CFGBlock *block) const = 0; virtual void processBB(Map& starting, CFGBlock* block) const = 0;
}; };
template <typename T> template <typename T>
typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &analyzer, bool reverse) { typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& analyzer, bool reverse) {
assert(!reverse); assert(!reverse);
typedef typename BBAnalyzer<T>::Map Map; typedef typename BBAnalyzer<T>::Map Map;
...@@ -49,17 +48,18 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> & ...@@ -49,17 +48,18 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &
q.push_back(cfg->getStartingBlock()); q.push_back(cfg->getStartingBlock());
while (q.size()) { while (q.size()) {
CFGBlock *block = q.back(); CFGBlock* block = q.back();
q.pop_back(); q.pop_back();
Map initial = states[block]; Map initial = states[block];
if (VERBOSITY("analysis") >= 2) printf("fpc on block %d - %ld entries\n", block->idx, initial.size()); if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %ld entries\n", block->idx, initial.size());
Map ending = Map(initial); Map ending = Map(initial);
analyzer.processBB(ending, block); analyzer.processBB(ending, block);
for (int i = 0; i < block->successors.size(); i++) { for (int i = 0; i < block->successors.size(); i++) {
CFGBlock *next_block = block->successors[i]; CFGBlock* next_block = block->successors[i];
bool changed = false; bool changed = false;
bool initial = false; bool initial = false;
if (states.count(next_block) == 0) { if (states.count(next_block) == 0) {
...@@ -67,8 +67,8 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> & ...@@ -67,8 +67,8 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &
initial = true; initial = true;
} }
Map &next = states[next_block]; Map& next = states[next_block];
for (const auto &p : ending) { for (const auto& p : ending) {
if (next.count(p.first) == 0) { if (next.count(p.first) == 0) {
changed = true; changed = true;
if (initial) { if (initial) {
...@@ -77,7 +77,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> & ...@@ -77,7 +77,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &
next[p.first] = analyzer.mergeBlank(p.second); next[p.first] = analyzer.mergeBlank(p.second);
} }
} else { } else {
T &next_elt = next[p.first]; T& next_elt = next[p.first];
T new_elt = analyzer.merge(p.second, next_elt); T new_elt = analyzer.merge(p.second, next_elt);
if (next_elt != new_elt) { if (next_elt != new_elt) {
...@@ -87,7 +87,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> & ...@@ -87,7 +87,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &
} }
} }
for (const auto &p : ending) { for (const auto& p : ending) {
if (ending.count(p.first)) if (ending.count(p.first))
continue; continue;
...@@ -108,7 +108,6 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> & ...@@ -108,7 +108,6 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T> &
return states; return states;
} }
} }
#endif #endif
This diff is collapsed.
...@@ -27,52 +27,50 @@ class CFGBlock; ...@@ -27,52 +27,50 @@ class CFGBlock;
class ScopeInfo; class ScopeInfo;
class LivenessAnalysis { class LivenessAnalysis {
public: public:
bool isLiveAtEnd(const std::string &name, CFGBlock *block); bool isLiveAtEnd(const std::string& name, CFGBlock* block);
}; };
class DefinednessAnalysis { class DefinednessAnalysis {
public: public:
enum DefinitionLevel { enum DefinitionLevel {
Undefined, Undefined,
PotentiallyDefined, PotentiallyDefined,
Defined, Defined,
}; };
typedef std::unordered_set<std::string> RequiredSet; typedef std::unordered_set<std::string> RequiredSet;
private: private:
std::unordered_map<CFGBlock*, std::unordered_map<std::string, DefinitionLevel> > results; std::unordered_map<CFGBlock*, std::unordered_map<std::string, DefinitionLevel> > results;
std::unordered_map<CFGBlock*, const RequiredSet> defined; std::unordered_map<CFGBlock*, const RequiredSet> defined;
ScopeInfo *scope_info; ScopeInfo* scope_info;
public: public:
DefinednessAnalysis(AST_arguments *args, CFG* cfg, ScopeInfo *scope_info); DefinednessAnalysis(AST_arguments* args, CFG* cfg, ScopeInfo* scope_info);
DefinitionLevel isDefinedAt(const std::string &name, CFGBlock *block); DefinitionLevel isDefinedAt(const std::string& name, CFGBlock* block);
const RequiredSet& getDefinedNamesAt(CFGBlock *block); const RequiredSet& getDefinedNamesAt(CFGBlock* block);
}; };
class PhiAnalysis { class PhiAnalysis {
public: public:
typedef std::unordered_set<std::string> RequiredSet; typedef std::unordered_set<std::string> RequiredSet;
private: private:
DefinednessAnalysis definedness; DefinednessAnalysis definedness;
LivenessAnalysis *liveness; LivenessAnalysis* liveness;
std::unordered_map<CFGBlock*, const RequiredSet> required_phis; std::unordered_map<CFGBlock*, const RequiredSet> required_phis;
public: public:
PhiAnalysis(AST_arguments*, CFG* cfg, LivenessAnalysis *liveness, ScopeInfo *scope_info); PhiAnalysis(AST_arguments*, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info);
bool isRequired(const std::string &name, CFGBlock* block); bool isRequired(const std::string& name, CFGBlock* block);
bool isRequiredAfter(const std::string &name, CFGBlock* block); bool isRequiredAfter(const std::string& name, CFGBlock* block);
const RequiredSet& getAllRequiredAfter(CFGBlock *block); const RequiredSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllDefinedAt(CFGBlock *block); const RequiredSet& getAllDefinedAt(CFGBlock* block);
bool isPotentiallyUndefinedAfter(const std::string &name, CFGBlock* block); bool isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block);
}; };
LivenessAnalysis* computeLivenessInfo(CFG*); LivenessAnalysis* computeLivenessInfo(CFG*);
PhiAnalysis* computeRequiredPhis(AST_arguments*, CFG*, LivenessAnalysis*, ScopeInfo* scope_Info); PhiAnalysis* computeRequiredPhis(AST_arguments*, CFG*, LivenessAnalysis*, ScopeInfo* scope_Info);
} }
#endif #endif
This diff is collapsed.
...@@ -23,38 +23,36 @@ class AST; ...@@ -23,38 +23,36 @@ class AST;
class AST_Module; class AST_Module;
class ScopeInfo { class ScopeInfo {
public: public:
virtual ~ScopeInfo() {} virtual ~ScopeInfo() {}
virtual ScopeInfo* getParent() = 0; virtual ScopeInfo* getParent() = 0;
virtual bool createsClosure() = 0; virtual bool createsClosure() = 0;
virtual bool takesClosure() = 0; virtual bool takesClosure() = 0;
virtual bool refersToGlobal(const std::string &name) = 0; virtual bool refersToGlobal(const std::string& name) = 0;
virtual bool refersToClosure(const std::string name) = 0; virtual bool refersToClosure(const std::string name) = 0;
virtual bool saveInClosure(const std::string name) = 0; virtual bool saveInClosure(const std::string name) = 0;
}; };
class ScopingAnalysis { class ScopingAnalysis {
public: public:
struct ScopeNameUsage; struct ScopeNameUsage;
typedef std::unordered_map<AST*, ScopeNameUsage*> NameUsageMap; typedef std::unordered_map<AST*, ScopeNameUsage*> NameUsageMap;
private: private:
std::unordered_map<AST*, ScopeInfo*> scopes;
AST_Module* parent_module;
std::unordered_map<AST*, ScopeInfo*> scopes; ScopeInfo* analyzeSubtree(AST* node);
AST_Module* parent_module; void processNameUsages(NameUsageMap* usages);
ScopeInfo* analyzeSubtree(AST* node); public:
void processNameUsages(NameUsageMap* usages); ScopingAnalysis(AST_Module* m);
ScopeInfo* getScopeInfoForNode(AST* node);
public:
ScopingAnalysis(AST_Module *m);
ScopeInfo* getScopeInfoForNode(AST* node);
}; };
ScopingAnalysis* runScopingAnalysis(AST_Module* m); ScopingAnalysis* runScopingAnalysis(AST_Module* m);
} }
#endif #endif
This diff is collapsed.
...@@ -26,22 +26,23 @@ namespace pyston { ...@@ -26,22 +26,23 @@ namespace pyston {
class ScopeInfo; class ScopeInfo;
class TypeAnalysis { class TypeAnalysis {
public: public:
enum SpeculationLevel { enum SpeculationLevel {
NONE, NONE,
SOME, SOME,
}; };
virtual ~TypeAnalysis() {} virtual ~TypeAnalysis() {}
virtual ConcreteCompilerType* getTypeAtBlockStart(const std::string &name, CFGBlock* block) = 0; virtual ConcreteCompilerType* getTypeAtBlockStart(const std::string& name, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(const std::string &name, CFGBlock* block) = 0; virtual ConcreteCompilerType* getTypeAtBlockEnd(const std::string& name, CFGBlock* block) = 0;
virtual BoxedClass* speculatedExprClass(AST_expr*) = 0; virtual BoxedClass* speculatedExprClass(AST_expr*) = 0;
}; };
//TypeAnalysis* analyze(CFG *cfg, std::unordered_map<std::string, ConcreteCompilerType*> arg_types); // TypeAnalysis* analyze(CFG *cfg, std::unordered_map<std::string, ConcreteCompilerType*> arg_types);
TypeAnalysis* doTypeAnalysis(CFG *cfg, const std::vector<AST_expr*> &arg_names, const std::vector<ConcreteCompilerType*> &arg_types, TypeAnalysis::SpeculationLevel speculation, ScopeInfo *scope_info); TypeAnalysis* doTypeAnalysis(CFG* cfg, const std::vector<AST_expr*>& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
} }
#endif #endif
...@@ -22,22 +22,7 @@ namespace pyston { ...@@ -22,22 +22,7 @@ namespace pyston {
namespace assembler { namespace assembler {
const char* regnames[] = { const char* regnames[] = {
"rax", "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
}; };
void Register::dump() const { void Register::dump() const {
...@@ -85,7 +70,7 @@ GenericRegister GenericRegister::fromDwarf(int dwarf_regnum) { ...@@ -85,7 +70,7 @@ GenericRegister GenericRegister::fromDwarf(int dwarf_regnum) {
void Assembler::emitArith(Immediate imm, Register r, int opcode) { void Assembler::emitArith(Immediate imm, Register r, int opcode) {
//assert(r != RSP && "This breaks unwinding, please don't use."); // assert(r != RSP && "This breaks unwinding, please don't use.");
int64_t amount = imm.val; int64_t amount = imm.val;
RELEASE_ASSERT(-0x80 <= amount && amount < 0x80 && "unsupported", ""); RELEASE_ASSERT(-0x80 <= amount && amount < 0x80 && "unsupported", "");
...@@ -142,7 +127,6 @@ void Assembler::emitSIB(uint8_t scalebits, uint8_t index, uint8_t base) { ...@@ -142,7 +127,6 @@ void Assembler::emitSIB(uint8_t scalebits, uint8_t index, uint8_t base) {
void Assembler::mov(Immediate val, Register dest) { void Assembler::mov(Immediate val, Register dest) {
int rex = REX_W; int rex = REX_W;
...@@ -159,7 +143,7 @@ void Assembler::mov(Immediate val, Register dest) { ...@@ -159,7 +143,7 @@ void Assembler::mov(Immediate val, Register dest) {
void Assembler::movq(Immediate src, Indirect dest) { void Assembler::movq(Immediate src, Indirect dest) {
int64_t src_val = src.val; int64_t src_val = src.val;
assert((-1L<<31) <= src_val && src_val < (1L<<31)-1); assert((-1L << 31) <= src_val && src_val < (1L << 31) - 1);
int rex = REX_W; int rex = REX_W;
...@@ -418,7 +402,7 @@ void Assembler::movsd(Indirect src, XMMRegister dest) { ...@@ -418,7 +402,7 @@ void Assembler::movsd(Indirect src, XMMRegister dest) {
void Assembler::push(Register reg) { void Assembler::push(Register reg) {
//assert(0 && "This breaks unwinding, please don't use."); // assert(0 && "This breaks unwinding, please don't use.");
assert(reg != RSP); // this might work but most likely a bug assert(reg != RSP); // this might work but most likely a bug
...@@ -433,7 +417,7 @@ void Assembler::push(Register reg) { ...@@ -433,7 +417,7 @@ void Assembler::push(Register reg) {
} }
void Assembler::pop(Register reg) { void Assembler::pop(Register reg) {
//assert(0 && "This breaks unwinding, please don't use."); // assert(0 && "This breaks unwinding, please don't use.");
assert(reg != RSP); // this might work but most likely a bug assert(reg != RSP); // this might work but most likely a bug
...@@ -467,7 +451,6 @@ void Assembler::inc(Indirect mem) { ...@@ -467,7 +451,6 @@ void Assembler::inc(Indirect mem) {
void Assembler::callq(Register r) { void Assembler::callq(Register r) {
assert(r == R11 && "untested"); assert(r == R11 && "untested");
...@@ -503,7 +486,7 @@ void Assembler::cmp(Register reg1, Register reg2) { ...@@ -503,7 +486,7 @@ void Assembler::cmp(Register reg1, Register reg2) {
void Assembler::cmp(Register reg, Immediate imm) { void Assembler::cmp(Register reg, Immediate imm) {
int64_t val = imm.val; int64_t val = imm.val;
assert((-1L<<31) <= val && val < (1L<<31)-1); assert((-1L << 31) <= val && val < (1L << 31) - 1);
int reg_idx = reg.regnum; int reg_idx = reg.regnum;
...@@ -522,7 +505,7 @@ void Assembler::cmp(Register reg, Immediate imm) { ...@@ -522,7 +505,7 @@ void Assembler::cmp(Register reg, Immediate imm) {
void Assembler::cmp(Indirect mem, Immediate imm) { void Assembler::cmp(Indirect mem, Immediate imm) {
int64_t val = imm.val; int64_t val = imm.val;
assert((-1L<<31) <= val && val < (1L<<31)-1); assert((-1L << 31) <= val && val < (1L << 31) - 1);
int src_idx = mem.base.regnum; int src_idx = mem.base.regnum;
...@@ -607,7 +590,8 @@ void Assembler::jmp_cond(JumpDestination dest, ConditionCode condition) { ...@@ -607,7 +590,8 @@ void Assembler::jmp_cond(JumpDestination dest, ConditionCode condition) {
assert(dest.type == JumpDestination::FROM_START); assert(dest.type == JumpDestination::FROM_START);
int offset = dest.offset - (addr - start_addr) - 2; int offset = dest.offset - (addr - start_addr) - 2;
if (unlikely) offset--; if (unlikely)
offset--;
if (offset >= -0x80 && offset < 0x80) { if (offset >= -0x80 && offset < 0x80) {
if (unlikely) if (unlikely)
...@@ -681,11 +665,11 @@ uint8_t* Assembler::emitCall(void* ptr, Register scratch) { ...@@ -681,11 +665,11 @@ uint8_t* Assembler::emitCall(void* ptr, Register scratch) {
return addr; return addr;
} }
void Assembler::emitBatchPush(StackInfo stack_info, const std::vector<GenericRegister> &to_push) { void Assembler::emitBatchPush(StackInfo stack_info, const std::vector<GenericRegister>& to_push) {
assert(stack_info.has_scratch); assert(stack_info.has_scratch);
int offset = 0; int offset = 0;
for (const GenericRegister &r : to_push) { for (const GenericRegister& r : to_push) {
assert(stack_info.scratch_bytes >= offset + 8); assert(stack_info.scratch_bytes >= offset + 8);
Indirect next_slot(RBP, offset + stack_info.scratch_rbp_offset); Indirect next_slot(RBP, offset + stack_info.scratch_rbp_offset);
...@@ -704,11 +688,11 @@ void Assembler::emitBatchPush(StackInfo stack_info, const std::vector<GenericReg ...@@ -704,11 +688,11 @@ void Assembler::emitBatchPush(StackInfo stack_info, const std::vector<GenericReg
} }
} }
void Assembler::emitBatchPop(StackInfo stack_info, const std::vector<GenericRegister> &to_push) { void Assembler::emitBatchPop(StackInfo stack_info, const std::vector<GenericRegister>& to_push) {
assert(stack_info.has_scratch); assert(stack_info.has_scratch);
int offset = 0; int offset = 0;
for (const GenericRegister &r : to_push) { for (const GenericRegister& r : to_push) {
assert(stack_info.scratch_bytes >= offset + 8); assert(stack_info.scratch_bytes >= offset + 8);
Indirect next_slot(RBP, offset + stack_info.scratch_rbp_offset); Indirect next_slot(RBP, offset + stack_info.scratch_rbp_offset);
...@@ -747,16 +731,17 @@ void Assembler::emitAnnotation(int num) { ...@@ -747,16 +731,17 @@ void Assembler::emitAnnotation(int num) {
uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uint8_t* end_addr, StackInfo stack_info, const std::unordered_set<int> &live_outs) { uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uint8_t* end_addr, StackInfo stack_info,
const std::unordered_set<int>& live_outs) {
assert(start_addr < slowpath_start); assert(start_addr < slowpath_start);
static const int INITIAL_CALL_SIZE = 13; static const int INITIAL_CALL_SIZE = 13;
assert(end_addr > slowpath_start + INITIAL_CALL_SIZE); assert(end_addr > slowpath_start + INITIAL_CALL_SIZE);
#ifndef NDEBUG #ifndef NDEBUG
//if (VERBOSITY()) printf("initializing patchpoint at %p - %p\n", addr, addr + size); // if (VERBOSITY()) printf("initializing patchpoint at %p - %p\n", addr, addr + size);
//for (int i = 0; i < size; i++) { // for (int i = 0; i < size; i++) {
//printf("%02x ", *(addr + i)); // printf("%02x ", *(addr + i));
//} //}
//printf("\n"); // printf("\n");
// Check the exact form of the patchpoint call. // Check the exact form of the patchpoint call.
// It's important to make sure that the only live registers // It's important to make sure that the only live registers
...@@ -800,8 +785,8 @@ uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uin ...@@ -800,8 +785,8 @@ uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uin
Assembler assem(slowpath_start, end_addr - slowpath_start); Assembler assem(slowpath_start, end_addr - slowpath_start);
//if (regs_to_spill.size()) // if (regs_to_spill.size())
//assem.trap(); // assem.trap();
assem.emitBatchPush(stack_info, regs_to_spill); assem.emitBatchPush(stack_info, regs_to_spill);
uint8_t* rtn = assem.emitCall(call_addr, R11); uint8_t* rtn = assem.emitCall(call_addr, R11);
assem.emitBatchPop(stack_info, regs_to_spill); assem.emitBatchPop(stack_info, regs_to_spill);
...@@ -809,6 +794,5 @@ uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uin ...@@ -809,6 +794,5 @@ uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uin
return rtn; return rtn;
} }
} }
} }
...@@ -27,102 +27,103 @@ namespace assembler { ...@@ -27,102 +27,103 @@ namespace assembler {
class BoxedClass; class BoxedClass;
enum ConditionCode { enum ConditionCode {
COND_OVERFLOW = 0, // OF=1: O COND_OVERFLOW = 0, // OF=1: O
COND_NOT_OVERFLOW = 1, // OF=0: NO COND_NOT_OVERFLOW = 1, // OF=0: NO
// next 4 are unsigned: // next 4 are unsigned:
COND_BELOW = 2, // CF=1: B/NAE/C COND_BELOW = 2, // CF=1: B/NAE/C
COND_NOT_BELOW = 3, // CF=0: NB/AE/C COND_NOT_BELOW = 3, // CF=0: NB/AE/C
COND_EQUAL = 4, // ZF=0: Z/E COND_EQUAL = 4, // ZF=0: Z/E
COND_NOT_EQUAL = 5, // ZF=1: NZ/NE COND_NOT_EQUAL = 5, // ZF=1: NZ/NE
COND_NOT_ZERO = 5, // ZF=1: NZ/NE COND_NOT_ZERO = 5, // ZF=1: NZ/NE
COND_NOT_ABOVE = 6, // CF=1: ZF=1: BE/NA COND_NOT_ABOVE = 6, // CF=1: ZF=1: BE/NA
COND_ABOVE = 7, // CF=0: ZF=0: NBE/A COND_ABOVE = 7, // CF=0: ZF=0: NBE/A
COND_SIGN = 8, // SF=1: S COND_SIGN = 8, // SF=1: S
COND_NOT_SIGN = 9, // SF=0: NS COND_NOT_SIGN = 9, // SF=0: NS
COND_PARITY_EVEN = 0xA, // PF=1: P/PE COND_PARITY_EVEN = 0xA, // PF=1: P/PE
COND_PARITY_ODD = 0xB, // PF=0: NP/PO COND_PARITY_ODD = 0xB, // PF=0: NP/PO
// next 4 are signed: // next 4 are signed:
COND_LESS = 0xC, // SF!=OF: L/NGE COND_LESS = 0xC, // SF!=OF: L/NGE
COND_NOT_LESS = 0xD, // SF==OF: NL/GE COND_NOT_LESS = 0xD, // SF==OF: NL/GE
COND_NOT_GREATER = 0xE, // ZF=1 || SF!=OF: LE/NG COND_NOT_GREATER = 0xE, // ZF=1 || SF!=OF: LE/NG
COND_GREATER = 0xF, // ZF=0 && SF==OF: NLE/G COND_GREATER = 0xF, // ZF=0 && SF==OF: NLE/G
}; };
class Assembler { class Assembler {
private: private:
uint8_t *const start_addr, *const end_addr; uint8_t* const start_addr, *const end_addr;
uint8_t *addr; uint8_t* addr;
static const uint8_t OPCODE_ADD = 0b000, OPCODE_SUB = 0b101; static const uint8_t OPCODE_ADD = 0b000, OPCODE_SUB = 0b101;
static const uint8_t REX_B = 1, REX_X = 2, REX_R = 4, REX_W = 8; static const uint8_t REX_B = 1, REX_X = 2, REX_R = 4, REX_W = 8;
private:
void emitByte(uint8_t b); private:
void emitInt(int64_t n, int bytes); void emitByte(uint8_t b);
void emitRex(uint8_t rex); void emitInt(int64_t n, int bytes);
void emitModRM(uint8_t mod, uint8_t reg, uint8_t rm); void emitRex(uint8_t rex);
void emitSIB(uint8_t scalebits, uint8_t index, uint8_t base); void emitModRM(uint8_t mod, uint8_t reg, uint8_t rm);
void emitArith(Immediate imm, Register reg, int opcode); void emitSIB(uint8_t scalebits, uint8_t index, uint8_t base);
void emitArith(Immediate imm, Register reg, int opcode);
public:
Assembler(uint8_t* start, int size) : start_addr(start), end_addr(start + size), addr(start_addr) {} public:
Assembler(uint8_t* start, int size) : start_addr(start), end_addr(start + size), addr(start_addr) {}
void nop() { emitByte(0x90); }
void trap() { emitByte(0xcc); } void nop() { emitByte(0x90); }
void trap() { emitByte(0xcc); }
// some things (such as objdump) call this "movabs" if the immediate is 64-bit
void mov(Immediate imm, Register dest); // some things (such as objdump) call this "movabs" if the immediate is 64-bit
// not sure if we should use the 'q' suffix here, but this is the most ambiguous one; void mov(Immediate imm, Register dest);
// this does a 64-bit store of a 32-bit value. // not sure if we should use the 'q' suffix here, but this is the most ambiguous one;
void movq(Immediate imm, Indirect dest); // this does a 64-bit store of a 32-bit value.
void mov(Register src, Register dest); void movq(Immediate imm, Indirect dest);
void mov(Register src, Indirect dest); void mov(Register src, Register dest);
void mov(Indirect src, Register dest); void mov(Register src, Indirect dest);
void movsd(XMMRegister src, XMMRegister dest); void mov(Indirect src, Register dest);
void movsd(XMMRegister src, Indirect dest); void movsd(XMMRegister src, XMMRegister dest);
void movsd(Indirect src, XMMRegister dest); void movsd(XMMRegister src, Indirect dest);
void movsd(Indirect src, XMMRegister dest);
void push(Register reg);
void pop(Register reg); void push(Register reg);
void pop(Register reg);
void add(Immediate imm, Register reg);
void sub(Immediate imm, Register reg); void add(Immediate imm, Register reg);
void inc(Register reg); void sub(Immediate imm, Register reg);
void inc(Indirect mem); void inc(Register reg);
void inc(Indirect mem);
void callq(Register reg);
void callq(Register reg);
void cmp(Register reg1, Register reg2);
void cmp(Register reg, Immediate imm); void cmp(Register reg1, Register reg2);
void cmp(Indirect mem, Immediate imm); void cmp(Register reg, Immediate imm);
void cmp(Indirect mem, Register reg); void cmp(Indirect mem, Immediate imm);
void cmp(Indirect mem, Register reg);
void test(Register reg1, Register reg2);
void test(Register reg1, Register reg2);
void jmp_cond(JumpDestination dest, ConditionCode condition);
void jmp(JumpDestination dest); void jmp_cond(JumpDestination dest, ConditionCode condition);
void je(JumpDestination dest); void jmp(JumpDestination dest);
void jne(JumpDestination dest); void je(JumpDestination dest);
void jne(JumpDestination dest);
void set_cond(Register reg, ConditionCode condition);
void sete(Register reg); void set_cond(Register reg, ConditionCode condition);
void setz(Register reg) { sete(reg); } void sete(Register reg);
void setne(Register reg); void setz(Register reg) { sete(reg); }
void setnz(Register reg) { setne(reg); } void setne(Register reg);
void setnz(Register reg) { setne(reg); }
// Macros:
uint8_t* emitCall(void* func_addr, Register scratch); // Macros:
void emitBatchPop(StackInfo stack_info, const std::vector<GenericRegister> &to_push); uint8_t* emitCall(void* func_addr, Register scratch);
void emitBatchPush(StackInfo stack_info, const std::vector<GenericRegister> &to_push); void emitBatchPop(StackInfo stack_info, const std::vector<GenericRegister>& to_push);
void fillWithNops(); void emitBatchPush(StackInfo stack_info, const std::vector<GenericRegister>& to_push);
void fillWithNopsExcept(int bytes); void fillWithNops();
void emitAnnotation(int num); void fillWithNopsExcept(int bytes);
void emitAnnotation(int num);
bool isExactlyFull() { return addr == end_addr; }
bool isExactlyFull() { return addr == end_addr; }
}; };
uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uint8_t* end_addr, StackInfo stack_info, const std::unordered_set<int> &live_outs); uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uint8_t* end_addr, StackInfo stack_info,
const std::unordered_set<int>& live_outs);
} }
} }
......
...@@ -59,7 +59,8 @@ ICSlotRewrite::ICSlotRewrite(ICInfo* ic, const char* debug_name) : ic(ic), debug ...@@ -59,7 +59,8 @@ ICSlotRewrite::ICSlotRewrite(ICInfo* ic, const char* debug_name) : ic(ic), debug
assembler = new Assembler(buf, ic->getSlotSize()); assembler = new Assembler(buf, ic->getSlotSize());
assembler->nop(); assembler->nop();
if (VERBOSITY()) printf("starting %s icentry\n", debug_name); if (VERBOSITY())
printf("starting %s icentry\n", debug_name);
} }
ICSlotRewrite::~ICSlotRewrite() { ICSlotRewrite::~ICSlotRewrite() {
...@@ -67,27 +68,28 @@ ICSlotRewrite::~ICSlotRewrite() { ...@@ -67,27 +68,28 @@ ICSlotRewrite::~ICSlotRewrite() {
free(buf); free(buf);
} }
void ICSlotRewrite::commit(uint64_t decision_path, CommitHook *hook) { void ICSlotRewrite::commit(uint64_t decision_path, CommitHook* hook) {
bool still_valid = true; bool still_valid = true;
for (int i = 0; i < dependencies.size(); i++) { for (int i = 0; i < dependencies.size(); i++) {
int orig_version = dependencies[i].second; int orig_version = dependencies[i].second;
ICInvalidator *invalidator = dependencies[i].first; ICInvalidator* invalidator = dependencies[i].first;
if (orig_version != invalidator->version()) { if (orig_version != invalidator->version()) {
still_valid = false; still_valid = false;
break; break;
} }
} }
if (!still_valid) { if (!still_valid) {
if (VERBOSITY()) printf("not committing %s icentry since a dependency got updated before commit\n", debug_name); if (VERBOSITY())
printf("not committing %s icentry since a dependency got updated before commit\n", debug_name);
return; return;
} }
ICSlotInfo *ic_entry = ic->pickEntryForRewrite(decision_path, debug_name); ICSlotInfo* ic_entry = ic->pickEntryForRewrite(decision_path, debug_name);
if (ic_entry == NULL) if (ic_entry == NULL)
return; return;
for (int i = 0; i < dependencies.size(); i++) { for (int i = 0; i < dependencies.size(); i++) {
ICInvalidator *invalidator = dependencies[i].first; ICInvalidator* invalidator = dependencies[i].first;
invalidator->addDependent(ic_entry); invalidator->addDependent(ic_entry);
} }
...@@ -98,13 +100,13 @@ void ICSlotRewrite::commit(uint64_t decision_path, CommitHook *hook) { ...@@ -98,13 +100,13 @@ void ICSlotRewrite::commit(uint64_t decision_path, CommitHook *hook) {
assert(assembler->isExactlyFull()); assert(assembler->isExactlyFull());
//if (VERBOSITY()) printf("Commiting to %p-%p\n", start, start + ic->slot_size); // if (VERBOSITY()) printf("Commiting to %p-%p\n", start, start + ic->slot_size);
memcpy(slot_start, buf, ic->getSlotSize()); memcpy(slot_start, buf, ic->getSlotSize());
llvm::sys::Memory::InvalidateInstructionCache(slot_start, ic->getSlotSize()); llvm::sys::Memory::InvalidateInstructionCache(slot_start, ic->getSlotSize());
} }
void ICSlotRewrite::addDependenceOn(ICInvalidator &invalidator) { void ICSlotRewrite::addDependenceOn(ICInvalidator& invalidator) {
dependencies.push_back(std::make_pair(&invalidator, invalidator.version())); dependencies.push_back(std::make_pair(&invalidator, invalidator.version()));
} }
...@@ -144,7 +146,7 @@ ICSlotRewrite* ICInfo::startRewrite(const char* debug_name) { ...@@ -144,7 +146,7 @@ ICSlotRewrite* ICInfo::startRewrite(const char* debug_name) {
ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debug_name) { ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debug_name) {
for (int i = 0; i < getNumSlots(); i++) { for (int i = 0; i < getNumSlots(); i++) {
SlotInfo &sinfo = slots[i]; SlotInfo& sinfo = slots[i];
if (!sinfo.is_patched) { if (!sinfo.is_patched) {
if (VERBOSITY()) { if (VERBOSITY()) {
printf("committing %s icentry to unused slot %d at %p\n", debug_name, i, start_addr); printf("committing %s icentry to unused slot %d at %p\n", debug_name, i, start_addr);
...@@ -160,7 +162,7 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu ...@@ -160,7 +162,7 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu
for (int _i = 0; _i < num_slots; _i++) { for (int _i = 0; _i < num_slots; _i++) {
int i = (_i + next_slot_to_try) % num_slots; int i = (_i + next_slot_to_try) % num_slots;
SlotInfo &sinfo = slots[i]; SlotInfo& sinfo = slots[i];
if (sinfo.is_patched && sinfo.decision_path != decision_path) { if (sinfo.is_patched && sinfo.decision_path != decision_path) {
continue; continue;
} }
...@@ -174,20 +176,27 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu ...@@ -174,20 +176,27 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(uint64_t decision_path, const char* debu
sinfo.decision_path = decision_path; sinfo.decision_path = decision_path;
return &sinfo.entry; return &sinfo.entry;
} }
if (VERBOSITY()) printf("not committing %s icentry since it is not compatible (%lx)\n", debug_name, decision_path); if (VERBOSITY())
printf("not committing %s icentry since it is not compatible (%lx)\n", debug_name, decision_path);
return NULL; return NULL;
} }
ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register, TypeRecorder *type_recorder) : next_slot_to_try(0), stack_info(stack_info), num_slots(num_slots), slot_size(slot_size), calling_conv(calling_conv), live_outs(live_outs.begin(), live_outs.end()), return_register(return_register), type_recorder(type_recorder), start_addr(start_addr), continue_addr(continue_addr) { ICInfo::ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size,
llvm::CallingConv::ID calling_conv, const std::unordered_set<int>& live_outs,
assembler::GenericRegister return_register, TypeRecorder* type_recorder)
: next_slot_to_try(0), stack_info(stack_info), num_slots(num_slots), slot_size(slot_size),
calling_conv(calling_conv), live_outs(live_outs.begin(), live_outs.end()), return_register(return_register),
type_recorder(type_recorder), start_addr(start_addr), continue_addr(continue_addr) {
for (int i = 0; i < num_slots; i++) { for (int i = 0; i < num_slots; i++) {
slots.push_back(SlotInfo(this, i)); slots.push_back(SlotInfo(this, i));
} }
} }
static std::unordered_map<void*, ICInfo*> ics_by_return_addr; static std::unordered_map<void*, ICInfo*> ics_by_return_addr;
void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, StackInfo stack_info, std::unordered_set<int> live_outs) { void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, StackInfo stack_info,
std::unordered_set<int> live_outs) {
int size = pp->totalSize(); int size = pp->totalSize();
uint8_t* end_addr = start_addr + size; uint8_t* end_addr = start_addr + size;
uint8_t* slowpath_addr = end_addr; uint8_t* slowpath_addr = end_addr;
...@@ -195,7 +204,8 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St ...@@ -195,7 +204,8 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St
uint8_t* rtn_addr; uint8_t* rtn_addr;
assembler::GenericRegister return_register; assembler::GenericRegister return_register;
assert(pp->getCallingConvention() == llvm::CallingConv::C || pp->getCallingConvention() == llvm::CallingConv::PreserveAll); assert(pp->getCallingConvention() == llvm::CallingConv::C || pp->getCallingConvention()
== llvm::CallingConv::PreserveAll);
if (pp->hasReturnValue()) { if (pp->hasReturnValue()) {
static const int DWARF_RAX = 0; static const int DWARF_RAX = 0;
// It's possible that the return value doesn't get used, in which case // It's possible that the return value doesn't get used, in which case
...@@ -213,13 +223,14 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St ...@@ -213,13 +223,14 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St
uint8_t* slowpath_start = start_addr + pp->num_slots * pp->slot_size; uint8_t* slowpath_start = start_addr + pp->num_slots * pp->slot_size;
rtn_addr = initializePatchpoint2(start_addr, slowpath_start, (uint8_t*)end_addr, stack_info, live_outs); rtn_addr = initializePatchpoint2(start_addr, slowpath_start, (uint8_t*)end_addr, stack_info, live_outs);
} else { } else {
//for (int regnum : live_outs) { // for (int regnum : live_outs) {
//// LLVM has a bug where it incorrectly determines the set of liveouts; //// LLVM has a bug where it incorrectly determines the set of liveouts;
//// so far it only seems to add additional ones to the set, which should //// so far it only seems to add additional ones to the set, which should
//// hopefully be safe. //// hopefully be safe.
//// Otherwise, I'd like to test here that it's only the registers //// Otherwise, I'd like to test here that it's only the registers
//// that we'd expect to be saved... //// that we'd expect to be saved...
//ASSERT(regnum == 0 || regnum == 3 || regnum == 6 || regnum == 12 || regnum == 13 || regnum == 14 || regnum == 15 || regnum == 7, "%d", regnum); // ASSERT(regnum == 0 || regnum == 3 || regnum == 6 || regnum == 12 || regnum == 13 || regnum == 14 || regnum ==
// 15 || regnum == 7, "%d", regnum);
//} //}
initializePatchpoint(start_addr, size); initializePatchpoint(start_addr, size);
...@@ -231,17 +242,19 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St ...@@ -231,17 +242,19 @@ void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo* pp, St
// Not sure if this is worth it or not? // Not sure if this is worth it or not?
for (int i = 0; i < pp->num_slots; i++) { for (int i = 0; i < pp->num_slots; i++) {
uint8_t* start = start_addr + i * pp->slot_size; uint8_t* start = start_addr + i * pp->slot_size;
//std::unique_ptr<MCWriter> writer(createMCWriter(start, pp->slot_size * (pp->num_slots - i), 0)); // std::unique_ptr<MCWriter> writer(createMCWriter(start, pp->slot_size * (pp->num_slots - i), 0));
//writer->emitNop(); // writer->emitNop();
//writer->emitGuardFalse(); // writer->emitGuardFalse();
std::unique_ptr<Assembler> writer(new Assembler(start, pp->slot_size)); std::unique_ptr<Assembler> writer(new Assembler(start, pp->slot_size));
writer->nop(); writer->nop();
//writer->trap(); // writer->trap();
writer->jmp(JumpDestination::fromStart(pp->slot_size * (pp->num_slots - i))); writer->jmp(JumpDestination::fromStart(pp->slot_size * (pp->num_slots - i)));
} }
ics_by_return_addr[rtn_addr] = new ICInfo(start_addr, slowpath_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(), live_outs, return_register, pp->type_recorder); ics_by_return_addr[rtn_addr]
= new ICInfo(start_addr, slowpath_addr, stack_info, pp->num_slots, pp->slot_size, pp->getCallingConvention(),
live_outs, return_register, pp->type_recorder);
} }
ICInfo* getICInfo(void* rtn_addr) { ICInfo* getICInfo(void* rtn_addr) {
...@@ -256,17 +269,17 @@ void ICInfo::clear(ICSlotInfo* icentry) { ...@@ -256,17 +269,17 @@ void ICInfo::clear(ICSlotInfo* icentry) {
uint8_t* start = (uint8_t*)start_addr + icentry->idx * getSlotSize(); uint8_t* start = (uint8_t*)start_addr + icentry->idx * getSlotSize();
if (VERBOSITY()) printf("clearing patchpoint %p, slot at %p\n", start_addr, start); if (VERBOSITY())
printf("clearing patchpoint %p, slot at %p\n", start_addr, start);
std::unique_ptr<Assembler> writer(new Assembler(start, getSlotSize())); std::unique_ptr<Assembler> writer(new Assembler(start, getSlotSize()));
writer->nop(); writer->nop();
writer->jmp(JumpDestination::fromStart(getSlotSize())); writer->jmp(JumpDestination::fromStart(getSlotSize()));
//std::unique_ptr<MCWriter> writer(createMCWriter(start, getSlotSize(), 0)); // std::unique_ptr<MCWriter> writer(createMCWriter(start, getSlotSize(), 0));
//writer->emitNop(); // writer->emitNop();
//writer->emitGuardFalse(); // writer->emitGuardFalse();
//writer->endWithSlowpath(); // writer->endWithSlowpath();
llvm::sys::Memory::InvalidateInstructionCache(start, getSlotSize()); llvm::sys::Memory::InvalidateInstructionCache(start, getSlotSize());
} }
} }
...@@ -30,102 +30,104 @@ class ICInfo; ...@@ -30,102 +30,104 @@ class ICInfo;
class ICInvalidator; class ICInvalidator;
struct ICSlotInfo { struct ICSlotInfo {
public: public:
ICSlotInfo(ICInfo* ic, int idx) : ic(ic), idx(idx) {} ICSlotInfo(ICInfo* ic, int idx) : ic(ic), idx(idx) {}
ICInfo *ic; ICInfo* ic;
int idx; int idx;
void clear(); void clear();
}; };
class ICSlotRewrite { class ICSlotRewrite {
public:
class CommitHook {
public: public:
class CommitHook { virtual ~CommitHook() {}
public: virtual void finishAssembly(int fastpath_offset) = 0;
virtual ~CommitHook() {} };
virtual void finishAssembly(int fastpath_offset) = 0;
};
private:
ICInfo* ic;
assembler::Assembler* assembler;
const char* debug_name;
uint8_t *buf; private:
ICInfo* ic;
assembler::Assembler* assembler;
const char* debug_name;
std::vector<std::pair<ICInvalidator*, int64_t> > dependencies; uint8_t* buf;
ICSlotRewrite(ICInfo* ic, const char* debug_name); std::vector<std::pair<ICInvalidator*, int64_t> > dependencies;
public: ICSlotRewrite(ICInfo* ic, const char* debug_name);
~ICSlotRewrite();
public:
~ICSlotRewrite();
assembler::Assembler* getAssembler() { return assembler; } assembler::Assembler* getAssembler() { return assembler; }
int getSlotSize(); int getSlotSize();
int getFuncStackSize(); int getFuncStackSize();
int getScratchRbpOffset(); int getScratchRbpOffset();
int getScratchBytes(); int getScratchBytes();
TypeRecorder* getTypeRecorder(); TypeRecorder* getTypeRecorder();
assembler::GenericRegister returnRegister(); assembler::GenericRegister returnRegister();
void addDependenceOn(ICInvalidator&); void addDependenceOn(ICInvalidator&);
void commit(uint64_t decision_path, CommitHook *hook); void commit(uint64_t decision_path, CommitHook* hook);
friend class ICInfo; friend class ICInfo;
}; };
class ICInfo { class ICInfo {
private: private:
struct SlotInfo { struct SlotInfo {
bool is_patched; bool is_patched;
uint64_t decision_path; uint64_t decision_path;
ICSlotInfo entry; ICSlotInfo entry;
SlotInfo(ICInfo* ic, int idx) : is_patched(false), decision_path(0), entry(ic, idx) {} SlotInfo(ICInfo* ic, int idx) : is_patched(false), decision_path(0), entry(ic, idx) {}
}; };
std::vector<SlotInfo> slots; std::vector<SlotInfo> slots;
// For now, just use a round-robin eviction policy. // For now, just use a round-robin eviction policy.
// This is probably a bunch worse than LRU, but it's also // This is probably a bunch worse than LRU, but it's also
// probably a bunch better than the "always evict slot #0" policy // probably a bunch better than the "always evict slot #0" policy
// that it's replacing. // that it's replacing.
int next_slot_to_try; int next_slot_to_try;
const StackInfo stack_info; const StackInfo stack_info;
const int num_slots; const int num_slots;
const int slot_size; const int slot_size;
const llvm::CallingConv::ID calling_conv; const llvm::CallingConv::ID calling_conv;
const std::vector<int> live_outs; const std::vector<int> live_outs;
const assembler::GenericRegister return_register; const assembler::GenericRegister return_register;
TypeRecorder * const type_recorder; TypeRecorder* const type_recorder;
// for ICSlotRewrite: // for ICSlotRewrite:
ICSlotInfo *pickEntryForRewrite(uint64_t decision_path, const char* debug_name); ICSlotInfo* pickEntryForRewrite(uint64_t decision_path, const char* debug_name);
void* getSlowpathStart(); void* getSlowpathStart();
public: public:
ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size, llvm::CallingConv::ID calling_conv, const std::unordered_set<int> &live_outs, assembler::GenericRegister return_register, TypeRecorder *type_recorder); ICInfo(void* start_addr, void* continue_addr, StackInfo stack_info, int num_slots, int slot_size,
void *const start_addr, *const continue_addr; llvm::CallingConv::ID calling_conv, const std::unordered_set<int>& live_outs,
assembler::GenericRegister return_register, TypeRecorder* type_recorder);
int getSlotSize() { return slot_size; } void* const start_addr, *const continue_addr;
int getNumSlots() { return num_slots; }
llvm::CallingConv::ID getCallingConvention() { return calling_conv; } int getSlotSize() { return slot_size; }
const std::vector<int>& getLiveOuts() { return live_outs; } int getNumSlots() { return num_slots; }
llvm::CallingConv::ID getCallingConvention() { return calling_conv; }
ICSlotRewrite* startRewrite(const char* debug_name); const std::vector<int>& getLiveOuts() { return live_outs; }
void clear(ICSlotInfo *entry);
ICSlotRewrite* startRewrite(const char* debug_name);
friend class ICSlotRewrite; void clear(ICSlotInfo* entry);
friend class ICSlotRewrite;
}; };
class PatchpointSetupInfo; class PatchpointSetupInfo;
void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo*, StackInfo stack_info, std::unordered_set<int> live_outs); void registerCompiledPatchpoint(uint8_t* start_addr, PatchpointSetupInfo*, StackInfo stack_info,
std::unordered_set<int> live_outs);
ICInfo* getICInfo(void* rtn_addr); ICInfo* getICInfo(void* rtn_addr);
} }
#endif #endif
This diff is collapsed.
...@@ -22,40 +22,38 @@ namespace pyston { ...@@ -22,40 +22,38 @@ namespace pyston {
class BoxedClass; class BoxedClass;
class MCWriter { class MCWriter {
public: public:
virtual ~MCWriter() {} virtual ~MCWriter() {}
virtual int numArgRegs() = 0; virtual int numArgRegs() = 0;
virtual int numTempRegs() = 0; virtual int numTempRegs() = 0;
// TODO I don't like this method, could be broken down into simpler things // TODO I don't like this method, could be broken down into simpler things
virtual void emitAlloca(int bytes, int dest_argnum) = 0; virtual void emitAlloca(int bytes, int dest_argnum) = 0;
virtual void emitNop() = 0; virtual void emitNop() = 0;
virtual void emitTrap() = 0; virtual void emitTrap() = 0;
virtual void emitAnnotation(int num) = 0; virtual void emitAnnotation(int num) = 0;
virtual void endFastPath(void* success_dest, void* will_relocate_to) = 0; virtual void endFastPath(void* success_dest, void* will_relocate_to) = 0;
virtual void endWithSlowpath() = 0; virtual void endWithSlowpath() = 0;
virtual uint8_t* emitCall(void* target, int npushes) = 0; virtual uint8_t* emitCall(void* target, int npushes) = 0;
virtual void emitGuardFalse() = 0; virtual void emitGuardFalse() = 0;
virtual void emitAttrGuard(int argnum, int offset, int64_t val, int npops) = 0; virtual void emitAttrGuard(int argnum, int offset, int64_t val, int npops) = 0;
virtual void emitGuard(int argnum, int64_t val, int npops) = 0; virtual void emitGuard(int argnum, int64_t val, int npops) = 0;
virtual void emitGuardNotEq(int argnum, int64_t val, int npops) = 0; virtual void emitGuardNotEq(int argnum, int64_t val, int npops) = 0;
virtual void emitMove(int src_argnum, int dest_argnum, int npushed) = 0; virtual void emitMove(int src_argnum, int dest_argnum, int npushed) = 0;
virtual void emitSetattr(int src_argnum, int dest_argnum, int dest_offset) = 0; virtual void emitSetattr(int src_argnum, int dest_argnum, int dest_offset) = 0;
virtual void emitGetattr(int src_argnum, int src_offset, int dest_argnum) = 0; virtual void emitGetattr(int src_argnum, int src_offset, int dest_argnum) = 0;
virtual void emitIncattr(int argnum, int offset) = 0; virtual void emitIncattr(int argnum, int offset) = 0;
virtual void emitPush(int reg) = 0; virtual void emitPush(int reg) = 0;
virtual void emitPop(int reg) = 0; virtual void emitPop(int reg) = 0;
virtual void emitLoadConst(int reg, int64_t value) = 0; virtual void emitLoadConst(int reg, int64_t value) = 0;
virtual void emitCmp(AST_TYPE::AST_TYPE cmp_type, int lhs_argnum, int rhs_argnum, int dest_argnum) = 0; virtual void emitCmp(AST_TYPE::AST_TYPE cmp_type, int lhs_argnum, int rhs_argnum, int dest_argnum) = 0;
virtual void emitToBool(int argnum, int dest_argnum) = 0; virtual void emitToBool(int argnum, int dest_argnum) = 0;
}; };
void initializePatchpoint(uint8_t* addr, int size); void initializePatchpoint(uint8_t* addr, int size);
MCWriter* createMCWriter(uint8_t* addr, int size, int num_temp_regs); MCWriter* createMCWriter(uint8_t* addr, int size, int num_temp_regs);
} }
#endif #endif
...@@ -50,11 +50,12 @@ Register fromArgnum(int argnum) { ...@@ -50,11 +50,12 @@ Register fromArgnum(int argnum) {
RELEASE_ASSERT(0, "%d", argnum); RELEASE_ASSERT(0, "%d", argnum);
} }
RewriterVar::RewriterVar(Rewriter *rewriter, int argnum, int version) : rewriter(rewriter), argnum(argnum), version(version) { RewriterVar::RewriterVar(Rewriter* rewriter, int argnum, int version)
//assert(rewriter.icentry.get()); : rewriter(rewriter), argnum(argnum), version(version) {
// assert(rewriter.icentry.get());
} }
RewriterVar& RewriterVar::operator=(const RewriterVar &rhs) { RewriterVar& RewriterVar::operator=(const RewriterVar& rhs) {
assert(rewriter == NULL || rewriter == rhs.rewriter); assert(rewriter == NULL || rewriter == rhs.rewriter);
rhs.assertValid(); rhs.assertValid();
rewriter = rhs.rewriter; rewriter = rhs.rewriter;
...@@ -81,7 +82,7 @@ void RewriterVar::unlock() { ...@@ -81,7 +82,7 @@ void RewriterVar::unlock() {
#endif #endif
int RewriterVar::getArgnum() { int RewriterVar::getArgnum() {
//assert(rewriter); // assert(rewriter);
return argnum; return argnum;
} }
...@@ -128,7 +129,7 @@ RewriterVar RewriterVar::move(int dest_argnum) { ...@@ -128,7 +129,7 @@ RewriterVar RewriterVar::move(int dest_argnum) {
rewriter->assembler->mov(Indirect(RSP, offset), fromArgnum(dest_argnum)); rewriter->assembler->mov(Indirect(RSP, offset), fromArgnum(dest_argnum));
} else { } else {
int stack_size = rewriter->rewrite->getFuncStackSize(); int stack_size = rewriter->rewrite->getFuncStackSize();
ASSERT(stack_size > 0 && stack_size < (1<<30), "%d", stack_size); ASSERT(stack_size > 0 && stack_size < (1 << 30), "%d", stack_size);
int offset = (this->argnum - 6) * 8 - (stack_size - 8); int offset = (this->argnum - 6) * 8 - (stack_size - 8);
rewriter->assembler->mov(Indirect(RBP, offset), fromArgnum(dest_argnum)); rewriter->assembler->mov(Indirect(RBP, offset), fromArgnum(dest_argnum));
} }
...@@ -151,7 +152,7 @@ void RewriterVar::addGuard(intptr_t val) { ...@@ -151,7 +152,7 @@ void RewriterVar::addGuard(intptr_t val) {
int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes; int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes;
if (val < (-1L<<31) || val >= (1L<<31) - 1) { if (val < (-1L << 31) || val >= (1L << 31) - 1) {
rewriter->assembler->push(RBP); rewriter->assembler->push(RBP);
rewriter->assembler->mov(Immediate(val), RBP); rewriter->assembler->mov(Immediate(val), RBP);
rewriter->assembler->cmp(fromArgnum(this->argnum), RBP); rewriter->assembler->cmp(fromArgnum(this->argnum), RBP);
...@@ -159,7 +160,7 @@ void RewriterVar::addGuard(intptr_t val) { ...@@ -159,7 +160,7 @@ void RewriterVar::addGuard(intptr_t val) {
} else { } else {
rewriter->assembler->cmp(fromArgnum(this->argnum), Immediate(val)); rewriter->assembler->cmp(fromArgnum(this->argnum), Immediate(val));
} }
rewriter->assembler->jne(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes/8)); rewriter->assembler->jne(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes / 8));
} }
void RewriterVar::addAttrGuard(int offset, intptr_t val) { void RewriterVar::addAttrGuard(int offset, intptr_t val) {
...@@ -170,7 +171,7 @@ void RewriterVar::addAttrGuard(int offset, intptr_t val) { ...@@ -170,7 +171,7 @@ void RewriterVar::addAttrGuard(int offset, intptr_t val) {
int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes; int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes;
if (val < (-1L<<31) || val >= (1L<<31) - 1) { if (val < (-1L << 31) || val >= (1L << 31) - 1) {
rewriter->assembler->push(RBP); rewriter->assembler->push(RBP);
rewriter->assembler->mov(Immediate(val), RBP); rewriter->assembler->mov(Immediate(val), RBP);
rewriter->assembler->cmp(Indirect(fromArgnum(this->argnum), offset), RBP); rewriter->assembler->cmp(Indirect(fromArgnum(this->argnum), offset), RBP);
...@@ -178,7 +179,7 @@ void RewriterVar::addAttrGuard(int offset, intptr_t val) { ...@@ -178,7 +179,7 @@ void RewriterVar::addAttrGuard(int offset, intptr_t val) {
} else { } else {
rewriter->assembler->cmp(Indirect(fromArgnum(this->argnum), offset), Immediate(val)); rewriter->assembler->cmp(Indirect(fromArgnum(this->argnum), offset), Immediate(val));
} }
rewriter->assembler->jne(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes/8)); rewriter->assembler->jne(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes / 8));
} }
void RewriterVar::addGuardNotEq(intptr_t val) { void RewriterVar::addGuardNotEq(intptr_t val) {
...@@ -189,7 +190,7 @@ void RewriterVar::addGuardNotEq(intptr_t val) { ...@@ -189,7 +190,7 @@ void RewriterVar::addGuardNotEq(intptr_t val) {
int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes; int bytes = 8 * rewriter->pushes.size() + rewriter->alloca_bytes;
rewriter->assembler->cmp(fromArgnum(this->argnum), Immediate(val)); rewriter->assembler->cmp(fromArgnum(this->argnum), Immediate(val));
rewriter->assembler->je(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes/8)); rewriter->assembler->je(JumpDestination::fromStart(rewriter->rewrite->getSlotSize() - bytes / 8));
} }
bool RewriterVar::isInReg() { bool RewriterVar::isInReg() {
...@@ -205,7 +206,7 @@ void RewriterVar::push() { ...@@ -205,7 +206,7 @@ void RewriterVar::push() {
rewriter->addPush(this->version); rewriter->addPush(this->version);
} }
RewriterVar RewriterVar::cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar &val, int dest) { RewriterVar RewriterVar::cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar& val, int dest) {
assertValid(); assertValid();
rewriter->assembler->cmp(fromArgnum(this->argnum), fromArgnum(val.argnum)); rewriter->assembler->cmp(fromArgnum(this->argnum), fromArgnum(val.argnum));
...@@ -239,7 +240,7 @@ Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num ...@@ -239,7 +240,7 @@ Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num
static StatCounter rewriter_nopatch("rewriter_nopatch"); static StatCounter rewriter_nopatch("rewriter_nopatch");
ICInfo *ic = getICInfo(ic_rtn_addr); ICInfo* ic = getICInfo(ic_rtn_addr);
if (ic == NULL) { if (ic == NULL) {
rewriter_nopatch.log(); rewriter_nopatch.log();
return NULL; return NULL;
...@@ -249,21 +250,22 @@ Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num ...@@ -249,21 +250,22 @@ Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num
return new Rewriter(ic->startRewrite(debug_name), num_orig_args, num_temp_regs); return new Rewriter(ic->startRewrite(debug_name), num_orig_args, num_temp_regs);
} }
Rewriter::Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs) : Rewriter::Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs)
rewrite(rewrite), assembler(rewrite->getAssembler()), : rewrite(rewrite), assembler(rewrite->getAssembler()), num_orig_args(num_orig_args), num_temp_regs(num_temp_regs),
num_orig_args(num_orig_args), num_temp_regs(num_temp_regs), alloca_bytes(0), max_pushes(0) alloca_bytes(0), max_pushes(0)
#ifndef NDEBUG #ifndef NDEBUG
, next_version(2), changed_something(false) ,
next_version(2), changed_something(false)
#endif #endif
, ndecisions(0), decision_path(1) ,
{ ndecisions(0), decision_path(1) {
//printf("trapping here\n"); // printf("trapping here\n");
//assembler->trap(); // assembler->trap();
//for (int i = 0; i < num_temp_regs; i++) { // for (int i = 0; i < num_temp_regs; i++) {
//icentry->push(-2 - i); // icentry->push(-2 - i);
//} //}
#ifndef NDEBUG #ifndef NDEBUG
for (int i = -3; i < MAX_ARGS; i++) { for (int i = -3; i < MAX_ARGS; i++) {
...@@ -279,7 +281,7 @@ void Rewriter::addPush(int version) { ...@@ -279,7 +281,7 @@ void Rewriter::addPush(int version) {
RewriterVar Rewriter::alloca_(int bytes, int dest_argnum) { RewriterVar Rewriter::alloca_(int bytes, int dest_argnum) {
// TODO should check to make sure we aren't crossing push+pops and allocas // TODO should check to make sure we aren't crossing push+pops and allocas
//printf("alloca()ing %d bytes\n", bytes); // printf("alloca()ing %d bytes\n", bytes);
assert(bytes % sizeof(void*) == 0); assert(bytes % sizeof(void*) == 0);
alloca_bytes += bytes; alloca_bytes += bytes;
...@@ -314,7 +316,7 @@ int Rewriter::mutate(int argnum) { ...@@ -314,7 +316,7 @@ int Rewriter::mutate(int argnum) {
assert(versions.count(argnum)); assert(versions.count(argnum));
int rtn_version = ++next_version; int rtn_version = ++next_version;
//printf("mutating %d to %d\n", argnum, rtn_version); // printf("mutating %d to %d\n", argnum, rtn_version);
versions[argnum] = rtn_version; versions[argnum] = rtn_version;
return rtn_version; return rtn_version;
} }
...@@ -357,7 +359,7 @@ RewriterVar Rewriter::call(void* func_addr) { ...@@ -357,7 +359,7 @@ RewriterVar Rewriter::call(void* func_addr) {
#ifndef NDEBUG #ifndef NDEBUG
changed_something = true; changed_something = true;
#endif #endif
//printf("%ld pushes, %d alloca bytes\n", pushes.size(), alloca_bytes); // printf("%ld pushes, %d alloca bytes\n", pushes.size(), alloca_bytes);
int bytes = 8 * pushes.size() + alloca_bytes; int bytes = 8 * pushes.size() + alloca_bytes;
bool didpush; bool didpush;
...@@ -391,7 +393,7 @@ RewriterVar Rewriter::pop(int argnum) { ...@@ -391,7 +393,7 @@ RewriterVar Rewriter::pop(int argnum) {
#ifndef NDEBUG #ifndef NDEBUG
versions[argnum] = version; versions[argnum] = version;
#endif #endif
//printf("popping %d to %d\n", version, argnum); // printf("popping %d to %d\n", version, argnum);
assembler->pop(fromArgnum(argnum)); assembler->pop(fromArgnum(argnum));
return RewriterVar(this, argnum, version); return RewriterVar(this, argnum, version);
...@@ -403,7 +405,7 @@ void Rewriter::addDecision(int way) { ...@@ -403,7 +405,7 @@ void Rewriter::addDecision(int way) {
decision_path = (decision_path << 1) | way; decision_path = (decision_path << 1) | way;
} }
void Rewriter::addDependenceOn(ICInvalidator &invalidator) { void Rewriter::addDependenceOn(ICInvalidator& invalidator) {
rewrite->addDependenceOn(invalidator); rewrite->addDependenceOn(invalidator);
} }
...@@ -426,5 +428,4 @@ void Rewriter::finishAssembly(int continue_offset) { ...@@ -426,5 +428,4 @@ void Rewriter::finishAssembly(int continue_offset) {
assembler->pop(RAX); assembler->pop(RAX);
} }
} }
} }
...@@ -36,103 +36,103 @@ class Assembler; ...@@ -36,103 +36,103 @@ class Assembler;
// and a release one, instead of trying to make one class do both? // and a release one, instead of trying to make one class do both?
class RewriterVar { class RewriterVar {
private: private:
Rewriter *rewriter; Rewriter* rewriter;
int argnum; int argnum;
int version; int version;
public: public:
RewriterVar() : rewriter(NULL), argnum(-100), version(-100) {} RewriterVar() : rewriter(NULL), argnum(-100), version(-100) {}
RewriterVar(Rewriter *rewriter, int argnum, int version); RewriterVar(Rewriter* rewriter, int argnum, int version);
RewriterVar& operator=(const RewriterVar &rhs); RewriterVar& operator=(const RewriterVar& rhs);
#ifndef NDEBUG #ifndef NDEBUG
void assertValid() const; void assertValid() const;
void lock(); void lock();
void unlock(); void unlock();
#else #else
inline void assertValid() const {} inline void assertValid() const {}
inline void lock() {} inline void lock() {}
inline void unlock() {} inline void unlock() {}
#endif #endif
int getArgnum(); int getArgnum();
void addGuard(intptr_t val); void addGuard(intptr_t val);
void addGuardNotEq(intptr_t val); void addGuardNotEq(intptr_t val);
// More efficient than getAttr().addGuard(), but less efficient than addGuard() if the value is already available: // More efficient than getAttr().addGuard(), but less efficient than addGuard() if the value is already available:
void addAttrGuard(int offset, intptr_t val); void addAttrGuard(int offset, intptr_t val);
RewriterVar getAttr(int offset, int dest); RewriterVar getAttr(int offset, int dest);
void incAttr(int offset); void incAttr(int offset);
void setAttr(int offset, const RewriterVar &val, bool user_visible=true); void setAttr(int offset, const RewriterVar& val, bool user_visible = true);
RewriterVar move(int argnum); RewriterVar move(int argnum);
bool isInReg(); bool isInReg();
void push(); void push();
RewriterVar cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar &val, int dest); RewriterVar cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar& val, int dest);
RewriterVar toBool(int dest); RewriterVar toBool(int dest);
friend class Rewriter; friend class Rewriter;
}; };
class Rewriter : public ICSlotRewrite::CommitHook { class Rewriter : public ICSlotRewrite::CommitHook {
private: private:
std::unique_ptr<ICSlotRewrite> rewrite; std::unique_ptr<ICSlotRewrite> rewrite;
assembler::Assembler *assembler; assembler::Assembler* assembler;
const int num_orig_args; const int num_orig_args;
const int num_temp_regs; const int num_temp_regs;
void finishAssembly(int continue_offset); void finishAssembly(int continue_offset);
int alloca_bytes; int alloca_bytes;
int max_pushes; int max_pushes;
std::vector<int> pushes; std::vector<int> pushes;
#ifndef NDEBUG #ifndef NDEBUG
std::unordered_map<int, int> versions; std::unordered_map<int, int> versions;
int next_version; int next_version;
bool changed_something; bool changed_something;
std::unordered_set<int> locked; std::unordered_set<int> locked;
#endif #endif
int ndecisions; int ndecisions;
uint64_t decision_path; uint64_t decision_path;
Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs); Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs);
void addPush(int version); void addPush(int version);
public:
static Rewriter* createRewriter(void* ic_rtn_addr, int num_orig_args, int num_temp_regs, const char* debug_name); public:
static Rewriter* createRewriter(void* ic_rtn_addr, int num_orig_args, int num_temp_regs, const char* debug_name);
#ifndef NDEBUG #ifndef NDEBUG
int mutate(int argnum); int mutate(int argnum);
void lock(int argnum); void lock(int argnum);
void unlock(int argnum); void unlock(int argnum);
void checkVersion(int argnum, int version); void checkVersion(int argnum, int version);
void checkArgsValid(); void checkArgsValid();
#else #else
inline int mutate(int argnum) { return 0; } inline int mutate(int argnum) { return 0; }
inline void lock(int argnum) {} inline void lock(int argnum) {}
inline void unlock(int argnum) {} inline void unlock(int argnum) {}
inline void checkVersion(int argnum, int version) {} inline void checkVersion(int argnum, int version) {}
inline void checkArgsValid() {} inline void checkArgsValid() {}
#endif #endif
void addDecision(int way); void addDecision(int way);
RewriterVar alloca_(int bytes, int dest_argnum); RewriterVar alloca_(int bytes, int dest_argnum);
RewriterVar getArg(int argnum); RewriterVar getArg(int argnum);
void trap(); void trap();
void nop(); void nop();
void annotate(int num); void annotate(int num);
RewriterVar pop(int argnum); RewriterVar pop(int argnum);
RewriterVar call(void* func_addr); RewriterVar call(void* func_addr);
RewriterVar loadConst(int argnum, intptr_t val); RewriterVar loadConst(int argnum, intptr_t val);
void addDependenceOn(ICInvalidator&); void addDependenceOn(ICInvalidator&);
void commit(); void commit();
friend class RewriterVar; friend class RewriterVar;
}; };
} }
#endif #endif
This diff is collapsed.
This diff is collapsed.
...@@ -36,13 +36,9 @@ struct Register { ...@@ -36,13 +36,9 @@ struct Register {
bool isCalleeSave(); bool isCalleeSave();
bool operator==(const Register &rhs) const { bool operator==(const Register& rhs) const { return regnum == rhs.regnum; }
return regnum == rhs.regnum;
}
bool operator!=(const Register &rhs) const { bool operator!=(const Register& rhs) const { return !(*this == rhs); }
return !(*this == rhs);
}
void dump() const; void dump() const;
}; };
...@@ -69,11 +65,11 @@ inline bool Register::isCalleeSave() { ...@@ -69,11 +65,11 @@ inline bool Register::isCalleeSave() {
} }
struct Indirect { struct Indirect {
public: public:
const Register base; const Register base;
const int offset; const int offset;
Indirect(const Register base, int offset) : base(base), offset(offset) {} Indirect(const Register base, int offset) : base(base), offset(offset) {}
}; };
struct XMMRegister { struct XMMRegister {
...@@ -81,13 +77,9 @@ struct XMMRegister { ...@@ -81,13 +77,9 @@ struct XMMRegister {
explicit constexpr XMMRegister(int regnum) : regnum(regnum) {} explicit constexpr XMMRegister(int regnum) : regnum(regnum) {}
bool operator==(const XMMRegister &rhs) const { bool operator==(const XMMRegister& rhs) const { return regnum == rhs.regnum; }
return regnum == rhs.regnum;
}
bool operator!=(const XMMRegister &rhs) const { bool operator!=(const XMMRegister& rhs) const { return !(*this == rhs); }
return !(*this == rhs);
}
}; };
const XMMRegister XMM0(0); const XMMRegister XMM0(0);
...@@ -157,7 +149,6 @@ struct JumpDestination { ...@@ -157,7 +149,6 @@ struct JumpDestination {
constexpr JumpDestination(OffsetType type, int offset) : type(type), offset(offset) {} constexpr JumpDestination(OffsetType type, int offset) : type(type), offset(offset) {}
static JumpDestination fromStart(int offset) { return JumpDestination(FROM_START, offset); } static JumpDestination fromStart(int offset) { return JumpDestination(FROM_START, offset); }
}; };
} }
} }
......
...@@ -28,7 +28,8 @@ ...@@ -28,7 +28,8 @@
namespace pyston { namespace pyston {
void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length, llvm::Function* llvm_func) { void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length,
llvm::Function* llvm_func) {
assert(addr); assert(addr);
assert(functions.count(addr) == 0); assert(functions.count(addr) == 0);
functions.insert(std::make_pair(addr, FuncInfo(name, length, llvm_func))); functions.insert(std::make_pair(addr, FuncInfo(name, length, llvm_func)));
...@@ -42,19 +43,19 @@ void FunctionAddressRegistry::dumpPerfMap() { ...@@ -42,19 +43,19 @@ void FunctionAddressRegistry::dumpPerfMap() {
code = llvm::sys::fs::create_directory(out_path, false); code = llvm::sys::fs::create_directory(out_path, false);
assert(!code); assert(!code);
FILE *index_f = fopen((out_path + "/index.txt").c_str(), "w"); FILE* index_f = fopen((out_path + "/index.txt").c_str(), "w");
char buf[80]; char buf[80];
snprintf(buf, 80, "/tmp/perf-%d.map", getpid()); snprintf(buf, 80, "/tmp/perf-%d.map", getpid());
FILE *f = fopen(buf, "w"); FILE* f = fopen(buf, "w");
for (const auto &p : functions) { for (const auto& p : functions) {
const FuncInfo& info = p.second; const FuncInfo& info = p.second;
fprintf(f, "%lx %x %s\n", (uintptr_t)p.first, info.length, info.name.c_str()); fprintf(f, "%lx %x %s\n", (uintptr_t)p.first, info.length, info.name.c_str());
if (info.length > 0) { if (info.length > 0) {
fprintf(index_f, "%lx %s\n", (uintptr_t)p.first, info.name.c_str()); fprintf(index_f, "%lx %s\n", (uintptr_t)p.first, info.name.c_str());
FILE *data_f = fopen((out_path + "/" + info.name).c_str(), "wb"); FILE* data_f = fopen((out_path + "/" + info.name).c_str(), "wb");
int written = fwrite((void*)p.first, 1, info.length, data_f); int written = fwrite((void*)p.first, 1, info.length, data_f);
assert(written == info.length); assert(written == info.length);
...@@ -77,7 +78,7 @@ llvm::Function* FunctionAddressRegistry::getLLVMFuncAtAddress(void* addr) { ...@@ -77,7 +78,7 @@ llvm::Function* FunctionAddressRegistry::getLLVMFuncAtAddress(void* addr) {
return NULL; return NULL;
} }
llvm::Function *r = g.stdlib_module->getFunction(name); llvm::Function* r = g.stdlib_module->getFunction(name);
if (!r) { if (!r) {
lookup_neg_cache.insert(addr); lookup_neg_cache.insert(addr);
...@@ -101,7 +102,7 @@ static std::string tryDemangle(const char* s) { ...@@ -101,7 +102,7 @@ static std::string tryDemangle(const char* s) {
return rtn; return rtn;
} }
std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool demangle, bool *out_success) { std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool demangle, bool* out_success) {
FuncMap::iterator it = functions.find(addr); FuncMap::iterator it = functions.find(addr);
if (it == functions.end()) { if (it == functions.end()) {
Dl_info info; Dl_info info;
...@@ -110,8 +111,9 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman ...@@ -110,8 +111,9 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman
if (success && info.dli_sname == NULL) if (success && info.dli_sname == NULL)
success = false; success = false;
if (out_success) *out_success = success; if (out_success)
//if (success && info.dli_saddr == addr) { *out_success = success;
// if (success && info.dli_saddr == addr) {
if (success) { if (success) {
if (demangle) if (demangle)
return tryDemangle(info.dli_sname); return tryDemangle(info.dli_sname);
...@@ -121,7 +123,8 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman ...@@ -121,7 +123,8 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman
return "<unknown>"; return "<unknown>";
} }
if (out_success) *out_success = true; if (out_success)
*out_success = true;
if (!demangle) if (!demangle)
return it->second.name; return it->second.name;
...@@ -129,53 +132,51 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman ...@@ -129,53 +132,51 @@ std::string FunctionAddressRegistry::getFuncNameAtAddress(void* addr, bool deman
} }
class RegistryEventListener : public llvm::JITEventListener { class RegistryEventListener : public llvm::JITEventListener {
public: public:
void NotifyObjectEmitted(const llvm::ObjectImage &Obj) { void NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
static StatCounter code_bytes("code_bytes"); static StatCounter code_bytes("code_bytes");
code_bytes.log(Obj.getData().size()); code_bytes.log(Obj.getData().size());
llvm::error_code code; llvm::error_code code;
for (llvm::object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; for (llvm::object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
#if LLVMREV < 200442 #if LLVMREV < 200442
I = I.increment(code) I = I.increment(code)
#else #else
++I ++I
#endif #endif
) { ) {
llvm::object::section_iterator section(Obj.end_sections()); llvm::object::section_iterator section(Obj.end_sections());
code = I->getSection(section); code = I->getSection(section);
assert(!code); assert(!code);
bool is_text; bool is_text;
code = section->isText(is_text); code = section->isText(is_text);
assert(!code); assert(!code);
if (!is_text) if (!is_text)
continue; continue;
llvm::StringRef name; llvm::StringRef name;
uint64_t addr, size, offset; uint64_t addr, size, offset;
code = I->getName(name); code = I->getName(name);
assert(!code); assert(!code);
code = I->getAddress(addr); code = I->getAddress(addr);
assert(!code); assert(!code);
code = I->getSize(size); code = I->getSize(size);
assert(!code); assert(!code);
code = I->getFileOffset(offset); code = I->getFileOffset(offset);
assert(!code); assert(!code);
if (name == ".text") if (name == ".text")
continue; continue;
//printf("%lx %lx %lx %s\n", addr, addr + size, offset, name.data()); // printf("%lx %lx %lx %s\n", addr, addr + size, offset, name.data());
g.func_addr_registry.registerFunction(name.data(), (void*)addr, size, NULL); g.func_addr_registry.registerFunction(name.data(), (void*)addr, size, NULL);
}
} }
}
}; };
GlobalState::GlobalState() : context(llvm::getGlobalContext()) { GlobalState::GlobalState() : context(llvm::getGlobalContext()) {};
};
llvm::JITEventListener* makeRegistryListener() { llvm::JITEventListener* makeRegistryListener() {
return new RegistryEventListener(); return new RegistryEventListener();
} }
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -25,8 +25,6 @@ void initCodegen(); ...@@ -25,8 +25,6 @@ void initCodegen();
void teardownCodegen(); void teardownCodegen();
void printAllIR(); void printAllIR();
int joinRuntime(); int joinRuntime();
} }
#endif #endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -23,8 +23,7 @@ extern "C" char* reoptCompiledFunc(CompiledFunction*); ...@@ -23,8 +23,7 @@ extern "C" char* reoptCompiledFunc(CompiledFunction*);
class AST_Module; class AST_Module;
class BoxedModule; class BoxedModule;
void compileAndRunModule(AST_Module *m, BoxedModule *bm); void compileAndRunModule(AST_Module* m, BoxedModule* bm);
} }
#endif #endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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