Commit fe26d83a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Some random runtime function optimizations

Mostly around trying to avoid calling callattr().
parent 3132de84
......@@ -250,15 +250,35 @@ extern "C" Box* max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
return maxElement;
}
extern "C" Box* next(Box* iterator, Box* _default) {
try {
static BoxedString* next_str = internStringImmortal("next");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = false, .argspec = ArgPassSpec(0) };
return callattr(iterator, next_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
} catch (ExcInfo e) {
if (_default && e.matches(StopIteration))
return _default;
throw e;
extern "C" Box* next(Box* iterator, Box* _default) noexcept {
if (!PyIter_Check(iterator)) {
PyErr_Format(PyExc_TypeError, "%.200s object is not an iterator", iterator->cls->tp_name);
return NULL;
}
Box* rtn;
if (iterator->cls->tp_iternext == slot_tp_iternext) {
rtn = iterator->cls->call_nextIC(iterator);
} else {
rtn = iterator->cls->tp_iternext(iterator);
}
if (rtn != NULL) {
return rtn;
} else if (_default != NULL) {
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_StopIteration))
return NULL;
PyErr_Clear();
}
Py_INCREF(_default);
return _default;
} else if (PyErr_Occurred()) {
return NULL;
} else {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
}
......@@ -1248,6 +1268,11 @@ Box* print(BoxedTuple* args, BoxedDict* kwargs) {
Box* getreversed(Box* o) {
static BoxedString* reversed_str = internStringImmortal("__reversed__");
// common case:
if (o->cls == list_cls) {
return listReversed(o);
}
// TODO add rewriting to this? probably want to try to avoid this path though
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(o, reversed_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
......@@ -1514,8 +1539,9 @@ void setupBuiltins() {
max_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)max, UNKNOWN, 1, 1, true, true), "max", { None });
builtins_module->giveAttr("max", max_obj);
builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)next, UNKNOWN, 2, 1, false, false), "next", { NULL }));
builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)next, UNKNOWN, 2, 1, false,
false, ParamNames::empty(), CAPI),
"next", { NULL }));
builtins_module->giveAttr("sum", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)sum, UNKNOWN, 2, 1, false, false), "sum", { boxInt(0) }));
......
......@@ -20,6 +20,7 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/ics.h"
#include "runtime/inline/list.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -238,11 +239,24 @@ template <enum ExceptionStyle S> Box* dictGetitem(BoxedDict* self, Box* k) noexc
if (it == self->d.end()) {
// Try calling __missing__ if this is a subclass
if (self->cls != dict_cls) {
// Special-case defaultdict, assuming that it's the main time we will actually hit this.
// We could just use a single runtime IC here, or have a small cache that maps type->runtimeic.
// Or use a polymorphic runtime ic.
static BoxedClass* defaultdict_cls = NULL;
static CallattrIC defaultdict_ic;
if (defaultdict_cls == NULL && strcmp(self->cls->tp_name, "collections.defaultdict") == 0) {
defaultdict_cls = self->cls;
}
static BoxedString* missing_str = internStringImmortal("__missing__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(1) };
Box* r;
try {
r = callattr(self, missing_str, callattr_flags, k, NULL, NULL, NULL, NULL);
if (self->cls == defaultdict_cls) {
r = defaultdict_ic.call(self, missing_str, callattr_flags, k, NULL, NULL, NULL, NULL);
} else {
r = callattr(self, missing_str, callattr_flags, k, NULL, NULL, NULL, NULL);
}
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
......@@ -603,9 +617,14 @@ void dictMerge(BoxedDict* self, Box* other) {
return;
}
static BoxedString* keys_str = internStringImmortal("keys");
CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* keys = callattr(other, keys_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
Box* keys;
if (other->cls == attrwrapper_cls) {
keys = attrwrapperKeys(other);
} else {
static BoxedString* keys_str = internStringImmortal("keys");
CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
keys = callattr(other, keys_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
}
assert(keys);
for (Box* k : keys->pyElements()) {
......
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