Commit 7ece5755 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #786 from kmod/exceptions3

have the llvm jit start emitting some capi-style calls
parents bb31b6ee 2b4fd9cd
......@@ -1229,7 +1229,7 @@ endif
# depend on the first one.
$(firstword $(TEST_EXT_MODULE_OBJS)): $(TEST_EXT_MODULE_SRCS) | $(BUILD_PY)
$(VERB) cd $(TEST_DIR)/test_extension; time ../../$(BUILD_PY) setup.py build
$(VERB) cd $(TEST_DIR)/test_extension; ln -sf $(TEST_EXT_MODULE_NAMES:%=build/lib.linux2-2.7/%.pyston.so) .
$(VERB) cd $(TEST_DIR)/test_extension; ln -sf $(TEST_EXT_MODULE_NAMES:%=build/lib.linux-x86_64-2.7/%.pyston.so) .
$(VERB) touch -c $(TEST_EXT_MODULE_OBJS)
$(wordlist 2,9999,$(TEST_EXT_MODULE_OBJS)): $(firstword $(TEST_EXT_MODULE_OBJS))
$(firstword $(SHAREDMODS_OBJS)): $(SHAREDMODS_SRCS) | $(BUILD_PY)
......
......@@ -489,14 +489,24 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm::Value* rtn_val = NULL;
ExceptionStyle target_exception_style = CXX;
if (info.unw_info.capi_exc_dest)
target_exception_style = CAPI;
llvm::Value* llvm_func;
void* raw_func;
if (cls_only) {
assert(target_exception_style == CXX);
llvm_func = g.funcs.getclsattr;
raw_func = (void*)pyston::getclsattr;
} else {
llvm_func = g.funcs.getattr;
raw_func = (void*)pyston::getattr;
if (target_exception_style == CXX) {
llvm_func = g.funcs.getattr;
raw_func = (void*)pyston::getattr;
} else {
llvm_func = g.funcs.getattr_capi;
raw_func = (void*)pyston::getattr_capi;
}
}
bool do_patchpoint = ENABLE_ICGETATTRS;
......@@ -507,15 +517,20 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info);
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info, target_exception_style);
rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr);
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr, target_exception_style);
}
if (target_exception_style == CAPI)
emitter.checkAndPropagateCapiException(info.unw_info, rtn_val, getNullPtr(g.llvm_value_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, rtn_val, true);
}
static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, llvm::Value* func, void* func_addr,
static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, llvm::Value* func,
ExceptionStyle target_exception_style, void* func_addr,
const std::vector<llvm::Value*>& other_args, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names, ConcreteCompilerType* rtn_type) {
......@@ -551,7 +566,6 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
llvm_args.push_back(getNullPtr(g.llvm_value_type_ptr));
}
llvm::Value* mallocsave = NULL;
if (args.size() >= 4) {
llvm::Value* arg_array;
......@@ -594,7 +608,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
ICSetupInfo* pp = createCallsiteIC(info.getTypeRecorder(), args.size());
llvm::Value* uncasted = emitter.createIC(pp, func_addr, llvm_args, info.unw_info);
llvm::Value* uncasted = emitter.createIC(pp, func_addr, llvm_args, info.unw_info, target_exception_style);
assert(llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(func->getType())->getElementType())
->getReturnType() == g.llvm_value_type_ptr);
......@@ -608,13 +622,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
//}
// printf("%ld %ld\n", llvm_args.size(), args.size());
// printf("\n");
rtn = emitter.createCall(info.unw_info, func, llvm_args);
}
if (mallocsave) {
llvm::Value* l_free = embedConstantPtr(
(void*)free, llvm::FunctionType::get(g.void_, g.i8->getPointerTo(), false)->getPointerTo());
emitter.getBuilder()->CreateCall(l_free, mallocsave);
rtn = emitter.createCall(info.unw_info, func, llvm_args, target_exception_style);
}
for (int i = 0; i < args.size(); i++) {
......@@ -622,6 +630,11 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
}
assert(rtn->getType() == rtn_type->llvmType());
if (target_exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, rtn, getNullPtr(g.llvm_value_type_ptr));
}
return new ConcreteCompilerVariable(rtn_type, rtn, true);
}
......@@ -650,7 +663,7 @@ CompilerVariable* UnknownType::call(IREmitter& emitter, const OpInfo& info, Conc
llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false);
other_args.push_back(llvm_argspec);
return _call(emitter, info, func, (void*)runtimeCall, other_args, argspec, args, keyword_names, UNKNOWN);
return _call(emitter, info, func, CXX, (void*)runtimeCall, other_args, argspec, args, keyword_names, UNKNOWN);
}
CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
......@@ -678,7 +691,8 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
other_args.push_back(var->getValue());
other_args.push_back(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr));
other_args.push_back(getConstantInt(flags.asInt(), g.i64));
return _call(emitter, info, func, (void*)pyston::callattr, other_args, flags.argspec, args, keyword_names, UNKNOWN);
return _call(emitter, info, func, CXX, (void*)pyston::callattr, other_args, flags.argspec, args, keyword_names,
UNKNOWN);
}
ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
......@@ -1480,10 +1494,18 @@ public:
if (canStaticallyResolveGetattrs()) {
Box* rtattr = typeLookup(cls, attr, nullptr);
if (rtattr == NULL) {
ExceptionStyle exception_style = info.unw_info.capi_exc_dest ? CAPI : CXX;
llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr
: g.funcs.raiseAttributeErrorStrCapi;
llvm::CallSite call = emitter.createCall3(
info.unw_info, g.funcs.raiseAttributeErrorStr, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64));
call.setDoesNotReturn();
info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style);
if (exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
} else {
call.setDoesNotReturn();
}
return undefVariable();
}
......@@ -1623,8 +1645,8 @@ public:
std::vector<llvm::Value*> other_args;
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, argspec, new_args,
keyword_names, cf->spec->rtn_type);
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->exception_style, cf->code, other_args,
argspec, new_args, keyword_names, cf->spec->rtn_type);
assert(rtn->getType() == cf->spec->rtn_type);
assert(rtn->getType() != UNDEF);
......
......@@ -32,16 +32,19 @@ class IREmitter;
struct UnwindInfo {
public:
AST_stmt* current_stmt;
llvm::BasicBlock* exc_dest;
bool needsInvoke() { return exc_dest != NULL; }
llvm::BasicBlock* capi_exc_dest;
llvm::BasicBlock* cxx_exc_dest;
UnwindInfo(AST_stmt* current_stmt, llvm::BasicBlock* exc_dest) : current_stmt(current_stmt), exc_dest(exc_dest) {}
bool hasHandler() const { return cxx_exc_dest != NULL || capi_exc_dest != NULL; }
UnwindInfo(AST_stmt* current_stmt, llvm::BasicBlock* capi_exc_dest, llvm::BasicBlock* cxx_exc_dest)
: current_stmt(current_stmt), capi_exc_dest(capi_exc_dest), cxx_exc_dest(cxx_exc_dest) {}
// Risky! This means that we can't unwind from this location, and should be used in the
// rare case that there are language-specific reasons that the statement should not unwind
// (ex: loading function arguments into the appropriate scopes).
static UnwindInfo cantUnwind() { return UnwindInfo(NULL, NULL); }
static UnwindInfo cantUnwind() { return UnwindInfo(NULL, NULL, NULL); }
};
// TODO get rid of this
......@@ -78,16 +81,23 @@ public:
virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 0;
virtual llvm::Value* createCall(UnwindInfo unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args)
virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
const std::vector<llvm::Value*>& args, ExceptionStyle target_exception_style = CXX)
= 0;
virtual llvm::Value* createCall(UnwindInfo unw_info, llvm::Value* callee) = 0;
virtual llvm::Value* createCall(UnwindInfo unw_info, llvm::Value* callee, llvm::Value* arg1) = 0;
virtual llvm::Value* createCall2(UnwindInfo unw_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2)
virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
ExceptionStyle target_exception_style = CXX) = 0;
virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
ExceptionStyle target_exception_style = CXX) = 0;
virtual llvm::Value* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
llvm::Value* arg2, ExceptionStyle target_exception_style = CXX) = 0;
virtual llvm::Value* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
llvm::Value* arg2, llvm::Value* arg3, ExceptionStyle target_exception_style = CXX)
= 0;
virtual llvm::Value* createCall3(UnwindInfo unw_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2,
llvm::Value* arg3) = 0;
virtual llvm::Value* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
UnwindInfo unw_info) = 0;
const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX) = 0;
virtual void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val,
llvm::Value* exc_val, bool double_check = false) = 0;
virtual Box* getIntConstant(int64_t n) = 0;
virtual Box* getFloatConstant(double d) = 0;
......@@ -132,7 +142,7 @@ private:
public:
const UnwindInfo unw_info;
OpInfo(EffortLevel effort, TypeRecorder* type_recorder, UnwindInfo unw_info)
OpInfo(EffortLevel effort, TypeRecorder* type_recorder, const UnwindInfo& unw_info)
: effort(effort), type_recorder(type_recorder), unw_info(unw_info) {}
TypeRecorder* getTypeRecorder() const { return type_recorder; }
......
......@@ -716,8 +716,7 @@ void CompiledFunction::speculationFailed() {
}
CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle::ExceptionStyle exception_style,
const OSREntryDescriptor* entry_descriptor)
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL),
func(func),
spec(spec),
......@@ -834,7 +833,7 @@ CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs,
}
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, const ParamNames& param_names,
ExceptionStyle::ExceptionStyle exception_style) {
ExceptionStyle exception_style) {
assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(param_names.vararg.str() == "");
assert(param_names.kwarg.str() == "");
......@@ -843,8 +842,7 @@ CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args,
}
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, int num_defaults, bool takes_varargs,
bool takes_kwargs, const ParamNames& param_names,
ExceptionStyle::ExceptionStyle exception_style) {
bool takes_kwargs, const ParamNames& param_names, ExceptionStyle exception_style) {
assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(takes_varargs || param_names.vararg.str() == "");
assert(takes_kwargs || param_names.kwarg.str() == "");
......@@ -855,8 +853,7 @@ CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args,
return cl_f;
}
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
ExceptionStyle::ExceptionStyle exception_style) {
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, ExceptionStyle exception_style) {
std::vector<ConcreteCompilerType*> arg_types(cl_f->numReceivedArgs(), UNKNOWN);
return addRTFunction(cl_f, f, rtn_type, arg_types, exception_style);
}
......@@ -867,8 +864,7 @@ static ConcreteCompilerType* processType(ConcreteCompilerType* type) {
}
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types,
ExceptionStyle::ExceptionStyle exception_style) {
const std::vector<ConcreteCompilerType*>& arg_types, ExceptionStyle exception_style) {
assert(arg_types.size() == cl_f->numReceivedArgs());
#ifndef NDEBUG
for (ConcreteCompilerType* t : arg_types)
......
......@@ -39,6 +39,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm);
// will we always want to generate unique function names? (ie will this function always be reasonable?)
CompiledFunction* cfForMachineFunctionName(const std::string&);
extern "C" void capiExcCaughtInJit(AST_stmt* current_stmt, void* source_info);
extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags);
extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals);
extern "C" Box* compile(Box* source, Box* filename, Box* mode, Box** _args /* flags, dont_inherit */);
......
This diff is collapsed.
......@@ -17,6 +17,7 @@
#include <map>
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Instructions.h"
......@@ -33,6 +34,7 @@ class MDNode;
namespace pyston {
class AST_Invoke;
class CFGBlock;
class GCBuilder;
struct PatchpointInfo;
......@@ -70,6 +72,7 @@ private:
llvm::Value* frame_info_arg;
int scratch_size;
llvm::DenseMap<CFGBlock*, ExceptionStyle> landingpad_styles;
public:
IRGenState(CLFunction* clfunc, CompiledFunction* cf, SourceInfo* source_info, std::unique_ptr<PhiAnalysis> phis,
......@@ -104,6 +107,9 @@ public:
ParamNames* getParamNames() { return param_names; }
void setFrameInfoArgument(llvm::Value* v) { frame_info_arg = v; }
ExceptionStyle getLandingpadStyle(AST_Invoke* invoke);
ExceptionStyle getLandingpadStyle(CFGBlock* block);
};
// turns CFGBlocks into LLVM IR
......
......@@ -195,6 +195,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(createSet);
GET(getattr);
GET(getattr_capi);
GET(setattr);
GET(delattr);
GET(getitem);
......@@ -223,6 +224,8 @@ void initGlobalFuncs(GlobalState& g) {
GET(unpackIntoArray);
GET(raiseAttributeError);
GET(raiseAttributeErrorStr);
GET(raiseAttributeErrorCapi);
GET(raiseAttributeErrorStrCapi);
GET(raiseIndexErrorStr);
GET(raiseNotIterableError);
GET(assertNameDefined);
......@@ -270,6 +273,9 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_);
GET(raise0);
GET(raise3);
GET(PyErr_Fetch);
GET(PyErr_NormalizeException);
GET(capiExcCaughtInJit);
GET(deopt);
GET(div_float_float);
......
......@@ -35,12 +35,13 @@ struct GlobalFuncs {
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxCLFunction, *unboxCLFunction, *boxInstanceMethod,
*boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createUserClass, *createClosure,
*createGenerator, *createSet;
llvm::Value* getattr, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare, *augbinop, *unboxedLen,
*getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom, *importStar, *repr, *str,
*strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
*augbinop, *unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom,
*importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*raiseIndexErrorStr, *assertNameDefined, *assertFail, *assertFailDerefNameDefined;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *assertNameDefined, *assertFail,
*assertFailDerefNameDefined;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN;
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN;
......@@ -50,6 +51,7 @@ struct GlobalFuncs {
llvm::Value* __cxa_end_catch;
llvm::Value* raise0, *raise3;
llvm::Value* PyErr_Fetch, *PyErr_NormalizeException, *capiExcCaughtInJit;
llvm::Value* deopt;
llvm::Value* div_float_float, *floordiv_float_float, *mod_float_float, *pow_float_float;
......
......@@ -603,6 +603,14 @@ static const LineInfo lineInfoForFrame(PythonFrameIteratorImpl* frame_it) {
return LineInfo(current_stmt->lineno, current_stmt->col_offset, source->fn, source->getName());
}
extern "C" void capiExcCaughtInJit(AST_stmt* stmt, void* _source_info) {
SourceInfo* source = static_cast<SourceInfo*>(_source_info);
// TODO: handle reraise (currently on the ExcInfo object)
PyThreadState* tstate = PyThreadState_GET();
BoxedTraceback::here(LineInfo(stmt->lineno, stmt->col_offset, source->fn, source->getName()),
&tstate->curexc_traceback);
}
void exceptionCaughtInInterpreter(LineInfo line_info, ExcInfo* exc_info) {
static StatCounter frames_unwound("num_frames_unwound_python");
frames_unwound.log();
......
......@@ -104,9 +104,6 @@ void Stats::clear() {
}
void Stats::startEstimatingCPUFreq() {
if (!Stats::enabled)
return;
clock_gettime(CLOCK_REALTIME, &Stats::start_ts);
Stats::start_tick = getCPUTicks();
}
......
......@@ -68,32 +68,43 @@ enum class EffortLevel {
MAXIMAL = 3,
};
namespace ExceptionStyle {
enum ExceptionStyle {
CAPI,
CXX,
};
};
template <typename R, typename... Args> struct ExceptionSwitchableFunction {
template <typename T> struct ExceptionSwitchable {
public:
typedef R (*FTy)(Args...);
FTy capi_ptr;
FTy cxx_ptr;
T capi_val;
T cxx_val;
ExceptionSwitchableFunction(FTy capi_ptr, FTy cxx_ptr) : capi_ptr(capi_ptr), cxx_ptr(cxx_ptr) {}
ExceptionSwitchable() : capi_val(), cxx_val() {}
ExceptionSwitchable(T capi_val, T cxx_val) : capi_val(std::move(capi_val)), cxx_val(std::move(cxx_val)) {}
template <ExceptionStyle::ExceptionStyle S> FTy get() {
if (S == ExceptionStyle::CAPI)
return capi_ptr;
template <ExceptionStyle S> T get() {
if (S == CAPI)
return capi_val;
else
return cxx_ptr;
return cxx_val;
}
template <ExceptionStyle::ExceptionStyle S> R call(Args... args) noexcept(S == ExceptionStyle::CAPI) {
return get()(args...);
T get(ExceptionStyle S) {
if (S == CAPI)
return capi_val;
else
return cxx_val;
}
};
template <typename R, typename... Args>
struct ExceptionSwitchableFunction : public ExceptionSwitchable<R (*)(Args...)> {
public:
typedef R (*FTy)(Args...);
ExceptionSwitchableFunction(FTy capi_ptr, FTy cxx_ptr) : ExceptionSwitchable<FTy>(capi_ptr, cxx_ptr) {}
template <ExceptionStyle S> R call(Args... args) noexcept(S == CAPI) { return this->template get<S>()(args...); }
};
class CompilerType;
template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
......@@ -283,7 +294,7 @@ public:
int code_size;
EffortLevel effort;
ExceptionStyle::ExceptionStyle exception_style;
ExceptionStyle exception_style;
int64_t times_called, times_speculation_failed;
ICInvalidator dependent_callsites;
......@@ -293,7 +304,7 @@ public:
std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle::ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ConcreteCompilerType* getReturnType();
......@@ -414,15 +425,12 @@ CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs,
const ParamNames& param_names = ParamNames::empty());
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, int num_defaults, bool takes_varargs,
bool takes_kwargs, const ParamNames& param_names = ParamNames::empty(),
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
ExceptionStyle exception_style = CXX);
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs,
const ParamNames& param_names = ParamNames::empty(),
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
const ParamNames& param_names = ParamNames::empty(), ExceptionStyle exception_style = CXX);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, ExceptionStyle exception_style = CXX);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types,
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
const std::vector<ConcreteCompilerType*>& arg_types, ExceptionStyle exception_style = CXX);
CLFunction* unboxRTFunction(Box*);
// Compiles a new version of the function with the given signature and adds it to the list;
......
......@@ -1382,7 +1382,7 @@ void setupBuiltins() {
builtins_module->giveAttr("repr", repr_obj);
auto len_func = boxRTFunction((void*)len, UNKNOWN, 1);
len_func->internal_callable.cxx_ptr = lenCallInternal;
len_func->internal_callable.cxx_val = lenCallInternal;
len_obj = new BoxedBuiltinFunctionOrMethod(len_func, "len");
builtins_module->giveAttr("len", len_obj);
......
......@@ -786,6 +786,11 @@ void setCAPIException(const ExcInfo& e) {
cur_thread_state.curexc_traceback = e.traceback;
}
void ensureCAPIExceptionSet() {
if (!cur_thread_state.curexc_type)
PyErr_SetString(SystemError, "error return without exception set");
}
void throwCAPIException() {
checkAndThrowCAPIException();
raiseExcHelper(SystemError, "error return without exception set");
......
......@@ -27,9 +27,6 @@
namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
Box* dictRepr(BoxedDict* self) {
std::vector<char> chars;
chars.push_back('{');
......
......@@ -74,6 +74,7 @@ void force() {
FORCE(decodeUTF8StringPtr);
FORCE(getattr);
FORCE(getattr_capi);
FORCE(setattr);
FORCE(delattr);
FORCE(nonzero);
......@@ -101,6 +102,8 @@ void force() {
FORCE(unpackIntoArray);
FORCE(raiseAttributeError);
FORCE(raiseAttributeErrorStr);
FORCE(raiseAttributeErrorCapi);
FORCE(raiseAttributeErrorStrCapi);
FORCE(raiseIndexErrorStr);
FORCE(raiseNotIterableError);
FORCE(assertNameDefined);
......@@ -117,6 +120,9 @@ void force() {
FORCE(raise0);
FORCE(raise3);
FORCE(PyErr_Fetch);
FORCE(PyErr_NormalizeException);
FORCE(capiExcCaughtInJit);
FORCE(deopt);
FORCE(div_i64_i64);
......
......@@ -22,9 +22,6 @@
namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
BoxedListIterator::BoxedListIterator(BoxedList* l, int start) : l(l), pos(start) {
}
......@@ -68,7 +65,7 @@ i1 listiterHasnextUnboxed(Box* s) {
return ans;
}
template <enum ExceptionStyle S> Box* listiterNext(Box* s) noexcept(S == CAPI) {
template <ExceptionStyle S> Box* listiterNext(Box* s) noexcept(S == CAPI) {
assert(s->cls == list_iterator_cls);
BoxedListIterator* self = static_cast<BoxedListIterator*>(s);
......
......@@ -704,7 +704,7 @@ private:
public:
PyCmpComparer(Box* cmp) : cmp(cmp) {}
bool operator()(Box* lhs, Box* rhs) {
Box* r = runtimeCallInternal<ExceptionStyle::CXX>(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL);
Box* r = runtimeCallInternal<CXX>(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL);
if (!isSubclass(r->cls, int_cls))
raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name);
return static_cast<BoxedInt*>(r)->n < 0;
......@@ -1170,8 +1170,8 @@ void setupList() {
list_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1)));
CLFunction* listiter_next = boxRTFunction((void*)listiterNext<ExceptionStyle::CXX>, UNKNOWN, 1);
addRTFunction(listiter_next, (void*)listiterNext<ExceptionStyle::CAPI>, UNKNOWN, ExceptionStyle::CAPI);
CLFunction* listiter_next = boxRTFunction((void*)listiterNext<CXX>, UNKNOWN, 1);
addRTFunction(listiter_next, (void*)listiterNext<CAPI>, UNKNOWN, CAPI);
list_iterator_cls->giveAttr("next", new BoxedFunction(listiter_next));
list_iterator_cls->freeze();
......
......@@ -35,7 +35,7 @@ Box* listIter(Box* self);
Box* listIterIter(Box* self);
Box* listiterHasnext(Box* self);
i1 listiterHasnextUnboxed(Box* self);
template <ExceptionStyle::ExceptionStyle S> Box* listiterNext(Box* self) noexcept(S == ExceptionStyle::CAPI);
template <ExceptionStyle S> Box* listiterNext(Box* self) noexcept(S == CAPI);
Box* listReversed(Box* self);
Box* listreviterHasnext(Box* self);
i1 listreviterHasnextUnboxed(Box* self);
......
This diff is collapsed.
......@@ -55,6 +55,7 @@ extern "C" bool softspace(Box* b, bool newval);
extern "C" void printHelper(Box* dest, Box* var, bool nl);
extern "C" void my_assert(bool b);
extern "C" Box* getattr(Box* obj, BoxedString* attr);
extern "C" Box* getattr_capi(Box* obj, BoxedString* attr) noexcept;
extern "C" Box* getattrMaybeNonstring(Box* obj, Box* attr);
extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val);
extern "C" void setattrMaybeNonstring(Box* obj, Box* attr, Box* attr_val);
......@@ -107,25 +108,22 @@ struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
struct CallRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
template <ExceptionStyle S>
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == ExceptionStyle::CAPI);
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
struct GetitemRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
template <ExceptionStyle S>
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI);
struct LenRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
template <ExceptionStyle S> BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI);
Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
template <ExceptionStyle::ExceptionStyle S>
template <ExceptionStyle S>
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == ExceptionStyle::CAPI);
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
enum LookupScope {
CLASS_ONLY = 1,
......@@ -141,8 +139,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
// This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or
// __getattribute__ methods.
template <ExceptionStyle::ExceptionStyle S>
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
template <ExceptionStyle S>
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI);
// This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for
// data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or
......@@ -156,6 +154,8 @@ Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_
extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef attr) noexcept;
extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept;
extern "C" void raiseNotIterableError(const char* typeName) __attribute__((__noreturn__));
extern "C" void raiseIndexErrorStr(const char* typeName) __attribute__((__noreturn__));
......@@ -168,10 +168,10 @@ Box* typeNew(Box* cls, Box* arg1, Box* arg2, Box** _args);
Box* processDescriptor(Box* obj, Box* inst, Box* owner);
Box* processDescriptorOrNull(Box* obj, Box* inst, Box* owner);
template <ExceptionStyle::ExceptionStyle S>
template <ExceptionStyle S>
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3,
Box** oargs) noexcept(S == ExceptionStyle::CAPI);
Box** oargs) noexcept(S == CAPI);
static const char* objectNewParameterTypeErrorMsg() {
if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) {
......
......@@ -639,7 +639,7 @@ static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args
if (argspec.has_starargs || argspec.num_args == 0) {
// Get callFunc to expand the arguments.
// TODO: update this to use rearrangeArguments instead.
return callFunc<ExceptionStyle::CXX>(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
return callFunc<CXX>(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
}
return typeCallInner(rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
......@@ -997,8 +997,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (new_npassed_args >= 4)
srewrite_args.args = rewrite_args->args;
made = runtimeCallInternal<ExceptionStyle::CXX>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3,
args, keyword_names);
made
= runtimeCallInternal<CXX>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3, args, keyword_names);
if (!srewrite_args.out_success) {
rewrite_args = NULL;
......@@ -1015,8 +1015,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init)
made = objectNewNoArgs(cls);
else
made = runtimeCallInternal<ExceptionStyle::CXX>(new_attr, NULL, new_argspec, cls, arg2, arg3, args,
keyword_names);
made = runtimeCallInternal<CXX>(new_attr, NULL, new_argspec, cls, arg2, arg3, args, keyword_names);
}
assert(made);
......@@ -1066,8 +1065,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
// initrtn = callattrInternal(cls, _init_str, INST_ONLY, &srewrite_args, argspec, made, arg2, arg3, args,
// keyword_names);
initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, &srewrite_args, argspec, made, arg2, arg3,
args, keyword_names);
initrtn
= runtimeCallInternal<CXX>(init_attr, &srewrite_args, argspec, made, arg2, arg3, args, keyword_names);
if (!srewrite_args.out_success) {
rewrite_args = NULL;
......@@ -1086,11 +1085,11 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
// If we weren't passed the args array, it's not safe to index into it
if (passed <= 2)
initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, NULL, init_argspec, arg2, arg3, NULL,
NULL, keyword_names);
initrtn
= runtimeCallInternal<CXX>(init_attr, NULL, init_argspec, arg2, arg3, NULL, NULL, keyword_names);
else
initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, NULL, init_argspec, arg2, arg3, args[0],
&args[1], keyword_names);
initrtn = runtimeCallInternal<CXX>(init_attr, NULL, init_argspec, arg2, arg3, args[0], &args[1],
keyword_names);
}
assertInitNone(initrtn);
} else {
......@@ -1659,7 +1658,7 @@ static Box* instancemethodRepr(Box* b) {
const char* sfuncname = "?", * sklassname = "?";
static BoxedString* name_str = internStringImmortal("__name__");
funcname = getattrInternal<ExceptionStyle::CXX>(func, name_str, NULL);
funcname = getattrInternal<CXX>(func, name_str, NULL);
if (funcname != NULL) {
if (!PyString_Check(funcname)) {
......@@ -1671,7 +1670,7 @@ static Box* instancemethodRepr(Box* b) {
if (klass == NULL) {
klassname = NULL;
} else {
klassname = getattrInternal<ExceptionStyle::CXX>(klass, name_str, NULL);
klassname = getattrInternal<CXX>(klass, name_str, NULL);
if (klassname != NULL) {
if (!PyString_Check(klassname)) {
klassname = NULL;
......@@ -3419,7 +3418,7 @@ void setupRuntime() {
// Punting on that until needed; hopefully by then we will have better Pyston slots support.
auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, true);
typeCallObj->internal_callable.cxx_ptr = &typeCallInternal;
typeCallObj->internal_callable.cxx_val = &typeCallInternal;
type_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeName, typeSetName, NULL));
type_cls->giveAttr("__bases__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeBases, typeSetBases, NULL));
......
......@@ -1000,6 +1000,7 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
void ensureCAPIExceptionSet();
struct ExcInfo;
void setCAPIException(const ExcInfo& e);
......
......@@ -52,3 +52,18 @@ print "******** 2", ''.join(traceback.format_exception(et2, ev2, tb2))
print et1 is et2
print ev1 is ev2
print tb1 is tb2
class C(object):
def __getattr__(self, attr):
raise AttributeError()
def f4():
try:
C().a
except IOError: # unrelated exception
pass
try:
f4()
except AttributeError:
print "******** 3", ''.join(traceback.format_exception(*sys.exc_info()))
......@@ -4,57 +4,5 @@ try:
__pyston__.setOption("REOPT_THRESHOLD_INTERPRETER", 1)
except:
pass
import traceback
import sys
def f():
a, b, c = sys.exc_info()
raise a, b, c
et0, ev0, tb0 = None, None, None
try:
1/0
except:
pass
for i in xrange(10):
try:
f()
except:
et0, ev0, tb0 = sys.exc_info()
print "******** 0", ''.join(traceback.format_exception(et0, ev0, tb0))
et1, ev1, tb1 = None, None, None
et2, ev2, tb2 = None, None, None
def f1():
raise
def f2():
f1()
def f21():
raise Exception()
def f3():
try:
f21()
except:
global et1, tv1, tb1
et1, tv1, tb1 = sys.exc_info()
f2()
try:
f3()
except:
et2, tv2, tb2 = sys.exc_info()
print "******** 1", ''.join(traceback.format_exception(et1, ev1, tb1))
print "******** 2", ''.join(traceback.format_exception(et2, ev2, tb2))
print et1 is et2
print ev1 is ev2
print tb1 is tb2
import incremental_tb
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