void raise3(Box* arg0, Box* arg1, Box* arg2) { // TODO switch this to PyErr_Normalize if (arg2 == None) arg2 = getTraceback(); if (isSubclass(arg0->cls, type_cls)) { BoxedClass* c = static_cast<BoxedClass*>(arg0); if (isSubclass(c, BaseException)) { Box* exc_obj; if (isSubclass(arg1->cls, BaseException)) { exc_obj = arg1; c = exc_obj->cls; } else if (arg1 != None) { exc_obj = runtimeCall(c, ArgPassSpec(1), arg1, NULL, NULL, NULL, NULL); } else { exc_obj = runtimeCall(c, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); } raiseRaw(ExcInfo(c, exc_obj, arg2)); } } if (isSubclass(arg0->cls, BaseException)) { if (arg1 != None) raiseExcHelper(TypeError, "instance exception may not have a separate value"); raiseRaw(ExcInfo(arg0->cls, arg0, arg2)); } raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s", getTypeName(arg0)); }
extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) { try { return runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL); } catch (Box* b) { Py_FatalError("unimplemented"); } }
static Box* property_copy(BoxedProperty* old, Box* get, Box* set, Box* del) { RELEASE_ASSERT(isSubclass(old->cls, property_cls), ""); if (!get || get == Py_None) get = old->prop_get; if (!set || set == Py_None) set = old->prop_set; if (!del || del == Py_None) del = old->prop_del; // Optimization for the case when the old propery is not subclassed if (old->cls == property_cls) { BoxedProperty* prop = new BoxedProperty(get, set, del, old->prop_doc); prop->getter_doc = false; if ((old->getter_doc && get != Py_None) || !old->prop_doc) propertyDocCopy(prop, get); return prop; } else { if (!get) get = Py_None; if (!set) set = Py_None; if (!del) del = Py_None; Box* doc; if ((old->getter_doc && get != Py_None) || !old->prop_doc) doc = Py_None; else doc = old->prop_doc; return runtimeCall(old->cls, ArgPassSpec(4), get, set, del, &doc, NULL); } }
Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, TypeRecorder* type_recorder, 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); }
// Have a special helper function for syntax errors, since we want to include the location // of the syntax error in the traceback, even though it is not part of the execution: void raiseSyntaxError(const char* msg, int lineno, int col_offset, llvm::StringRef file, llvm::StringRef func) { Box* exc = runtimeCall(SyntaxError, ArgPassSpec(1), boxString(msg), NULL, NULL, NULL, NULL); auto tb = new BoxedTraceback(LineInfo(lineno, col_offset, boxString(file), boxString(func)), None); assert(!PyErr_Occurred()); throw ExcInfo(exc->cls, exc, tb); }
// Have a special helper function for syntax errors, since we want to include the location // of the syntax error in the traceback, even though it is not part of the execution: void raiseSyntaxError(const char* msg, int lineno, int col_offset, const std::string& file, const std::string& func) { Box* exc = runtimeCall(SyntaxError, ArgPassSpec(1), boxStrConstant(msg), NULL, NULL, NULL, NULL); auto tb = getTraceback(); std::vector<const LineInfo*> entries = tb->lines; entries.push_back(new LineInfo(lineno, col_offset, file, func)); raiseRaw(ExcInfo(exc->cls, exc, new BoxedTraceback(std::move(entries)))); }
extern "C" PyObject* PyFrozenSet_New(PyObject* iterable) noexcept { try { return runtimeCall(frozenset_cls, ArgPassSpec(iterable ? 1 : 0), iterable, NULL, NULL, NULL, NULL); } catch (ExcInfo e) { setCAPIException(e); return NULL; } }
static Box* sysExit(Box* arg) { assert(arg); Box* exc = runtimeCall(SystemExit, ArgPassSpec(1), arg, NULL, NULL, NULL, NULL); // TODO this should be handled by the SystemExit constructor exc->giveAttr("code", arg); raiseExc(exc); }
extern "C" PyObject* PySet_New(PyObject* iterable) noexcept { if (!iterable) return new BoxedSet(); // Fast path for empty set. try { return runtimeCall(set_cls, ArgPassSpec(iterable ? 1 : 0), iterable, NULL, NULL, NULL, NULL); } catch (ExcInfo e) { setCAPIException(e); return NULL; } }
static void* thread_start(Box* target, Box* varargs, Box* kwargs) { assert(target); assert(varargs); try { runtimeCall(target, ArgPassSpec(0, 0, true, kwargs != NULL), varargs, kwargs, NULL, NULL, NULL); } catch (Box* b) { std::string msg = formatException(b); printLastTraceback(); fprintf(stderr, "%s\n", msg.c_str()); } return NULL; }
static Box* propertySet(Box* self, Box* obj, Box* val) { RELEASE_ASSERT(isSubclass(self->cls, property_cls), ""); BoxedProperty* prop = static_cast<BoxedProperty*>(self); Box* func; if (val == NULL) { func = prop->prop_del; } else { func = prop->prop_set; } if (func == NULL) { raiseExcHelper(AttributeError, val == NULL ? "can't delete attribute" : "can't set attribute"); } if (val == NULL) { autoDecref(runtimeCall(func, ArgPassSpec(1), obj, NULL, NULL, NULL, NULL)); } else { autoDecref(runtimeCall(func, ArgPassSpec(2), obj, val, NULL, NULL, NULL)); } return incref(Py_None); }
static Box* propertyGet(Box* self, Box* obj, Box* type) { RELEASE_ASSERT(isSubclass(self->cls, property_cls), ""); BoxedProperty* prop = static_cast<BoxedProperty*>(self); if (obj == NULL || obj == Py_None) { return incref(self); } if (prop->prop_get == NULL) { raiseExcHelper(AttributeError, "unreadable attribute"); } return runtimeCall(prop->prop_get, ArgPassSpec(1), obj, NULL, NULL, NULL, NULL); }
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) { if (msg != NULL) { va_list ap; va_start(ap, msg); // printf("Raising: "); // vprintf(msg, ap); // printf("\n"); // va_start(ap, msg); char buf[1024]; vsnprintf(buf, sizeof(buf), msg, ap); va_end(ap); BoxedString* message = boxStrConstant(buf); Box* exc_obj = runtimeCall(cls, ArgPassSpec(1), message, NULL, NULL, NULL, NULL); raiseExc(exc_obj); } else { Box* exc_obj = runtimeCall(cls, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); raiseExc(exc_obj); } }
extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) { RELEASE_ASSERT(args, ""); // actually it looks like this is allowed to be NULL RELEASE_ASSERT(args->cls == tuple_cls, ""); // TODO do something like this? not sure if this is safe; will people expect that calling into a known function // won't end up doing a GIL check? // threading::GLDemoteRegion _gil_demote; try { Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL); return r; } catch (Box* b) { Py_FatalError("unimplemented"); } }
void runCollection() { static StatCounter sc("gc_collections"); sc.log(); ncollections++; if (VERBOSITY("gc") >= 2) printf("Collection #%d\n", ncollections); Timer _t("collecting", /*min_usec=*/10000); markPhase(); std::list<Box*, StlCompatAllocator<Box*>> weakly_referenced; sweepPhase(weakly_referenced); for (auto o : weakly_referenced) { PyWeakReference** list = (PyWeakReference**)PyObject_GET_WEAKREFS_LISTPTR(o); while (PyWeakReference* head = *list) { assert(isValidGCObject(head)); if (head->wr_object != Py_None) { _PyWeakref_ClearRef(head); if (head->wr_callback) { runtimeCall(head->wr_callback, ArgPassSpec(1), reinterpret_cast<Box*>(head), NULL, NULL, NULL, NULL); head->wr_callback = NULL; } } } } if (VERBOSITY("gc") >= 2) printf("Collection #%d done\n\n", ncollections); long us = _t.end(); static StatCounter sc_us("gc_collections_us"); sc_us.log(us); // dumpHeapStatistics(); }
static void* thread_start(Box* target, Box* varargs, Box* kwargs) { assert(target); assert(varargs); #if STAT_TIMERS // TODO: maybe we should just not log anything for threads... static uint64_t* timer_counter = Stats::getStatCounter("us_timer_thread_start"); StatTimer timer(timer_counter, 0, true); timer.pushTopLevel(getCPUTicks()); #endif try { runtimeCall(target, ArgPassSpec(0, 0, true, kwargs != NULL), varargs, kwargs, NULL, NULL, NULL); } catch (ExcInfo e) { e.printExcAndTraceback(); } #if STAT_TIMERS timer.popTopLevel(getCPUTicks()); #endif return NULL; }
static Box* sysExit(Box* arg) { assert(arg); Box* exc = runtimeCall(SystemExit, ArgPassSpec(1), arg, NULL, NULL, NULL, NULL); raiseExc(exc); }
void raiseExcHelper(BoxedClass* cls, Box* arg) { Box* exc_obj = runtimeCall(cls, ArgPassSpec(1), arg, NULL, NULL, NULL, NULL); raiseExc(exc_obj); }