Commit 0814d218 authored by Marius Wachtler's avatar Marius Wachtler Committed by GitHub

Merge pull request #1338 from undingen/fix_pointer_reuse_problems

Fix pointer reuse problems
parents 0abee106 64961ca3
......@@ -23,6 +23,7 @@
#include "asm_writing/assembler.h"
#include "asm_writing/mc_writer.h"
#include "codegen/patchpoints.h"
#include "codegen/type_recording.h"
#include "codegen/unwinding.h"
#include "core/common.h"
#include "core/options.h"
......@@ -339,14 +340,12 @@ static llvm::DenseMap<AST*, ICInfo*> ics_by_ast_node;
ICInfo::ICInfo(void* start_addr, void* slowpath_rtn_addr, void* continue_addr, StackInfo stack_info, int size,
llvm::CallingConv::ID calling_conv, LiveOutSet _live_outs, assembler::GenericRegister return_register,
TypeRecorder* type_recorder, std::vector<Location> ic_global_decref_locations,
assembler::RegisterSet allocatable_registers)
std::vector<Location> ic_global_decref_locations, assembler::RegisterSet allocatable_registers)
: next_slot_to_try(0),
stack_info(stack_info),
calling_conv(calling_conv),
live_outs(std::move(_live_outs)),
return_register(return_register),
type_recorder(type_recorder),
retry_in(0),
retry_backoff(1),
times_rewritten(0),
......@@ -416,7 +415,7 @@ std::unique_ptr<ICInfo> registerCompiledPatchpoint(uint8_t* start_addr, uint8_t*
ICInfo* icinfo
= new ICInfo(start_addr, slowpath_rtn_addr, continue_addr, stack_info, ic->size, ic->getCallingConvention(),
std::move(live_outs), return_register, ic->type_recorder, decref_info, ic->allocatable_regs);
std::move(live_outs), return_register, decref_info, ic->allocatable_regs);
assert(!ics_by_return_addr.count(slowpath_rtn_addr));
ics_by_return_addr[slowpath_rtn_addr] = icinfo;
......@@ -487,9 +486,10 @@ ICInfo* ICInfo::getICInfoForNode(AST* node) {
return it->second;
return NULL;
}
void ICInfo::associateNodeWithICInfo(AST* node) {
void ICInfo::associateNodeWithICInfo(AST* node, std::unique_ptr<TypeRecorder> type_recorder) {
assert(!this->node);
this->node = node;
this->type_recorder = std::move(type_recorder);
ics_by_ast_node[node] = this;
}
void ICInfo::appendDecrefInfosTo(std::vector<DecrefInfo>& dest_decref_infos) {
......
......@@ -93,7 +93,7 @@ private:
const llvm::CallingConv::ID calling_conv;
LiveOutSet live_outs;
const assembler::GenericRegister return_register;
TypeRecorder* const type_recorder;
std::unique_ptr<TypeRecorder> type_recorder;
int retry_in, retry_backoff;
int times_rewritten;
assembler::RegisterSet allocatable_registers;
......@@ -113,7 +113,7 @@ private:
public:
ICInfo(void* start_addr, void* slowpath_rtn_addr, void* continue_addr, StackInfo stack_info, int size,
llvm::CallingConv::ID calling_conv, LiveOutSet live_outs, assembler::GenericRegister return_register,
TypeRecorder* type_recorder, std::vector<Location> ic_global_decref_locations,
std::vector<Location> ic_global_decref_locations,
assembler::RegisterSet allocatable_registers = assembler::RegisterSet::stdAllocatable());
~ICInfo();
void* const start_addr, *const slowpath_rtn_addr, *const continue_addr;
......@@ -123,6 +123,7 @@ public:
llvm::CallingConv::ID getCallingConvention() { return calling_conv; }
const LiveOutSet& getLiveOuts() { return live_outs; }
TypeRecorder* getTypeRecorder() { return type_recorder.get(); }
std::unique_ptr<ICSlotRewrite> startRewrite(const char* debug_name);
void invalidate(ICSlotInfo* entry);
......@@ -145,7 +146,7 @@ public:
friend class ICSlotRewrite;
static ICInfo* getICInfoForNode(AST* node);
void associateNodeWithICInfo(AST* node);
void associateNodeWithICInfo(AST* node, std::unique_ptr<TypeRecorder> type_recorder);
void appendDecrefInfosTo(std::vector<DecrefInfo>& dest_decref_infos);
};
......@@ -179,7 +180,7 @@ public:
ICInfo* getICInfo() { return ic_entry->ic; }
int getSlotSize() { return ic_entry->size; }
uint8_t* getSlotStart() { return ic_entry->start_addr; }
TypeRecorder* getTypeRecorder() { return getICInfo()->type_recorder; }
TypeRecorder* getTypeRecorder() { return getICInfo()->getTypeRecorder(); }
assembler::GenericRegister returnRegister() { return getICInfo()->return_register; }
int getScratchSize() { return getICInfo()->stack_info.scratch_size; }
int getScratchRspOffset() {
......
......@@ -179,6 +179,7 @@ public:
RewriterVar* cmp(AST_TYPE::AST_TYPE cmp_type, RewriterVar* other, Location loc = Location::any());
RewriterVar* toBool(Location loc = Location::any());
RefType getType() const { return reftype; }
RewriterVar* setType(RefType type);
RewriterVar* setNullable(bool nullable) {
this->nullable = nullable;
......
......@@ -129,6 +129,7 @@ JitCodeBlock::~JitCodeBlock() {
for (auto&& block : md->source->cfg->blocks) {
block_patch_locations.erase(block);
blocks_aborted.erase(block);
}
}
......@@ -148,8 +149,8 @@ std::unique_ptr<JitFragmentWriter> JitCodeBlock::newFragment(CFGBlock* block, in
long bytes_left = a.bytesLeft() + patch_jump_offset;
constexpr assembler::RegisterSet bjit_allocatable_regs = assembler::RegisterSet::stdAllocatable() | additional_regs;
std::unique_ptr<ICInfo> ic_info(new ICInfo(fragment_start, nullptr, nullptr, stack_info, bytes_left,
llvm::CallingConv::C, live_outs, assembler::RAX, 0,
std::vector<Location>(), bjit_allocatable_regs));
llvm::CallingConv::C, live_outs, assembler::RAX, std::vector<Location>(),
bjit_allocatable_regs));
std::unique_ptr<ICSlotRewrite> rewrite = ic_info->startRewrite("");
return std::unique_ptr<JitFragmentWriter>(
......@@ -226,7 +227,8 @@ RewriterVar* JitFragmentWriter::imm(void* val) {
}
RewriterVar* JitFragmentWriter::emitAugbinop(AST_expr* node, RewriterVar* lhs, RewriterVar* rhs, int op_type) {
return emitPPCall((void*)augbinop, { lhs, rhs, imm(op_type) }, 2 * 320, node).first->setType(RefType::OWNED);
return emitPPCall((void*)augbinop, { lhs, rhs, imm(op_type) }, 2 * 320, true /* record type */, node)
.first->setType(RefType::OWNED);
}
RewriterVar* JitFragmentWriter::emitApplySlice(RewriterVar* target, RewriterVar* lower, RewriterVar* upper) {
......@@ -238,14 +240,13 @@ RewriterVar* JitFragmentWriter::emitApplySlice(RewriterVar* target, RewriterVar*
}
RewriterVar* JitFragmentWriter::emitBinop(AST_expr* node, RewriterVar* lhs, RewriterVar* rhs, int op_type) {
return emitPPCall((void*)binop, { lhs, rhs, imm(op_type) }, 2 * 240, node).first->setType(RefType::OWNED);
return emitPPCall((void*)binop, { lhs, rhs, imm(op_type) }, 2 * 240, true /* record type */, node)
.first->setType(RefType::OWNED);
}
RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, BoxedString* attr, CallattrFlags flags,
const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS
RewriterVar* attr_var = imm(attr);
RewriterVar* flags_var = imm(flags.asInt());
......@@ -269,7 +270,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B
if (keyword_names)
call_args.push_back(imm(keyword_names));
return emitPPCall((void*)callattr, call_args, 2 * 640, node, type_recorder, additional_uses)
return emitPPCall((void*)callattr, call_args, 2 * 640, true /* record type */, node, additional_uses)
.first->setType(RefType::OWNED);
#else
// We could make this faster but for now: keep it simple, stupid...
......@@ -288,8 +289,6 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B
call_args.push_back(attr_var);
call_args.push_back(flags_var);
call_args.push_back(imm(type_recorder));
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
......@@ -304,7 +303,8 @@ RewriterVar* JitFragmentWriter::emitCompare(AST_expr* node, RewriterVar* lhs, Re
RewriterVar* cmp_result = lhs->cmp(op_type == AST_TYPE::IsNot ? AST_TYPE::NotEq : AST_TYPE::Eq, rhs);
return call(false, (void*)boxBool, cmp_result)->setType(RefType::OWNED);
}
return emitPPCall((void*)compare, { lhs, rhs, imm(op_type) }, 2 * 240, node).first->setType(RefType::OWNED);
return emitPPCall((void*)compare, { lhs, rhs, imm(op_type) }, 2 * 240, true /* record type */, node)
.first->setType(RefType::OWNED);
}
RewriterVar* JitFragmentWriter::emitCreateDict() {
......@@ -387,7 +387,7 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
}
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node) {
return emitPPCall((void*)getattr, { obj, imm(s) }, 2 * 256, node, getTypeRecorderForNode(node))
return emitPPCall((void*)getattr, { obj, imm(s) }, 2 * 256, true /* record type */, node)
.first->setType(RefType::OWNED);
}
......@@ -432,7 +432,8 @@ RewriterVar* JitFragmentWriter::emitGetGlobal(BoxedString* s) {
}
RewriterVar* JitFragmentWriter::emitGetItem(AST_expr* node, RewriterVar* value, RewriterVar* slice) {
return emitPPCall((void*)getitem, { value, slice }, 256, node).first->setType(RefType::OWNED);
return emitPPCall((void*)getitem, { value, slice }, 256, true /* record type */, node)
.first->setType(RefType::OWNED);
}
RewriterVar* JitFragmentWriter::emitGetLocal(InternedString s, int vreg) {
......@@ -504,8 +505,6 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) {
RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj, ArgPassSpec argspec,
const llvm::ArrayRef<RewriterVar*> args,
std::vector<BoxedString*>* keyword_names) {
TypeRecorder* type_recorder = getTypeRecorderForNode(node);
#if ENABLE_BASELINEJIT_ICS
RewriterVar* argspec_var = imm(argspec.asInt());
RewriterVar::SmallVector call_args;
......@@ -525,7 +524,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj
if (keyword_names)
call_args.push_back(imm(keyword_names));
return emitPPCall((void*)runtimeCall, call_args, 2 * 640, node, type_recorder, additional_uses)
return emitPPCall((void*)runtimeCall, call_args, 2 * 640, node != NULL /* record type */, node, additional_uses)
.first->setType(RefType::OWNED);
#else
RewriterVar* argspec_var = imm(argspec.asInt());
......@@ -540,7 +539,6 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj
RewriterVar::SmallVector call_args;
call_args.push_back(obj);
call_args.push_back(argspec_var);
call_args.push_back(imm(type_recorder));
if (args_array)
call_args.push_back(args_array);
if (keyword_names_var)
......@@ -684,7 +682,7 @@ void JitFragmentWriter::emitReturn(RewriterVar* v) {
}
void JitFragmentWriter::emitSetAttr(AST_expr* node, RewriterVar* obj, BoxedString* s, STOLEN(RewriterVar*) attr) {
auto rtn = emitPPCall((void*)setattr, { obj, imm(s), attr }, 2 * 256, node);
auto rtn = emitPPCall((void*)setattr, { obj, imm(s), attr }, 2 * 256, false /* don't record type */, node);
attr->refConsumed(rtn.second);
}
......@@ -863,7 +861,10 @@ std::pair<int, llvm::DenseSet<int>> JitFragmentWriter::finishCompilation() {
std::unique_ptr<ICInfo> pp = registerCompiledPatchpoint(
start_addr, slowpath_start, initialization_info.continue_addr, slowpath_rtn_addr, pp_info.ic.get(),
pp_info.stack_info, LiveOutSet(), std::move(pp_info.decref_infos));
pp->associateNodeWithICInfo(pp_info.node);
if (pp_info.node)
pp->associateNodeWithICInfo(pp_info.node, std::move(pp_info.type_recorder));
else
assert(!pp_info.type_recorder);
ic_infos.push_back(std::move(pp));
}
......@@ -925,11 +926,10 @@ uint64_t JitFragmentWriter::asUInt(InternedString s) {
#endif
std::pair<RewriterVar*, RewriterAction*>
JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, unsigned short pp_size, AST* ast_node,
TypeRecorder* type_recorder, llvm::ArrayRef<RewriterVar*> additional_uses) {
JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args, unsigned short pp_size,
bool should_record_type, AST* ast_node, llvm::ArrayRef<RewriterVar*> additional_uses) {
if (LOG_BJIT_ASSEMBLY)
comment("BJIT: emitPPCall() start");
RewriterVar::SmallVector args_vec(args.begin(), args.end());
#if ENABLE_BASELINEJIT_ICS
RewriterVar* result = createNewVar();
......@@ -941,6 +941,9 @@ JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args
unsigned char num_additional = additional_uses.size();
RewriterVar** args_array = args_array_ref.data();
if (should_record_type)
assert(ast_node);
RewriterAction* call_action
= addAction([this, result, func_addr, ast_node, args_array, args_size, pp_size, num_additional]() {
auto all_args = llvm::makeArrayRef(args_array, args_size + num_additional);
......@@ -948,13 +951,12 @@ JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args
this->_emitPPCall(result, func_addr, args, pp_size, ast_node, all_args);
}, args_array_ref, ActionType::NORMAL);
if (type_recorder) {
RewriterVar* type_recorder_var = imm(type_recorder);
if (should_record_type) {
RewriterVar* obj_cls_var = result->getAttr(offsetof(Box, cls));
addAction([=]() {
_emitRecordType(type_recorder_var, obj_cls_var);
_emitRecordType(obj_cls_var);
result->bumpUse();
}, { type_recorder_var, obj_cls_var, result }, ActionType::NORMAL);
}, { obj_cls_var, result }, ActionType::NORMAL);
emitPendingCallsCheck();
return std::make_pair(result, call_action);
......@@ -964,6 +966,7 @@ JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args
comment("BJIT: emitPPCall() end");
return std::make_pair(result, call_action);
#else
RewriterVar::SmallVector args_vec(args.begin(), args.end());
assert(args_vec.size() < 7);
RewriterVar* result = call(false, func_addr, args_vec);
RewriterAction* call_action = getLastAction();
......@@ -978,12 +981,12 @@ void JitFragmentWriter::assertNameDefinedHelper(const char* id) {
assertNameDefined(0, id, UnboundLocalError, true);
}
Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
Box** args, std::vector<BoxedString*>* keyword_names) {
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());
Box* r = callattr(obj, attr, flags, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple), keyword_names);
return recordType(type_recorder, r);
return r;
}
Box* JitFragmentWriter::createDictHelper(uint64_t num, Box** keys, Box** values) {
......@@ -1037,12 +1040,12 @@ BORROWED(Box*) JitFragmentWriter::notHelper(Box* b) {
return b->nonzeroIC() ? Py_False : Py_True;
}
Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, TypeRecorder* type_recorder, Box** args,
Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args,
std::vector<BoxedString*>* keyword_names) {
auto arg_tuple = getTupleFromArgsArray(&args[0], argspec.totalPassed());
Box* r = runtimeCall(obj, argspec, std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
std::get<3>(arg_tuple), keyword_names);
return recordType(type_recorder, r);
return r;
}
void JitFragmentWriter::_emitGetLocal(RewriterVar* val_var, const char* name) {
......@@ -1159,7 +1162,7 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::
regs |= assembler::RegisterSet(reg);
}
std::unique_ptr<ICSetupInfo> setup_info(ICSetupInfo::initialize(true, pp_size, ICSetupInfo::Generic, NULL, regs));
std::unique_ptr<ICSetupInfo> setup_info(ICSetupInfo::initialize(true, pp_size, ICSetupInfo::Generic, regs));
// calculate available scratch space
......@@ -1178,8 +1181,8 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::
StackInfo stack_info(pp_scratch_size, pp_scratch_location);
auto&& decref_infos = getDecrefLocations();
pp_infos.emplace_back(
PPInfo{ func_addr, pp_start, pp_end, std::move(setup_info), stack_info, ast_node, std::move(decref_infos) });
pp_infos.emplace_back(PPInfo{ func_addr, pp_start, pp_end, std::move(setup_info), stack_info, ast_node,
std::move(decref_infos), std::unique_ptr<TypeRecorder>() });
assert(vars_by_location.count(assembler::RAX) == 0);
result->initializeInReg(assembler::RAX);
......@@ -1192,11 +1195,15 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::
}
}
void JitFragmentWriter::_emitRecordType(RewriterVar* type_recorder_var, RewriterVar* obj_cls_var) {
// This directly emits the instructions of the recordType() function.
void JitFragmentWriter::_emitRecordType(RewriterVar* obj_cls_var) {
assert(!pp_infos.back().type_recorder);
TypeRecorder* type_recorder = new TypeRecorder;
pp_infos.back().type_recorder.reset(type_recorder);
// This directly emits the instructions of the recordType() function.
assembler::Register obj_cls_reg = obj_cls_var->getInReg();
assembler::Register type_recorder_reg = type_recorder_var->getInReg(Location::any(), true, obj_cls_reg);
assembler::Register type_recorder_reg = allocReg(Location::any(), obj_cls_reg);
const_loader.loadConstIntoReg((uint64_t)type_recorder, type_recorder_reg);
assembler::Indirect last_seen_count = assembler::Indirect(type_recorder_reg, offsetof(TypeRecorder, last_count));
assembler::Indirect last_seen_indirect = assembler::Indirect(type_recorder_reg, offsetof(TypeRecorder, last_seen));
......@@ -1208,7 +1215,6 @@ void JitFragmentWriter::_emitRecordType(RewriterVar* type_recorder_var, Rewriter
}
assembler->incq(last_seen_count);
type_recorder_var->bumpUse();
obj_cls_var->bumpUse();
}
......
......@@ -251,6 +251,7 @@ private:
StackInfo stack_info;
AST* node;
std::vector<Location> decref_infos;
std::unique_ptr<TypeRecorder> type_recorder;
};
llvm::SmallVector<PPInfo, 8> pp_infos;
......@@ -349,13 +350,13 @@ private:
RewriterVar* emitCallWithAllocatedArgs(void* func_addr, const llvm::ArrayRef<RewriterVar*> args,
const llvm::ArrayRef<RewriterVar*> additional_uses);
std::pair<RewriterVar*, RewriterAction*> emitPPCall(void* func_addr, llvm::ArrayRef<RewriterVar*> args,
unsigned short pp_size, AST* ast_node = NULL,
TypeRecorder* type_recorder = NULL,
unsigned short pp_size, bool should_record_type = false,
AST* ast_node = NULL,
llvm::ArrayRef<RewriterVar*> additional_uses = {});
static void assertNameDefinedHelper(const char* id);
static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, TypeRecorder* type_recorder,
Box** args, std::vector<BoxedString*>* keyword_names);
static Box* callattrHelper(Box* obj, BoxedString* attr, CallattrFlags flags, Box** args,
std::vector<BoxedString*>* keyword_names);
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);
......@@ -364,15 +365,14 @@ private:
static BORROWED(Box*) hasnextHelper(Box* b);
static BORROWED(Box*) nonzeroHelper(Box* b);
static BORROWED(Box*) notHelper(Box* b);
static Box* runtimeCallHelper(Box* obj, ArgPassSpec argspec, TypeRecorder* type_recorder, Box** args,
std::vector<BoxedString*>* keyword_names);
static Box* runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** args, std::vector<BoxedString*>* keyword_names);
void _emitGetLocal(RewriterVar* val_var, const char* name);
void _emitJump(CFGBlock* b, RewriterVar* block_next, ExitInfo& exit_info);
void _emitOSRPoint();
void _emitPPCall(RewriterVar* result, void* func_addr, llvm::ArrayRef<RewriterVar*> args, unsigned short pp_size,
AST* ast_node, llvm::ArrayRef<RewriterVar*> vars_to_bump);
void _emitRecordType(RewriterVar* type_recorder_var, RewriterVar* obj_cls_var);
void _emitRecordType(RewriterVar* obj_cls_var);
void _emitReturn(RewriterVar* v);
void _emitSideExit(STOLEN(RewriterVar*) var, RewriterVar* val_constant, CFGBlock* next_block,
RewriterVar* false_path);
......
......@@ -246,7 +246,7 @@ public:
bool do_patchpoint = ENABLE_ICSETATTRS;
llvm::Instruction* inst;
if (do_patchpoint) {
auto pp = createSetattrIC(info.getTypeRecorder(), info.getBJitICInfo());
auto pp = createSetattrIC(info.getBJitICInfo());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -269,7 +269,7 @@ public:
bool do_patchpoint = false;
if (do_patchpoint) {
auto pp = createDelattrIC(info.getTypeRecorder());
auto pp = createDelattrIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -316,7 +316,7 @@ public:
bool do_patchpoint = ENABLE_ICGENERICS;
llvm::Value* rtn;
if (do_patchpoint) {
auto pp = createGenericIC(info.getTypeRecorder(), true, 256);
auto pp = createGenericIC(true, 256);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -350,7 +350,7 @@ public:
: emitter.setType(getNullPtr(g.llvm_value_type_ptr), RefType::BORROWED);
llvm::Value* r = NULL;
if (do_patchpoint) {
auto pp = createGetitemIC(info.getTypeRecorder(), info.getBJitICInfo());
auto pp = createGetitemIC(info.getBJitICInfo());
llvm::Instruction* uncasted = emitter.createIC(
std::move(pp),
(void*)(target_exception_style == CAPI ? pyston::apply_slice : pyston::applySlice),
......@@ -377,7 +377,7 @@ public:
llvm::Value* rtn;
if (do_patchpoint) {
auto pp = createGetitemIC(info.getTypeRecorder(), info.getBJitICInfo());
auto pp = createGetitemIC(info.getBJitICInfo());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -428,7 +428,7 @@ public:
// var has __iter__()
emitter.setCurrentBasicBlock(bb_has_iter);
auto pp = createGenericIC(info.getTypeRecorder(), true, 128);
auto pp = createGenericIC(true, 128);
llvm::Instruction* uncasted = emitter.createIC(std::move(pp), (void*)pyston::createBoxedIterWrapperIfNeeded,
{ converted_iter_call->getValue() }, info.unw_info);
llvm::Value* value_has_iter = createAfter<llvm::IntToPtrInst>(uncasted, uncasted, g.llvm_value_type_ptr, "");
......@@ -440,7 +440,7 @@ public:
// TODO: we could create a patchpoint if this turns out to be hot
emitter.setCurrentBasicBlock(bb_no_iter);
auto pp2 = createGenericIC(info.getTypeRecorder(), true, 128);
auto pp2 = createGenericIC(true, 128);
llvm::Instruction* value_no_iter
= emitter.createIC(std::move(pp2), (void*)getiterHelper, { var->getValue() }, info.unw_info);
value_no_iter = createAfter<llvm::IntToPtrInst>(value_no_iter, value_no_iter, g.llvm_value_type_ptr, "");
......@@ -483,7 +483,7 @@ public:
}
if (do_patchpoint) {
auto pp = createBinexpIC(info.getTypeRecorder(), info.getBJitICInfo());
auto pp = createBinexpIC(info.getBJitICInfo());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -571,7 +571,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
bool do_patchpoint = ENABLE_ICGETATTRS;
if (do_patchpoint) {
auto pp = createGetattrIC(info.getTypeRecorder(), info.getBJitICInfo());
auto pp = createGetattrIC(info.getBJitICInfo());
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -674,7 +674,7 @@ _call(IREmitter& emitter, const OpInfo& info, llvm::Value* func, ExceptionStyle
if (do_patchpoint) {
assert(func_addr);
auto pp = createCallsiteIC(info.getTypeRecorder(), args.size(), info.getBJitICInfo());
auto pp = createCallsiteIC(args.size(), info.getBJitICInfo());
llvm::Instruction* uncasted = emitter.createIC(std::move(pp), func_addr, llvm_args, info.unw_info,
target_exception_style, getNullPtr(g.llvm_value_type_ptr));
......@@ -782,7 +782,7 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
bool do_patchpoint = ENABLE_ICNONZEROS;
llvm::Value* rtn_val;
if (do_patchpoint) {
auto pp = createNonzeroIC(info.getTypeRecorder());
auto pp = createNonzeroIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......@@ -802,7 +802,7 @@ ConcreteCompilerVariable* UnknownType::unaryop(IREmitter& emitter, const OpInfo&
llvm::Value* rtn = NULL;
bool do_patchpoint = ENABLE_ICGENERICS;
if (do_patchpoint) {
auto pp = createGenericIC(info.getTypeRecorder(), true, 256);
auto pp = createGenericIC(true, 256);
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted->getValue());
......@@ -824,7 +824,7 @@ ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo&
do_patchpoint = false; // we are currently using runtime ics for this
llvm::Value* rtn_val;
if (do_patchpoint) {
auto pp = createHasnextIC(info.getTypeRecorder());
auto pp = createHasnextIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(var->getValue());
......
......@@ -163,20 +163,17 @@ llvm::Value* handlePotentiallyUndefined(ConcreteCompilerVariable* is_defined_var
std::function<llvm::Value*(IREmitter&)> when_defined,
std::function<llvm::Value*(IREmitter&)> when_undefined);
class TypeRecorder;
class OpInfo {
private:
const EffortLevel effort;
TypeRecorder* const type_recorder;
ICInfo* bjit_ic_info;
public:
const UnwindInfo unw_info;
OpInfo(EffortLevel effort, TypeRecorder* type_recorder, const UnwindInfo& unw_info, ICInfo* bjit_ic_info)
: effort(effort), type_recorder(type_recorder), bjit_ic_info(bjit_ic_info), unw_info(unw_info) {}
OpInfo(EffortLevel effort, const UnwindInfo& unw_info, ICInfo* bjit_ic_info)
: effort(effort), bjit_ic_info(bjit_ic_info), unw_info(unw_info) {}
TypeRecorder* getTypeRecorder() const { return type_recorder; }
ICInfo* getBJitICInfo() const { return bjit_ic_info; }
ExceptionStyle preferredExceptionStyle() const { return unw_info.preferredExceptionStyle(); }
......
......@@ -758,24 +758,15 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock, IRG
return new IREmitterImpl(irstate, curblock, irgenerator);
}
static std::unordered_map<AST_expr*, std::vector<BoxedString*>*> made_keyword_storage;
std::vector<BoxedString*>* getKeywordNameStorage(AST_Call* node) {
auto it = made_keyword_storage.find(node);
if (it != made_keyword_storage.end())
return it->second;
auto rtn = new std::vector<BoxedString*>();
made_keyword_storage.insert(it, std::make_pair(node, rtn));
// Only add the keywords to the array the first time, since
// the later times we will hit the cache which will have the
// keyword names already populated:
if (!rtn->size()) {
for (auto kw : node->keywords)
rtn->push_back(kw->arg.getBox());
if (!node->keywords_names) {
node->keywords_names = llvm::make_unique<std::vector<BoxedString*>>();
for (auto kw : node->keywords) {
node->keywords_names->push_back(kw->arg.getBox());
}
}
return rtn;
return node->keywords_names.get();
}
const std::string CREATED_CLOSURE_NAME = "#created_closure";
......@@ -843,25 +834,10 @@ private:
OpInfo getOpInfoForNode(AST* ast, const UnwindInfo& unw_info) {
assert(ast);
EffortLevel effort = irstate->getEffortLevel();
// This is the only place we create type recorders for the llvm tier;
// if we are ok with never doing that there's a bunch of code that could
// be removed.
bool record_types = false;
TypeRecorder* type_recorder;
if (record_types) {
type_recorder = getTypeRecorderForNode(ast);
} else {
type_recorder = NULL;
}
return OpInfo(irstate->getEffortLevel(), type_recorder, unw_info, ICInfo::getICInfoForNode(ast));
return OpInfo(irstate->getEffortLevel(), unw_info, ICInfo::getICInfoForNode(ast));
}
OpInfo getEmptyOpInfo(const UnwindInfo& unw_info) {
return OpInfo(irstate->getEffortLevel(), NULL, unw_info, NULL);
}
OpInfo getEmptyOpInfo(const UnwindInfo& unw_info) { return OpInfo(irstate->getEffortLevel(), unw_info, NULL); }
void createExprTypeGuard(llvm::Value* check_val, AST* node, llvm::Value* node_value, AST_stmt* current_statement) {
assert(check_val->getType() == g.i1);
......@@ -1320,7 +1296,7 @@ private:
bool do_patchpoint = ENABLE_ICGETGLOBALS;
if (do_patchpoint) {
auto pp = createGetGlobalIC(getOpInfoForNode(node, unw_info).getTypeRecorder());
auto pp = createGetGlobalIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(irstate->getGlobals());
......@@ -2012,7 +1988,7 @@ private:
bool do_patchpoint = ENABLE_ICSETITEMS;
if (do_patchpoint) {
auto pp = createSetitemIC(getEmptyOpInfo(unw_info).getTypeRecorder());
auto pp = createSetitemIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(target);
......@@ -2043,7 +2019,7 @@ private:
// patchpoints if it couldn't.
bool do_patchpoint = ENABLE_ICSETITEMS;
if (do_patchpoint) {
auto pp = createSetitemIC(getEmptyOpInfo(unw_info).getTypeRecorder());
auto pp = createSetitemIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted_target->getValue());
......@@ -2173,7 +2149,7 @@ private:
bool do_patchpoint = ENABLE_ICDELITEMS;
if (do_patchpoint) {
auto pp = createDelitemIC(getEmptyOpInfo(unw_info).getTypeRecorder());
auto pp = createDelitemIC();
std::vector<llvm::Value*> llvm_args;
llvm_args.push_back(converted_target->getValue());
......
......@@ -32,67 +32,6 @@
namespace pyston {
/*
static std::string getStringName(std::string strvalue) {
std::ostringstream name_os;
name_os << "str";
name_os << g.global_string_table.size();
name_os << '_';
for (int i = 0; i < strvalue.size(); i++) {
if (isalnum(strvalue[i]))
name_os << strvalue[i];
}
return name_os.str();
}
// Gets a reference (creating if necessary) to a global string constant with the given value.
// The return type will be a char array.
static llvm::Constant* getStringConstant(const std::string &str) {
if (g.global_string_table.find(str) != g.global_string_table.end()) {
llvm::GlobalVariable *gv = g.global_string_table[str];
llvm::Constant *rtn = g.cur_module->getOrInsertGlobal(gv->getName(), gv->getType()->getElementType());
return rtn;
}
int len = str.size();
std::vector<llvm::Constant*> chars;
for (int i = 0; i < len; i++) {
chars.push_back(llvm::ConstantInt::get(g.i8, str[i]));
}
llvm::ArrayType *at = llvm::ArrayType::get(g.i8, len);
llvm::Constant *val = llvm::ConstantArray::get(at, llvm::ArrayRef<llvm::Constant*>(chars));
llvm::GlobalVariable *gv = new llvm::GlobalVariable(*g.cur_module, at, true, llvm::GlobalValue::ExternalLinkage,
val, getStringName(str));
g.global_string_table[str] = gv;
return gv;
}
*/
std::unordered_map<std::string, const char*> strings;
/*
// Returns a llvm::Constant char* to a global string constant
llvm::Constant* getStringConstantPtr(llvm::StringRef str) {
const char* c;
if (strings.count(str)) {
c = strings[str];
} else {
char* buf = (char*)malloc(str.size() + 1);
memcpy(buf, str.c_str(), str.size());
buf[str.size()] = '\0';
strings[str] = buf;
c = buf;
}
return embedRelocatablePtr(c, g.i8->getPointerTo());
}
// Returns a llvm::Constant char* to a global string constant
llvm::Constant* getStringConstantPtr(llvm::StringRef str) {
return getStringConstantPtr(std::string(str, strlen(str) + 1));
}
*/
// Sometimes we want to embed pointers into the emitted code, usually to link the emitted code
// to some associated compiler-level data structure.
// It's slightly easier to emit them as integers (there are primitive integer constants but not pointer constants),
......
......@@ -45,10 +45,8 @@ int ICSetupInfo::totalSize() const {
static std::vector<std::pair<std::unique_ptr<PatchpointInfo>, void* /* addr of func to call */>> new_patchpoints;
std::unique_ptr<ICSetupInfo> ICSetupInfo::initialize(bool has_return_value, int size, ICType type,
TypeRecorder* type_recorder,
assembler::RegisterSet allocatable_regs) {
auto rtn
= std::unique_ptr<ICSetupInfo>(new ICSetupInfo(type, size, has_return_value, type_recorder, allocatable_regs));
auto rtn = std::unique_ptr<ICSetupInfo>(new ICSetupInfo(type, size, has_return_value, allocatable_regs));
// We use size == CALL_ONLY_SIZE to imply that the call isn't patchable
......@@ -382,57 +380,56 @@ int slotSize(ICInfo* bjit_ic_info, int default_size) {
return suggested_size;
}
std::unique_ptr<ICSetupInfo> createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size) {
return ICSetupInfo::initialize(has_return_value, size, ICSetupInfo::Generic, type_recorder);
std::unique_ptr<ICSetupInfo> createGenericIC(bool has_return_value, int size) {
return ICSetupInfo::initialize(has_return_value, size, ICSetupInfo::Generic);
}
std::unique_ptr<ICSetupInfo> createGetattrIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 1024), ICSetupInfo::Getattr, type_recorder);
std::unique_ptr<ICSetupInfo> createGetattrIC(ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 1024), ICSetupInfo::Getattr);
}
std::unique_ptr<ICSetupInfo> createGetitemIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 512), ICSetupInfo::Getitem, type_recorder);
std::unique_ptr<ICSetupInfo> createGetitemIC(ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 512), ICSetupInfo::Getitem);
}
std::unique_ptr<ICSetupInfo> createSetitemIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 512, ICSetupInfo::Setitem, type_recorder);
std::unique_ptr<ICSetupInfo> createSetitemIC() {
return ICSetupInfo::initialize(true, 512, ICSetupInfo::Setitem);
}
std::unique_ptr<ICSetupInfo> createDelitemIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(false, 512, ICSetupInfo::Delitem, type_recorder);
std::unique_ptr<ICSetupInfo> createDelitemIC() {
return ICSetupInfo::initialize(false, 512, ICSetupInfo::Delitem);
}
std::unique_ptr<ICSetupInfo> createSetattrIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(false, slotSize(bjit_ic_info, 1024), ICSetupInfo::Setattr, type_recorder);
std::unique_ptr<ICSetupInfo> createSetattrIC(ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(false, slotSize(bjit_ic_info, 1024), ICSetupInfo::Setattr);
}
std::unique_ptr<ICSetupInfo> createDelattrIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(false, 144, ICSetupInfo::Delattr, type_recorder);
std::unique_ptr<ICSetupInfo> createDelattrIC() {
return ICSetupInfo::initialize(false, 144, ICSetupInfo::Delattr);
}
std::unique_ptr<ICSetupInfo> createCallsiteIC(TypeRecorder* type_recorder, int num_args, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 4 * (640 + 48 * num_args)), ICSetupInfo::Callsite,
type_recorder);
std::unique_ptr<ICSetupInfo> createCallsiteIC(int num_args, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 4 * (640 + 48 * num_args)), ICSetupInfo::Callsite);
}
std::unique_ptr<ICSetupInfo> createGetGlobalIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 128, ICSetupInfo::GetGlobal, type_recorder);
std::unique_ptr<ICSetupInfo> createGetGlobalIC() {
return ICSetupInfo::initialize(true, 128, ICSetupInfo::GetGlobal);
}
std::unique_ptr<ICSetupInfo> createBinexpIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 2048), ICSetupInfo::Binexp, type_recorder);
std::unique_ptr<ICSetupInfo> createBinexpIC(ICInfo* bjit_ic_info) {
return ICSetupInfo::initialize(true, slotSize(bjit_ic_info, 2048), ICSetupInfo::Binexp);
}
std::unique_ptr<ICSetupInfo> createNonzeroIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 1024, ICSetupInfo::Nonzero, type_recorder);
std::unique_ptr<ICSetupInfo> createNonzeroIC() {
return ICSetupInfo::initialize(true, 1024, ICSetupInfo::Nonzero);
}
std::unique_ptr<ICSetupInfo> createHasnextIC(TypeRecorder* type_recorder) {
return ICSetupInfo::initialize(true, 128, ICSetupInfo::Hasnext, type_recorder);
std::unique_ptr<ICSetupInfo> createHasnextIC() {
return ICSetupInfo::initialize(true, 128, ICSetupInfo::Hasnext);
}
std::unique_ptr<ICSetupInfo> createDeoptIC() {
return ICSetupInfo::initialize(true, 0, ICSetupInfo::Deopt, NULL);
return ICSetupInfo::initialize(true, 0, ICSetupInfo::Deopt);
}
} // namespace pyston
......@@ -65,19 +65,13 @@ public:
};
private:
ICSetupInfo(ICType type, int size, bool has_return_value, TypeRecorder* type_recorder,
assembler::RegisterSet allocatable_regs)
: type(type),
size(size),
has_return_value(has_return_value),
type_recorder(type_recorder),
allocatable_regs(allocatable_regs) {}
ICSetupInfo(ICType type, int size, bool has_return_value, assembler::RegisterSet allocatable_regs)
: type(type), size(size), has_return_value(has_return_value), allocatable_regs(allocatable_regs) {}
public:
const ICType type;
const int size;
const bool has_return_value;
TypeRecorder* const type_recorder;
assembler::RegisterSet allocatable_regs;
int totalSize() const;
......@@ -97,9 +91,9 @@ public:
return llvm::CallingConv::C;
}
static std::unique_ptr<ICSetupInfo>
initialize(bool has_return_value, int size, ICType type, TypeRecorder* type_recorder,
assembler::RegisterSet allocatable_regs = assembler::RegisterSet::stdAllocatable());
static std::unique_ptr<ICSetupInfo> initialize(bool has_return_value, int size, ICType type,
assembler::RegisterSet allocatable_regs
= assembler::RegisterSet::stdAllocatable());
};
struct PatchpointInfo {
......@@ -178,18 +172,18 @@ public:
};
class ICInfo;
std::unique_ptr<ICSetupInfo> createGenericIC(TypeRecorder* type_recorder, bool has_return_value, int size);
std::unique_ptr<ICSetupInfo> createCallsiteIC(TypeRecorder* type_recorder, int num_args, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createGetGlobalIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createGetattrIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createSetattrIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createDelattrIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createGetitemIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createSetitemIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createDelitemIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createBinexpIC(TypeRecorder* type_recorder, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createNonzeroIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createHasnextIC(TypeRecorder* type_recorder);
std::unique_ptr<ICSetupInfo> createGenericIC(bool has_return_value, int size);
std::unique_ptr<ICSetupInfo> createCallsiteIC(int num_args, ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createGetGlobalIC();
std::unique_ptr<ICSetupInfo> createGetattrIC(ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createSetattrIC(ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createDelattrIC();
std::unique_ptr<ICSetupInfo> createGetitemIC(ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createSetitemIC();
std::unique_ptr<ICSetupInfo> createDelitemIC();
std::unique_ptr<ICSetupInfo> createBinexpIC(ICInfo* bjit_ic_info);
std::unique_ptr<ICSetupInfo> createNonzeroIC();
std::unique_ptr<ICSetupInfo> createHasnextIC();
std::unique_ptr<ICSetupInfo> createDeoptIC();
} // namespace pyston
......
......@@ -14,21 +14,12 @@
#include "codegen/type_recording.h"
#include <unordered_map>
#include "asm_writing/icinfo.h"
#include "core/options.h"
#include "core/types.h"
namespace pyston {
static std::unordered_map<AST*, std::unique_ptr<TypeRecorder>> type_recorders;
TypeRecorder* getTypeRecorderForNode(AST* node) {
std::unique_ptr<TypeRecorder>& r = type_recorders[node];
if (r == NULL)
r = llvm::make_unique<TypeRecorder>();
return r.get();
}
Box* recordType(TypeRecorder* self, Box* obj) {
// The baseline JIT directly generates machine code for this function inside JitFragmentWriter::_emitRecordType.
// When changing this function one has to also change the bjit code.
......@@ -52,11 +43,11 @@ Box* recordType(TypeRecorder* self, Box* obj) {
}
BoxedClass* predictClassFor(AST* node) {
auto it = type_recorders.find(node);
if (it == type_recorders.end())
ICInfo* ic = ICInfo::getICInfoForNode(node);
if (!ic || !ic->getTypeRecorder())
return NULL;
return it->second->predict();
return ic->getTypeRecorder()->predict();
}
BoxedClass* TypeRecorder::predict() {
......
......@@ -44,8 +44,6 @@ public:
friend Box* recordType(TypeRecorder*, Box*);
};
TypeRecorder* getTypeRecorderForNode(AST* node);
BoxedClass* predictClassFor(AST* node);
}
......
......@@ -353,6 +353,9 @@ public:
std::vector<AST_expr*> args;
std::vector<AST_keyword*> keywords;
// used during execution stores all keyword names
std::unique_ptr<std::vector<BoxedString*>> keywords_names;
virtual void accept(ASTVisitor* v);
virtual void* accept_expr(ExprVisitor* v);
......
......@@ -249,8 +249,7 @@ RuntimeIC::RuntimeIC(void* func_addr, int total_size) {
// printf("Allocated runtime IC at %p\n", addr);
std::unique_ptr<ICSetupInfo> setup_info(
ICSetupInfo::initialize(true, patchable_size, ICSetupInfo::Generic, NULL));
std::unique_ptr<ICSetupInfo> setup_info(ICSetupInfo::initialize(true, patchable_size, ICSetupInfo::Generic));
uint8_t* pp_start = (uint8_t*)addr + PROLOGUE_SIZE;
uint8_t* pp_end = pp_start + patchable_size + CALL_SIZE;
......
......@@ -2879,13 +2879,7 @@ template <ExceptionStyle S> Box* _getattrEntry(Box* obj, BoxedString* attr, void
rewriter->getArg(0)->setType(RefType::BORROWED);
rewriter->getArg(1)->setType(RefType::BORROWED);
Location dest;
TypeRecorder* recorder = rewriter->getTypeRecorder();
if (recorder)
dest = Location::forArg(1);
else
dest = rewriter->getReturnDestination();
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), dest);
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination());
val = getattrInternal<S>(obj, attr, &rewrite_args);
if (rewrite_args.isSuccessful()) {
......@@ -2914,16 +2908,9 @@ template <ExceptionStyle S> Box* _getattrEntry(Box* obj, BoxedString* attr, void
}
if (return_convention == ReturnConvention::HAS_RETURN
|| (S == CAPI && return_convention == ReturnConvention::CAPI_RETURN)) {
if (recorder) {
rtn = rewriter->call(false, (void*)recordType,
rewriter->loadConst((intptr_t)recorder, Location::forArg(0)), rtn);
recordType(recorder, val);
}
|| (S == CAPI && return_convention == ReturnConvention::CAPI_RETURN))
rewriter->commitReturning(rtn);
}
}
} else {
val = getattrInternal<S>(obj, attr);
}
......
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