Commit 703d45d8 authored by Marius Wachtler's avatar Marius Wachtler

bjit: directly emit patchpoints instead of using runtime ICs

this also adds support for calling 8 arg functions (=2 stack args)
parent 719cbb6d
......@@ -29,6 +29,7 @@ namespace pyston {
static llvm::DenseSet<CFGBlock*> blocks_aborted;
static llvm::DenseMap<CFGBlock*, std::vector<void*>> block_patch_locations;
JitCodeBlock::JitCodeBlock(llvm::StringRef name)
: frame_manager(false /* don't omit frame pointers */),
code(new uint8_t[code_size]),
......@@ -48,7 +49,12 @@ JitCodeBlock::JitCodeBlock(llvm::StringRef name)
static_assert(scratch_size % 16 == 0, "stack aligment code depends on this");
// subtract scratch size + 8bytes to align stack after the push.
a.sub(assembler::Immediate(scratch_size + 8), assembler::RSP);
a.push(assembler::RDI); // push interpreter pointer
a.push(assembler::RDI); // push interpreter pointer
// subtract space in order to be able to pass additional args on the stack without having to adjusting the SP when
// calling functions with more than 6 args.
a.sub(assembler::Immediate(num_stack_args * sizeof(void*)), assembler::RSP);
a.jmp(assembler::Indirect(assembler::RSI, offsetof(CFGBlock, code))); // jump to block
entry_offset = a.bytesWritten();
......@@ -65,7 +71,8 @@ std::unique_ptr<JitFragmentWriter> JitCodeBlock::newFragment(CFGBlock* block, in
is_currently_writing = true;
StackInfo stack_info(scratch_size, 16);
int scratch_offset = num_stack_args * 8 + 8 /* ASTInterpreter* */ + 8 /* alignment */;
StackInfo stack_info(scratch_size, scratch_offset);
std::unordered_set<int> live_outs;
void* fragment_start = a.curInstPointer() - patch_jump_offset;
......@@ -106,7 +113,7 @@ JitFragmentWriter::JitFragmentWriter(CFGBlock* block, std::unique_ptr<ICInfo> ic
interp(0),
ic_info(std::move(ic_info)) {
interp = createNewVar();
addLocationToVar(interp, Location(Location::Stack, 0));
addLocationToVar(interp, Location(Location::Stack, JitCodeBlock::interpreter_ptr_offset));
interp->setAttr(ASTInterpreterJitInterface::getCurrentBlockOffset(), imm(block));
}
......@@ -119,24 +126,41 @@ RewriterVar* JitFragmentWriter::imm(void* val) {
}
RewriterVar* JitFragmentWriter::emitAugbinop(RewriterVar* lhs, RewriterVar* rhs, int op_type) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)augbinopICHelper, imm(new AugBinopIC), lhs, rhs, imm(op_type));
#else
return call(false, (void*)augbinop, lhs, rhs, imm(op_type));
#endif
return emitPPCall((void*)augbinop, { lhs, rhs, imm(op_type) }, 2, 320);
}
RewriterVar* JitFragmentWriter::emitBinop(RewriterVar* lhs, RewriterVar* rhs, int op_type) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)binopICHelper, imm(new BinopIC), lhs, rhs, imm(op_type));
#else
return call(false, (void*)binop, lhs, rhs, imm(op_type));
#endif
return emitPPCall((void*)binop, { lhs, rhs, imm(op_type) }, 2, 240);
}
RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr, CallattrFlags flags,
const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) {
#if ENABLE_BASELINEJIT_ICS
RewriterVar* attr_var = imm(attr);
RewriterVar* flags_var = imm(flags.asInt());
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(attr_var);
call_args.push_back(flags_var);
call_args.push_back(args.size() > 0 ? args[0] : imm(0ul));
call_args.push_back(args.size() > 1 ? args[1] : imm(0ul));
call_args.push_back(args.size() > 2 ? args[2] : imm(0ul));
if (args.size() > 3) {
RewriterVar* scratch = allocate(args.size() - 3);
for (int i = 0; i < args.size() - 3; ++i)
scratch->setAttr(i * sizeof(void*), args[i + 3]);
call_args.push_back(scratch);
} else if (keyword_names) {
call_args.push_back(imm(0ul));
}
if (keyword_names)
call_args.push_back(imm(keyword_names));
return emitPPCall((void*)callattr, call_args, 2, 640);
#else
// We could make this faster but for now: keep it simple, stupid...
RewriterVar* attr_var = imm(attr);
RewriterVar* flags_var = imm(flags.asInt());
......@@ -148,41 +172,23 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
else
RELEASE_ASSERT(!keyword_names_var, "0 args but keyword names are set");
bool use_ic = false;
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(attr_var);
call_args.push_back(flags_var);
#if ENABLE_BASELINEJIT_ICS
if (!keyword_names_var
&& flags.argspec.totalPassed() < 4) { // looks like runtime ICs with 7 or more args don't work right now..
use_ic = true;
call_args.push_back(imm(new CallattrIC));
}
#endif
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
call_args.push_back(keyword_names_var);
#if ENABLE_BASELINEJIT_ICS
if (use_ic)
return call(false, (void*)callattrHelperIC, call_args);
#endif
return call(false, (void*)callattrHelper, call_args);
#endif
}
RewriterVar* JitFragmentWriter::emitCompare(RewriterVar* lhs, RewriterVar* rhs, int op_type) {
// TODO: can directly emit the assembly for Is/IsNot
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)compareICHelper, imm(new CompareIC), lhs, rhs, imm(op_type));
#else
return call(false, (void*)compare, lhs, rhs, imm(op_type));
#endif
// TODO: can directly emit the assembly for Is/IsNot
return emitPPCall((void*)compare, { lhs, rhs, imm(op_type) }, 2, 240);
}
RewriterVar* JitFragmentWriter::emitCreateDict(const llvm::ArrayRef<RewriterVar*> keys,
......@@ -242,11 +248,7 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
}
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)getAttrICHelper, imm(new GetAttrIC), obj, imm(s));
#else
return call(false, (void*)getattr, obj, imm(s));
#endif
return emitPPCall((void*)getattr, { obj, imm(s) }, 2, 512);
}
RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s) {
......@@ -265,23 +267,15 @@ RewriterVar* JitFragmentWriter::emitGetBoxedLocals() {
}
RewriterVar* JitFragmentWriter::emitGetClsAttr(RewriterVar* obj, BoxedString* s) {
return call(false, (void*)getclsattr, obj, imm(s));
return emitPPCall((void*)getclsattr, { obj, imm(s) }, 2, 512);
}
RewriterVar* JitFragmentWriter::emitGetGlobal(Box* global, BoxedString* s) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)getGlobalICHelper, imm(new GetGlobalIC), imm(global), imm(s));
#else
return call(false, (void*)getGlobal, imm(global), imm(s));
#endif
return emitPPCall((void*)getGlobal, { imm(global), imm(s) }, 2, 512);
}
RewriterVar* JitFragmentWriter::emitGetItem(RewriterVar* value, RewriterVar* slice) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)getitemICHelper, imm(new GetItemIC), value, slice);
#else
return call(false, (void*)getitem, value, slice);
#endif
return emitPPCall((void*)getitem, { value, slice }, 2, 512);
}
RewriterVar* JitFragmentWriter::emitGetLocal(InternedString s) {
......@@ -320,7 +314,27 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) {
RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec argspec,
const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) {
// We could make this faster but for now: keep it simple, stupid..
#if ENABLE_BASELINEJIT_ICS
RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(argspec_var);
call_args.push_back(args.size() > 0 ? args[0] : imm(0ul));
call_args.push_back(args.size() > 1 ? args[1] : imm(0ul));
call_args.push_back(args.size() > 2 ? args[2] : imm(0ul));
if (args.size() > 3) {
RewriterVar* scratch = allocate(args.size() - 3);
for (int i = 0; i < args.size() - 3; ++i)
scratch->setAttr(i * sizeof(void*), args[i + 3]);
call_args.push_back(scratch);
} else
call_args.push_back(imm(0ul));
if (keyword_names)
call_args.push_back(imm(keyword_names));
return emitPPCall((void*)runtimeCall, call_args, 2, 640);
#else
RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar* keyword_names_var = keyword_names ? imm(keyword_names) : nullptr;
......@@ -330,38 +344,20 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
} else
RELEASE_ASSERT(!keyword_names_var, "0 args but keyword names are set");
bool use_ic = false;
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(argspec_var);
#if ENABLE_BASELINEJIT_ICS
if (!keyword_names) { // looks like runtime ICs with 7 or more args don't work right now..
use_ic = true;
call_args.push_back(imm(new RuntimeCallIC));
}
#endif
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
call_args.push_back(keyword_names_var);
#if ENABLE_BASELINEJIT_ICS
if (use_ic)
return call(false, (void*)runtimeCallHelperIC, call_args);
#endif
return call(false, (void*)runtimeCallHelper, call_args);
#endif
}
RewriterVar* JitFragmentWriter::emitUnaryop(RewriterVar* v, int op_type) {
#if ENABLE_BASELINEJIT_ICS
return call(false, (void*)unaryopICHelper, imm(new UnaryopIC), v, imm(op_type));
#else
return call(false, (void*)unaryop, v, imm(op_type));
#endif
return emitPPCall((void*)unaryop, { v, imm(op_type) }, 2, 160);
}
RewriterVar* JitFragmentWriter::emitUnpackIntoArray(RewriterVar* v, uint64_t num) {
......@@ -414,11 +410,7 @@ void JitFragmentWriter::emitReturn(RewriterVar* v) {
}
void JitFragmentWriter::emitSetAttr(RewriterVar* obj, BoxedString* s, RewriterVar* attr) {
#if ENABLE_BASELINEJIT_ICS
call(false, (void*)setAttrICHelper, imm(new SetAttrIC), obj, imm(s), attr);
#else
call(false, (void*)setattr, obj, imm(s), attr);
#endif
emitPPCall((void*)setattr, { obj, imm(s), attr }, 2, 512);
}
void JitFragmentWriter::emitSetBlockLocal(InternedString s, RewriterVar* v) {
......@@ -434,19 +426,11 @@ void JitFragmentWriter::emitSetExcInfo(RewriterVar* type, RewriterVar* value, Re
}
void JitFragmentWriter::emitSetGlobal(Box* global, BoxedString* s, RewriterVar* v) {
#if ENABLE_BASELINEJIT_ICS
call(false, (void*)setGlobalICHelper, imm(new SetGlobalIC), imm(global), imm(s), v);
#else
call(false, (void*)setGlobal, imm(global), imm(s), v);
#endif
emitPPCall((void*)setGlobal, { imm(global), imm(s), v }, 2, 512);
}
void JitFragmentWriter::emitSetItem(RewriterVar* target, RewriterVar* slice, RewriterVar* value) {
#if ENABLE_BASELINEJIT_ICS
call(false, (void*)setitemICHelper, imm(new SetItemIC), target, slice, value);
#else
call(false, (void*)setitem, target, slice, value);
#endif
emitPPCall((void*)setitem, { target, slice, value }, 2, 512);
}
void JitFragmentWriter::emitSetItemName(BoxedString* s, RewriterVar* v) {
......@@ -524,6 +508,22 @@ int JitFragmentWriter::finishCompilation() {
block_patch_locations[side_exit_patch_location.first].push_back(patch_location);
}
for (auto&& pp_info : pp_infos) {
SpillMap _spill_map;
uint8_t* start_addr = pp_info.start_addr;
uint8_t* end_addr = pp_info.end_addr;
std::pair<uint8_t*, uint8_t*> p
= initializePatchpoint3(pp_info.func_addr, start_addr, end_addr, 0 /* scratch_offset */,
0 /* scratch_size */, std::unordered_set<int>(), _spill_map);
uint8_t* slowpath_start = p.first;
uint8_t* slowpath_rtn_addr = p.second;
std::unique_ptr<ICInfo> pp
= registerCompiledPatchpoint(start_addr, slowpath_start, end_addr, slowpath_rtn_addr, pp_info.ic.get(),
pp_info.stack_info, std::unordered_set<int>());
pp.release();
}
void* next_fragment_start = (uint8_t*)block->code + assembler->bytesWritten();
code_block.fragmentFinished(assembler->bytesWritten(), num_bytes_overlapping, next_fragment_start);
return num_bytes_exit;
......@@ -569,23 +569,20 @@ RewriterVar* JitFragmentWriter::getInterp() {
return interp;
}
Box* JitFragmentWriter::augbinopICHelper(AugBinopIC* ic, Box* lhs, Box* rhs, int op) {
return ic->call(lhs, rhs, op);
}
Box* JitFragmentWriter::binopICHelper(BinopIC* ic, Box* lhs, Box* rhs, int op) {
return ic->call(lhs, rhs, op);
}
RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots,
int slot_size) {
RewriterVar::SmallVector args_vec(args.begin(), args.end());
#if ENABLE_BASELINEJIT_ICS
Box* JitFragmentWriter::callattrHelperIC(Box* obj, BoxedString* attr, CallattrFlags flags, CallattrIC* ic, Box** args) {
auto arg_tuple = getTupleFromArgsArray(&args[0], flags.argspec.totalPassed());
return ic->call(obj, attr, flags, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple), NULL,
NULL);
}
RewriterVar* result = createNewVar();
addAction([=]() { this->_emitPPCall(result, func_addr, args_vec, num_slots, slot_size); }, args,
ActionType::NORMAL);
return result;
#else
assert(args_vec.size() < 7);
return call(false, func_addr, args_vec);
#endif
}
Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args,
std::vector<BoxedString*>* keyword_names) {
auto arg_tuple = getTupleFromArgsArray(&args[0], flags.argspec.totalPassed());
......@@ -595,10 +592,6 @@ Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlag
return r;
}
Box* JitFragmentWriter::compareICHelper(CompareIC* ic, Box* lhs, Box* rhs, int op) {
return ic->call(lhs, rhs, op);
}
Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) {
BoxedDict* dict = (BoxedDict*)createDict();
for (uint64_t i = 0; i < num; ++i) {
......@@ -634,18 +627,6 @@ Box* JitFragmentWriter::exceptionMatchesHelper(Box* obj, Box* cls) {
return boxBool(exceptionMatches(obj, cls));
}
Box* JitFragmentWriter::getAttrICHelper(GetAttrIC* ic, Box* o, BoxedString* attr) {
return ic->call(o, attr);
}
Box* JitFragmentWriter::getGlobalICHelper(GetGlobalIC* ic, Box* o, BoxedString* s) {
return ic->call(o, s);
}
Box* JitFragmentWriter::getitemICHelper(GetItemIC* ic, Box* o, Box* attr) {
return ic->call(o, attr);
}
Box* JitFragmentWriter::hasnextHelper(Box* b) {
return boxBool(pyston::hasnext(b));
}
......@@ -658,13 +639,6 @@ Box* JitFragmentWriter::notHelper(Box* b) {
return boxBool(!b->nonzeroIC());
}
#if ENABLE_BASELINEJIT_ICS
Box* JitFragmentWriter::runtimeCallHelperIC(Box* obj, ArgPassSpec argspec, RuntimeCallIC* ic, Box** args) {
auto arg_tuple = getTupleFromArgsArray(&args[0], argspec.totalPassed());
return ic->call(obj, argspec, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple));
}
#endif
Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args,
std::vector<BoxedString*>* keyword_names) {
auto arg_tuple = getTupleFromArgsArray(&args[0], argspec.totalPassed());
......@@ -672,22 +646,6 @@ Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** a
std::get<3>(arg_tuple), keyword_names);
}
Box* JitFragmentWriter::setAttrICHelper(SetAttrIC* ic, Box* o, BoxedString* attr, Box* value) {
return ic->call(o, attr, value);
}
Box* JitFragmentWriter::setGlobalICHelper(SetGlobalIC* ic, Box* o, BoxedString* s, Box* v) {
return ic->call(o, s, v);
}
Box* JitFragmentWriter::setitemICHelper(SetItemIC* ic, Box* o, Box* attr, Box* value) {
return ic->call(o, attr, value);
}
Box* JitFragmentWriter::unaryopICHelper(UnaryopIC* ic, Box* obj, int op) {
return ic->call(obj, op);
}
void JitFragmentWriter::_emitJump(CFGBlock* b, RewriterVar* block_next, int& size_of_exit_to_interp) {
size_of_exit_to_interp = 0;
......@@ -733,6 +691,60 @@ void JitFragmentWriter::_emitOSRPoint(RewriterVar* result, RewriterVar* node_var
assertConsistent();
}
void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, const RewriterVar::SmallVector& args,
int num_slots, int slot_size) {
assembler::Register r = allocReg(assembler::R11);
if (args.size() > 6) { // only 6 args can get passed in registers.
assert(args.size() <= 6 + JitCodeBlock::num_stack_args);
for (int i = 6; i < args.size(); ++i) {
assembler::Register reg = args[i]->getInReg(Location::any(), true);
assembler->mov(reg, assembler::Indirect(assembler::RSP, sizeof(void*) * (i - 6)));
args[i]->bumpUse();
}
RewriterVar::SmallVector reg_args(args.begin(), args.begin() + 6);
assert(reg_args.size() == 6);
_setupCall(result, false, reg_args, RewriterVar::SmallVector());
} else
_setupCall(result, false, args, RewriterVar::SmallVector());
// make sure setupCall doesn't use R11
assert(vars_by_location.count(assembler::R11) == 0);
int pp_size = slot_size * num_slots;
// make space for patchpoint
uint8_t* pp_start = rewrite->getSlotStart() + assembler->bytesWritten();
constexpr int call_size = 16;
assembler->skipBytes(pp_size + call_size);
uint8_t* pp_end = rewrite->getSlotStart() + assembler->bytesWritten();
assert(assembler->hasFailed() || (pp_start + pp_size + call_size == pp_end));
std::unique_ptr<ICSetupInfo> setup_info(
ICSetupInfo::initialize(true, num_slots, slot_size, ICSetupInfo::Generic, NULL));
// calculate available scratch space
int pp_scratch_size = 0;
int pp_scratch_location = rewrite->getScratchRspOffset() + rewrite->getScratchSize();
for (int i = rewrite->getScratchSize() - 8; i >= 0; i -= 8) {
Location l(Location::Scratch, i);
if (vars_by_location.count(l))
break;
pp_scratch_size += 8;
pp_scratch_location -= 8;
}
StackInfo stack_info(pp_scratch_size, pp_scratch_location);
pp_infos.emplace_back(PPInfo{ func_addr, pp_start, pp_end, std::move(setup_info), stack_info });
assert(vars_by_location.count(assembler::RAX) == 0);
result->initializeInReg(assembler::RAX);
assertConsistent();
result->releaseIfNoUses();
}
void JitFragmentWriter::_emitReturn(RewriterVar* return_val) {
return_val->getInReg(assembler::RDX, true);
assembler->mov(assembler::Immediate(0ul), assembler::RAX); // TODO: use xor
......
......@@ -19,6 +19,7 @@
#include "asm_writing/rewriter.h"
#include "codegen/ast_interpreter.h"
#include "codegen/patchpoints.h"
#include "gc/heap.h"
#include "runtime/ics.h"
......@@ -32,17 +33,6 @@ class BoxedDict;
class BoxedList;
class BoxedTuple;
class SetGlobalIC;
class GetGlobalIC;
class SetAttrIC;
class GetAttrIC;
class SetItemIC;
class GetItemIC;
class CompareIC;
class AugBinopIC;
class UnaryopIC;
class RuntimeCallIC;
class JitFragmentWriter;
// This JIT tier is designed as Pystons entry level JIT tier (executed after a only a few dozens runs of a basic block)
......@@ -100,6 +90,7 @@ class JitFragmentWriter;
// mov %rsp,%rbp
// sub $0x108,%rsp ; setup scratch, 0x108 = scratch_size + 8 (=stack alignment)
// push %rdi ; save the pointer to ASTInterpreter instance
// sub $0x16,%rsp ; space for two func args passed on the stack
// jmpq *0x8(%rsi) ; jump to block->code
// possible values: first_JitFragment, second_JitFragment,...
//
......@@ -130,10 +121,14 @@ class JitFragmentWriter;
//
//
class JitCodeBlock {
private:
public:
static constexpr int scratch_size = 256;
static constexpr int code_size = 4096 * 2;
static constexpr int code_size = 32768;
static constexpr int num_stack_args = 2;
static constexpr int interpreter_ptr_offset = num_stack_args * 8;
private:
EHFrameManager frame_manager;
std::unique_ptr<uint8_t[]> code;
int entry_offset;
......@@ -178,6 +173,16 @@ private:
// it in this field and process it only when we know we successfully generated the code.
std::pair<CFGBlock*, int /* offset from fragment start*/> side_exit_patch_location;
struct PPInfo {
void* func_addr;
uint8_t* start_addr;
uint8_t* end_addr;
std::unique_ptr<ICSetupInfo> ic;
StackInfo stack_info;
};
llvm::SmallVector<PPInfo, 8> pp_infos;
public:
JitFragmentWriter(CFGBlock* block, std::unique_ptr<ICInfo> ic_info, std::unique_ptr<ICSlotRewrite> rewrite,
int code_offset, int num_bytes_overlapping, void* entry_code, JitCodeBlock& code_block);
......@@ -250,35 +255,24 @@ private:
#endif
RewriterVar* getInterp();
static Box* augbinopICHelper(AugBinopIC* ic, Box* lhs, Box* rhs, int op);
static Box* binopICHelper(BinopIC* ic, Box* lhs, Box* rhs, int op);
RewriterVar* emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, int num_slots, int slot_size);
static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args,
std::vector<BoxedString*>* keyword_names);
static Box* compareICHelper(CompareIC* ic, Box* lhs, Box* rhs, int op);
static Box* createDictHelper(uint64_t num, Box** keys, Box** values);
static Box* createListHelper(uint64_t num, Box** data);
static Box* createSetHelper(uint64_t num, Box** data);
static Box* createTupleHelper(uint64_t num, Box** data);
static Box* exceptionMatchesHelper(Box* obj, Box* cls);
static Box* getAttrICHelper(GetAttrIC* ic, Box* o, BoxedString* attr);
static Box* getGlobalICHelper(GetGlobalIC* ic, Box* o, BoxedString* s);
static Box* getitemICHelper(GetItemIC* ic, Box* o, Box* attr);
static Box* hasnextHelper(Box* b);
static Box* nonzeroHelper(Box* b);
static Box* notHelper(Box* b);
static Box* runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args, std::vector<BoxedString*>* keyword_names);
static Box* setAttrICHelper(SetAttrIC* ic, Box* o, BoxedString* attr, Box* value);
static Box* setGlobalICHelper(SetGlobalIC* ic, Box* o, BoxedString* s, Box* v);
static Box* setitemICHelper(SetItemIC* ic, Box* o, Box* attr, Box* value);
static Box* unaryopICHelper(UnaryopIC* ic, Box* obj, int op);
#if ENABLE_BASELINEJIT_ICS
static Box* callattrHelperIC(Box* obj, BoxedString* attr, CallattrFlags flags, CallattrIC* ic, Box** args);
static Box* runtimeCallHelperIC(Box* obj, ArgPassSpec argspec, RuntimeCallIC* ic, Box** args);
#endif
void _emitJump(CFGBlock* b, RewriterVar* block_next, int& size_of_exit_to_interp);
void _emitOSRPoint(RewriterVar* result, RewriterVar* node_var);
void _emitPPCall(RewriterVar* result, void* func_addr, const RewriterVar::SmallVector& args, int num_slots,
int slot_size);
void _emitReturn(RewriterVar* v);
void _emitSideExit(RewriterVar* var, RewriterVar* val_constant, CFGBlock* next_block, RewriterVar* false_path);
};
......
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