Commit 7974eb8c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #1209 from kmod/cpython_descr2

Switch to CPython's descrobject.c
parents c9cab0e0 a11ffa73
......@@ -856,7 +856,7 @@ nosearch_check_%: %.py pyston_dbg check-deps
$(call make_search,check_%)
nosearch_dbgpy_% nosearch_pydbg_%: %.py ext_pythondbg
export PYTHON_VERSION=$$(python2.7-dbg -V 2>&1 | awk '{print $$2}'); PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7-pydebug $(GDB) --ex "dir $(DEPS_DIR)/python-src/python2.7-$$PYTHON_VERSION/debian" $(GDB_CMDS) --args python2.7-dbg $<
export PYTHON_VERSION=$$(python2.7-dbg -V 2>&1 | awk '{print $$2}'); PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7-pydebug $(GDB) --ex "dir $(DEPS_DIR)/python-src/python2.7-$$PYTHON_VERSION/debian" $(GDB_CMDS) --args python2.7-dbg $(ARGS) $<
$(call make_search,dbgpy_%)
$(call make_search,pydbg_%)
......
......@@ -86,8 +86,8 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
capsule.c
cobject.c
complexobject.c
descrobject.c
dictobject.c
dictproxy.c
errors.c
exceptions.c
floatobject.c
......
......@@ -24,14 +24,16 @@ typedef PyObject *(*wrapperfunc)(PyObject *self, PyObject *args,
typedef PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args,
void *wrapped, PyObject *kwds);
// Pyston addition: faster CC
typedef PyObject *(*wrapperfunc_1arg)(PyObject *self, void *wrapped);
typedef PyObject *(*wrapperfunc_2arg)(PyObject *self, PyObject* arg, void *wrapped);
struct wrapperbase {
char *name;
const char *name;
int offset;
void *function;
wrapperfunc wrapper;
char *doc;
const char *doc;
int flags;
PyObject *name_strobj;
};
......@@ -45,8 +47,6 @@ struct wrapperbase {
/* Various kinds of descriptor objects */
// Pyston change: these are not our object layouts
#if 0
#define PyDescr_COMMON \
PyObject_HEAD \
PyTypeObject *d_type; \
......@@ -76,21 +76,11 @@ typedef struct {
struct wrapperbase *d_base;
void *d_wrapped; /* This can be any function pointer */
} PyWrapperDescrObject;
#endif
// (Pyston TODO: add opaque definitions of those names)
// Pyston change: these are not static objects any more
#if 0
PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type;
PyAPI_DATA(PyTypeObject) PyDictProxy_Type;
PyAPI_DATA(PyTypeObject) PyGetSetDescr_Type;
PyAPI_DATA(PyTypeObject) PyMemberDescr_Type;
#else
PyAPI_DATA(PyTypeObject) PyDictProxy_Type;
#endif
// (Pyston TODO: add #defines to our names)
PyAPI_DATA(PyTypeObject*) wrapperdescr_cls;
#define PyWrapperDescr_Type (*wrapperdescr_cls)
PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyDescr_NewClassMethod(PyTypeObject *, PyMethodDef *) PYSTON_NOEXCEPT;
......@@ -106,8 +96,17 @@ PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *) PYSTON_NOEXCEPT;
// Pyston change: this is no longer a static object
//PyAPI_DATA(PyTypeObject) PyProperty_Type;
PyAPI_DATA(PyTypeObject) PyProperty_Type;
// Pyston change: exposed these
typedef struct {
PyObject_HEAD
PyWrapperDescrObject *descr;
PyObject *self;
} wrapperobject;
PyAPI_DATA(PyTypeObject) wrappertype;
PyAPI_DATA(PyTypeObject) PyMethodDescr_Type;
PyAPI_DATA(PyTypeObject) PyClassMethodDescr_Type;
#ifdef __cplusplus
}
......
......@@ -37,7 +37,7 @@ struct memberlist {
typedef struct PyMemberDef {
/* Current version, use this */
char *name;
const char *name;
int type;
Py_ssize_t offset;
int flags;
......
This diff is collapsed.
// This file is originally from CPython 2.7, with modifications for Pyston
// The code is normally part of descrobject.c
#include "Python.h"
/* --- Readonly proxy for dictionaries (actually any mapping) --- */
/* This has no reason to be in this file except that adding new files is a
bit of a pain */
typedef struct {
PyObject_HEAD
PyObject *dict;
} proxyobject;
static Py_ssize_t
proxy_len(proxyobject *pp)
{
return PyObject_Size(pp->dict);
}
static PyObject *
proxy_getitem(proxyobject *pp, PyObject *key)
{
return PyObject_GetItem(pp->dict, key);
}
static PyMappingMethods proxy_as_mapping = {
(lenfunc)proxy_len, /* mp_length */
(binaryfunc)proxy_getitem, /* mp_subscript */
0, /* mp_ass_subscript */
};
static int
proxy_contains(proxyobject *pp, PyObject *key)
{
return PyDict_Contains(pp->dict, key);
}
static PySequenceMethods proxy_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)proxy_contains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
static PyObject *
proxy_has_key(proxyobject *pp, PyObject *key)
{
int res = PyDict_Contains(pp->dict, key);
if (res < 0)
return NULL;
return PyBool_FromLong(res);
}
static PyObject *
proxy_get(proxyobject *pp, PyObject *args)
{
PyObject *key, *def = Py_None;
if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
return NULL;
return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);
}
static PyObject *
proxy_keys(proxyobject *pp)
{
return PyMapping_Keys(pp->dict);
}
static PyObject *
proxy_values(proxyobject *pp)
{
return PyMapping_Values(pp->dict);
}
static PyObject *
proxy_items(proxyobject *pp)
{
return PyMapping_Items(pp->dict);
}
static PyObject *
proxy_iterkeys(proxyobject *pp)
{
return PyObject_CallMethod(pp->dict, "iterkeys", NULL);
}
static PyObject *
proxy_itervalues(proxyobject *pp)
{
return PyObject_CallMethod(pp->dict, "itervalues", NULL);
}
static PyObject *
proxy_iteritems(proxyobject *pp)
{
return PyObject_CallMethod(pp->dict, "iteritems", NULL);
}
static PyObject *
proxy_copy(proxyobject *pp)
{
return PyObject_CallMethod(pp->dict, "copy", NULL);
}
static PyMethodDef proxy_methods[] = {
{"has_key", (PyCFunction)proxy_has_key, METH_O,
PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")},
{"get", (PyCFunction)proxy_get, METH_VARARGS,
PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d."
" d defaults to None.")},
{"keys", (PyCFunction)proxy_keys, METH_NOARGS,
PyDoc_STR("D.keys() -> list of D's keys")},
{"values", (PyCFunction)proxy_values, METH_NOARGS,
PyDoc_STR("D.values() -> list of D's values")},
{"items", (PyCFunction)proxy_items, METH_NOARGS,
PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
{"iterkeys", (PyCFunction)proxy_iterkeys, METH_NOARGS,
PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")},
{"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS,
PyDoc_STR("D.itervalues() -> an iterator over the values of D")},
{"iteritems", (PyCFunction)proxy_iteritems, METH_NOARGS,
PyDoc_STR("D.iteritems() ->"
" an iterator over the (key, value) items of D")},
{"copy", (PyCFunction)proxy_copy, METH_NOARGS,
PyDoc_STR("D.copy() -> a shallow copy of D")},
{0}
};
static void
proxy_dealloc(proxyobject *pp)
{
_PyObject_GC_UNTRACK(pp);
Py_DECREF(pp->dict);
PyObject_GC_Del(pp);
}
static PyObject *
proxy_getiter(proxyobject *pp)
{
return PyObject_GetIter(pp->dict);
}
static PyObject *
proxy_str(proxyobject *pp)
{
return PyObject_Str(pp->dict);
}
static PyObject *
proxy_repr(proxyobject *pp)
{
PyObject *dictrepr;
PyObject *result;
dictrepr = PyObject_Repr(pp->dict);
if (dictrepr == NULL)
return NULL;
result = PyString_FromFormat("dict_proxy(%s)", PyString_AS_STRING(dictrepr));
Py_DECREF(dictrepr);
return result;
}
static int
proxy_traverse(PyObject *self, visitproc visit, void *arg)
{
proxyobject *pp = (proxyobject *)self;
Py_VISIT(pp->dict);
return 0;
}
static int
proxy_compare(proxyobject *v, PyObject *w)
{
return PyObject_Compare(v->dict, w);
}
static PyObject *
proxy_richcompare(proxyobject *v, PyObject *w, int op)
{
return PyObject_RichCompare(v->dict, w, op);
}
PyTypeObject PyDictProxy_Type = {
// Pyston change:
// PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyVarObject_HEAD_INIT(NULL, 0)
"dictproxy", /* tp_name */
sizeof(proxyobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)proxy_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)proxy_compare, /* tp_compare */
(reprfunc)proxy_repr, /* tp_repr */
0, /* tp_as_number */
&proxy_as_sequence, /* tp_as_sequence */
&proxy_as_mapping, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
(reprfunc)proxy_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
proxy_traverse, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)proxy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)proxy_getiter, /* tp_iter */
0, /* tp_iternext */
proxy_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
};
PyObject *
PyDictProxy_New(PyObject *dict)
{
proxyobject *pp;
pp = PyObject_GC_New(proxyobject, &PyDictProxy_Type);
if (pp != NULL) {
Py_INCREF(dict);
pp->dict = dict;
_PyObject_GC_TRACK(pp);
}
return (PyObject *)pp;
}
......@@ -262,7 +262,7 @@ structseq_repr(PyStructSequence *obj)
for (i=0; i < VISIBLE_SIZE(obj); i++) {
PyObject *val, *repr;
char *cname, *crepr;
/* Pyston change: made const */ const char *cname, *crepr;
cname = typ->tp_members[i].name;
......@@ -399,7 +399,7 @@ structseq_reduce(PyStructSequence* self)
}
for (; i < n_fields; i++) {
char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
/* Pyston change: made const */ const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
PyDict_SetItemString(dict, n,
self->ob_item[i]);
}
......
......@@ -35,18 +35,39 @@ using namespace pyston::assembler;
#define MAX_RETRY_BACKOFF 1024
// TODO not right place for this...
int64_t ICInvalidator::version() {
return cur_version;
}
ICInvalidator::~ICInvalidator() {
for (ICSlotInfo* slot : dependents) {
slot->invalidators.erase(std::find(slot->invalidators.begin(), slot->invalidators.end(), this));
}
}
void ICInvalidator::addDependent(ICSlotInfo* entry_info) {
dependents.insert(entry_info);
auto p = dependents.insert(entry_info);
bool was_inserted = p.second;
if (was_inserted)
entry_info->invalidators.push_back(this);
}
void ICInvalidator::invalidateAll() {
cur_version++;
for (ICSlotInfo* slot : dependents) {
bool found_self = false;
for (auto invalidator : slot->invalidators) {
if (invalidator == this) {
assert(!found_self);
found_self = true;
} else {
assert(invalidator->dependents.count(slot));
invalidator->dependents.erase(slot);
}
}
assert(found_self);
slot->invalidators.clear();
slot->clear();
}
dependents.clear();
......@@ -98,6 +119,8 @@ void ICSlotRewrite::commit(CommitHook* hook, std::vector<void*> gc_references,
if (!still_valid) {
if (VERBOSITY() >= 3)
printf("not committing %s icentry since a dependency got updated before commit\n", debug_name);
for (auto p : gc_references)
Py_DECREF(p);
return;
}
......@@ -106,8 +129,11 @@ void ICSlotRewrite::commit(CommitHook* hook, std::vector<void*> gc_references,
bool do_commit = hook->finishAssembly(continue_point - slot_start);
if (!do_commit)
if (!do_commit) {
for (auto p : gc_references)
Py_DECREF(p);
return;
}
assert(!assembler.hasFailed());
......@@ -204,25 +230,8 @@ ICSlotInfo* ICInfo::pickEntryForRewrite(const char* debug_name) {
return NULL;
}
// Keep track of all ICInfo(s) that we create because they contain pointers to Pyston heap objects
// that we have written into the generated code and we may need to scan those.
static llvm::DenseSet<ICInfo*> ics_list;
static llvm::DenseMap<void*, ICInfo*> ics_by_return_addr;
void registerGCTrackedICInfo(ICInfo* ic) {
#if MOVING_GC
assert(ics_list.count(ic) == 0);
ics_list.insert(ic);
#endif
}
void deregisterGCTrackedICInfo(ICInfo* ic) {
#if MOVING_GC
assert(ics_list.count(ic) == 1);
ics_list.erase(ic);
#endif
}
ICInfo::ICInfo(void* start_addr, void* slowpath_rtn_addr, void* continue_addr, StackInfo stack_info, int num_slots,
int slot_size, llvm::CallingConv::ID calling_conv, LiveOutSet _live_outs,
assembler::GenericRegister return_register, TypeRecorder* type_recorder,
......@@ -248,16 +257,15 @@ ICInfo::ICInfo(void* start_addr, void* slowpath_rtn_addr, void* continue_addr, S
}
if (slowpath_rtn_addr && !this->ic_global_decref_locations.empty())
slowpath_decref_info = DecrefInfo((uint64_t)slowpath_rtn_addr, this->ic_global_decref_locations);
#if MOVING_GC
assert(ics_list.count(this) == 0);
#endif
}
ICInfo::~ICInfo() {
#if MOVING_GC
assert(ics_list.count(this) == 0);
#endif
for (auto& slot : slots) {
for (auto invalidator : slot.invalidators) {
assert(invalidator->dependents.count(&slot));
invalidator->dependents.erase(&slot);
}
}
}
DecrefInfo::DecrefInfo(uint64_t ip, std::vector<Location> locations) : ip(ip) {
......@@ -323,7 +331,9 @@ std::unique_ptr<ICInfo> registerCompiledPatchpoint(uint8_t* start_addr, uint8_t*
}
void deregisterCompiledPatchpoint(ICInfo* ic) {
assert(ics_by_return_addr.count(ic->slowpath_rtn_addr));
ic->clearAll();
assert(ics_by_return_addr[ic->slowpath_rtn_addr] == ic);
ics_by_return_addr.erase(ic->slowpath_rtn_addr);
deregisterGCTrackedICInfo(ic);
......@@ -403,7 +413,7 @@ void ICInfo::appendDecrefInfosTo(std::vector<DecrefInfo>& dest_decref_infos) {
}
void clearAllICs() {
for (auto&& p : ics_by_ast_node) {
for (auto&& p : ics_by_return_addr) {
p.second->clearAll();
}
}
......
......@@ -63,6 +63,7 @@ public:
std::vector<void*> gc_references;
std::vector<DecrefInfo> decref_infos;
std::vector<ICInvalidator*> invalidators; // ICInvalidators that reference this slotinfo
void clear();
};
......@@ -183,8 +184,10 @@ public:
void appendDecrefInfosTo(std::vector<DecrefInfo>& dest_decref_infos);
};
void registerGCTrackedICInfo(ICInfo* ic);
void deregisterGCTrackedICInfo(ICInfo* ic);
inline void registerGCTrackedICInfo(ICInfo* ic) {
}
inline void deregisterGCTrackedICInfo(ICInfo* ic) {
}
class ICSetupInfo;
struct CompiledFunction;
......
......@@ -432,14 +432,15 @@ void Rewriter::_getAttr(RewriterVar* result, RewriterVar* ptr, int offset, Locat
// mov ($0x133), %rdi
assembler::Register ptr_reg = ptr->getInReg(Location::any(), /* allow_constant_in_reg */ true);
// It's okay to bump the use now, since it's fine to allocate the result
// in the same register as ptr
ptr->bumpUse();
ptr->bumpUseEarlyIfPossible();
assembler::Register newvar_reg = result->initializeInReg(dest);
assembler->mov_generic(assembler::Indirect(ptr_reg, offset), newvar_reg, type);
result->releaseIfNoUses();
ptr->bumpUseLateIfNecessary();
assertConsistent();
}
......@@ -457,11 +458,12 @@ void Rewriter::_getAttrDouble(RewriterVar* result, RewriterVar* ptr, int offset,
assembler::Register ptr_reg = ptr->getInReg();
ptr->bumpUse();
ptr->bumpUseEarlyIfPossible();
assembler::XMMRegister newvar_reg = result->initializeInXMMReg(dest);
assembler->movsd(assembler::Indirect(ptr_reg, offset), newvar_reg);
ptr->bumpUseLateIfNecessary();
result->releaseIfNoUses();
assertConsistent();
}
......@@ -480,7 +482,7 @@ void Rewriter::_getAttrFloat(RewriterVar* result, RewriterVar* ptr, int offset,
assembler::Register ptr_reg = ptr->getInReg();
ptr->bumpUse();
ptr->bumpUseEarlyIfPossible();
assembler::XMMRegister newvar_reg = result->initializeInXMMReg(dest);
assembler->movss(assembler::Indirect(ptr_reg, offset), newvar_reg);
......@@ -488,6 +490,7 @@ void Rewriter::_getAttrFloat(RewriterVar* result, RewriterVar* ptr, int offset,
// cast to double
assembler->cvtss2sd(newvar_reg, newvar_reg);
ptr->bumpUseLateIfNecessary();
result->releaseIfNoUses();
assertConsistent();
}
......@@ -633,8 +636,8 @@ void Rewriter::_cmp(RewriterVar* result, RewriterVar* v1, AST_TYPE::AST_TYPE cmp
assembler::Register v2_reg = v2->getInReg();
assert(v1_reg != v2_reg); // TODO how do we ensure this?
v1->bumpUse();
v2->bumpUse();
v1->bumpUseEarlyIfPossible();
v2->bumpUseEarlyIfPossible();
assembler::Register newvar_reg = allocReg(dest);
result->initializeInReg(newvar_reg);
......@@ -650,6 +653,9 @@ void Rewriter::_cmp(RewriterVar* result, RewriterVar* v1, AST_TYPE::AST_TYPE cmp
RELEASE_ASSERT(0, "%d", cmp_type);
}
v1->bumpUseLateIfNecessary();
v2->bumpUseLateIfNecessary();
result->releaseIfNoUses();
assertConsistent();
}
......@@ -668,7 +674,7 @@ void Rewriter::_toBool(RewriterVar* result, RewriterVar* var, Location dest) {
assembler::Register this_reg = var->getInReg();
var->bumpUse();
var->bumpUseEarlyIfPossible();
assembler::Register result_reg = allocReg(dest);
result->initializeInReg(result_reg);
......@@ -676,6 +682,7 @@ void Rewriter::_toBool(RewriterVar* result, RewriterVar* var, Location dest) {
assembler->test(this_reg, this_reg);
assembler->setnz(result_reg);
var->bumpUseLateIfNecessary();
result->releaseIfNoUses();
assertConsistent();
}
......
......@@ -227,6 +227,24 @@ private:
llvm::SmallVector<int, 32> uses;
int next_use;
void bumpUse();
// Helper functions for a common optimization.
// We want to be able to call bumpUse() as soon as the register is able to be used.
// But if we have an owned ref in that variable, we need to hold on to it until
// the end of the operation, even though its register is theoretically available to use.
// So before we would just call bumpUse() early. Now we can do
// bumpUseEarlyIfPossible();
// /* some code */
// bumpUseLateIfNecessary();
void bumpUseEarlyIfPossible() {
if (reftype != RefType::OWNED)
bumpUse();
}
void bumpUseLateIfNecessary() {
if (reftype == RefType::OWNED)
bumpUse();
}
// Call this on the result at the end of the action in which it's created
// TODO we should have a better way of dealing with variables that have 0 uses
void releaseIfNoUses();
......
This diff is collapsed.
......@@ -59,6 +59,11 @@ class GetattrRewriteArgs;
template <ExceptionStyle S, Rewritable rewritable>
Box* slotTpGetattrHookInternal(Box* self, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool for_call,
BORROWED(Box**) bind_obj_out, RewriterVar** r_bind_obj_out) noexcept(S == CAPI);
// Set a class's tp_call to this to have calls to tp_call (and __call__) proxy to tpp_call
Box* proxyToTppCall(Box* self, Box* args, Box* kw) noexcept;
int add_methods(PyTypeObject* type, PyMethodDef* meth) noexcept;
}
#endif
......@@ -54,7 +54,7 @@ public:
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
static Box* getname(Box* b, void*) {
static Box* getname(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == capifunc_cls, "");
const char* s = static_cast<BoxedCApiFunction*>(b)->method_def->ml_name;
if (s)
......@@ -62,7 +62,7 @@ public:
return incref(None);
}
static Box* doc(Box* b, void*) {
static Box* doc(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == capifunc_cls, "");
const char* s = static_cast<BoxedCApiFunction*>(b)->method_def->ml_doc;
if (s)
......
......@@ -112,7 +112,7 @@ BORROWED(BoxedString*) SourceInfo::getFn() {
return fn;
}
BORROWED(BoxedString*) SourceInfo::getName() {
BORROWED(BoxedString*) SourceInfo::getName() noexcept {
assert(ast);
static BoxedString* lambda_name = getStaticString("<lambda>");
......
......@@ -923,9 +923,16 @@ private:
// trigger an exception, but the irgenerator will know that definitely-defined
// local symbols will not throw.
emitter.getBuilder()->CreateUnreachable();
// Hacky: create a new BB for any more code that we might generate
llvm::BasicBlock* continue_bb
= llvm::BasicBlock::Create(g.context, "cant_reach", irstate->getLLVMFunction());
emitter.setCurrentBasicBlock(continue_bb);
exc_type = exc_value = exc_tb = undefVariable();
// TODO: should we not emit the rest of the block? I (kmod) think I tried that and
// ran into some sort of issue, but I don't remember what it was.
// TODO: we should just call endBlock instead. It looks like the implementation
// of that has some issues though, and it might end up generating code as well. ANd
// then I'm not sure that the higher-level irgen.cpp would handle that well.
// endBlock(DEAD);
}
......
......@@ -289,10 +289,14 @@ private:
public:
ICInvalidator() : cur_version(0) {}
~ICInvalidator();
void addDependent(ICSlotInfo* icentry);
int64_t version();
void invalidateAll();
friend class ICInfo;
friend class ICSlotInfo;
};
// Codegen types:
......@@ -416,7 +420,8 @@ public:
// body and we have to create one. Ideally, we'd be able to avoid the space duplication for non-lambdas.
const std::vector<AST_stmt*> body;
BORROWED(BoxedString*) getName();
// does not throw CXX or CAPI exceptions:
BORROWED(BoxedString*) getName() noexcept;
BORROWED(BoxedString*) getFn();
InternedString mangleName(InternedString id);
......@@ -867,8 +872,8 @@ public:
void clearAttrsForDealloc();
void giveAttrDescriptor(const char* attr, Box* (*get)(Box*, void*), void (*set)(Box*, Box*, void*));
void giveCapiAttrDescriptor(const char* attr, Box* (*get)(Box*, void*), int (*set)(Box*, Box*, void*));
void giveAttrDescriptor(const char* attr, Box* (*get)(Box*, void*), int (*set)(Box*, Box*, void*));
void giveAttrMember(const char* attr, int type, ssize_t offset, bool readonly = true);
// getattr() does the equivalent of PyDict_GetItem(obj->dict, attr): it looks up the attribute's value on the
// object's attribute storage. it doesn't look at other objects or do any descriptor logic.
......
......@@ -816,9 +816,7 @@ void setupSys() {
sys_flags_cls->giveAttr(
"__new__", new BoxedFunction(FunctionMetadata::create((void*)BoxedSysFlags::__new__, UNKNOWN, 1, true, true)));
sys_flags_cls->tp_dealloc = (destructor)BoxedSysFlags::dealloc;
#define ADD(name) \
sys_flags_cls->giveAttr(STRINGIFY(name), \
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSysFlags, name)))
#define ADD(name) sys_flags_cls->giveAttrMember(STRINGIFY(name), T_OBJECT, offsetof(BoxedSysFlags, name));
ADD(division_warning);
ADD(bytes_warning);
ADD(no_user_site);
......
......@@ -47,8 +47,6 @@
namespace pyston {
BoxedClass* method_cls;
extern "C" int _PyIndex_Check(PyObject* obj) noexcept {
return (Py_TYPE(obj)->tp_as_number != NULL && PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_HAVE_INDEX)
&& Py_TYPE(obj)->tp_as_number->nb_index != NULL);
......@@ -1565,8 +1563,6 @@ extern "C" PyObject* Py_FindMethod(PyMethodDef* methods, PyObject* self, const c
}
extern "C" PyObject* PyCFunction_NewEx(PyMethodDef* ml, PyObject* self, PyObject* module) noexcept {
assert((ml->ml_flags & (~(METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O))) == 0);
return new BoxedCApiFunction(ml, self, module);
}
......@@ -1725,6 +1721,8 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
int flags = self->method_def->ml_flags;
auto func = self->method_def->ml_meth;
flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST);
ParamReceiveSpec paramspec(0, 0, true, false);
Box** defaults = NULL;
if (flags == METH_VARARGS) {
......@@ -1820,7 +1818,7 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
rewrite_args->arg1)->setType(RefType::OWNED);
} else if ((flags & ~(METH_O3 | METH_D3)) == 0) {
assert(paramspec.totalReceived() <= 3); // would need to pass through oargs
rtn = ((Box * (*)(Box*, Box*, Box*, Box*))func)(self->passthrough, arg1, arg2, arg3);
rtn = ((Box * (*)(Box*, Box*, Box*, Box**))func)(self->passthrough, arg1, arg2, &arg3);
if (rewrite_args) {
if (paramspec.totalReceived() == 1)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough,
......@@ -1829,11 +1827,13 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
rewrite_args->out_rtn
= rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1,
rewrite_args->arg2)->setType(RefType::OWNED);
else if (paramspec.totalReceived() == 3)
else if (paramspec.totalReceived() == 3) {
auto args = rewrite_args->rewriter->allocate(1);
args->setAttr(0, rewrite_args->arg3);
rewrite_args->out_rtn
= rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1,
rewrite_args->arg2, rewrite_args->arg3)->setType(RefType::OWNED);
else
rewrite_args->arg2, args)->setType(RefType::OWNED);
} else
abort();
}
} else if (flags == METH_OLDARGS) {
......@@ -1915,8 +1915,7 @@ void setupCAPI() {
capifunc_cls->tpp_call.cxx_val = BoxedCApiFunction::tppCall<CXX>;
capifunc_cls->giveAttrDescriptor("__name__", BoxedCApiFunction::getname, NULL);
capifunc_cls->giveAttrDescriptor("__doc__", BoxedCApiFunction::doc, NULL);
capifunc_cls->giveAttr(
"__module__", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedCApiFunction, module)));
capifunc_cls->giveAttrMember("__module__", T_OBJECT, offsetof(BoxedCApiFunction, module));
capifunc_cls->freeze();
}
......
......@@ -26,7 +26,7 @@ extern "C" {
BoxedClass* code_cls;
}
BORROWED(Box*) BoxedCode::name(Box* b, void*) {
BORROWED(Box*) BoxedCode::name(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
if (code->_name)
......@@ -34,11 +34,11 @@ BORROWED(Box*) BoxedCode::name(Box* b, void*) {
return code->f->source->getName();
}
Box* BoxedCode::co_name(Box* b, void* arg) {
Box* BoxedCode::co_name(Box* b, void* arg) noexcept {
return incref(name(b, arg));
}
BORROWED(Box*) BoxedCode::filename(Box* b, void*) {
BORROWED(Box*) BoxedCode::filename(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
if (code->_filename)
......@@ -46,11 +46,11 @@ BORROWED(Box*) BoxedCode::filename(Box* b, void*) {
return code->f->source->getFn();
}
Box* BoxedCode::co_filename(Box* b, void* arg) {
Box* BoxedCode::co_filename(Box* b, void* arg) noexcept {
return incref(filename(b, arg));
}
Box* BoxedCode::firstlineno(Box* b, void*) {
Box* BoxedCode::firstlineno(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
FunctionMetadata* md = code->f;
......@@ -64,12 +64,12 @@ Box* BoxedCode::firstlineno(Box* b, void*) {
return boxInt(md->source->ast->lineno);
}
Box* BoxedCode::argcount(Box* b, void*) {
Box* BoxedCode::argcount(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
return boxInt(static_cast<BoxedCode*>(b)->f->num_args);
}
Box* BoxedCode::varnames(Box* b, void*) {
Box* BoxedCode::varnames(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
......@@ -90,7 +90,7 @@ Box* BoxedCode::varnames(Box* b, void*) {
return rtn;
}
Box* BoxedCode::flags(Box* b, void*) {
Box* BoxedCode::flags(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
......
......@@ -39,14 +39,14 @@ public:
// These need to be static functions rather than methods because function
// pointers could point to them.
static BORROWED(Box*) name(Box* b, void*);
static BORROWED(Box*) filename(Box* b, void*);
static Box* co_name(Box* b, void*);
static Box* co_filename(Box* b, void*);
static Box* firstlineno(Box* b, void*);
static Box* argcount(Box* b, void*);
static Box* varnames(Box* b, void*);
static Box* flags(Box* b, void*);
static BORROWED(Box*) name(Box* b, void*) noexcept;
static BORROWED(Box*) filename(Box* b, void*) noexcept;
static Box* co_name(Box* b, void*) noexcept;
static Box* co_filename(Box* b, void*) noexcept;
static Box* firstlineno(Box* b, void*) noexcept;
static Box* argcount(Box* b, void*) noexcept;
static Box* varnames(Box* b, void*) noexcept;
static Box* flags(Box* b, void*) noexcept;
static int traverse(Box* self, visitproc visit, void* arg) noexcept;
static void dealloc(Box* b) noexcept;
......
......@@ -741,7 +741,8 @@ PyObject* complex_neg(PyComplexObject* v) {
}
static PyMethodDef complex_methods[] = {
{ "__format__", (PyCFunction)complex__format__, METH_VARARGS, NULL },
{ "__format__", (PyCFunction)complex__format__, METH_VARARGS, NULL }, //
{ NULL, NULL, 0, NULL },
};
void setupComplex() {
......@@ -810,19 +811,15 @@ void setupComplex() {
complex_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)complexFloat, UNKNOWN, 1)));
complex_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)complexLong, UNKNOWN, 1)));
complex_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)complexRepr, STR, 1)));
complex_cls->giveAttr("real",
new BoxedMemberDescriptor(BoxedMemberDescriptor::DOUBLE, offsetof(BoxedComplex, real)));
complex_cls->giveAttr("imag",
new BoxedMemberDescriptor(BoxedMemberDescriptor::DOUBLE, offsetof(BoxedComplex, imag)));
complex_cls->giveAttrMember("real", T_DOUBLE, offsetof(BoxedComplex, real), true);
complex_cls->giveAttrMember("imag", T_DOUBLE, offsetof(BoxedComplex, imag), true);
complex_cls->giveAttr("__doc__",
boxString("complex(real[, imag]) -> complex number\n"
"\n"
"Create a complex number from a real part and an optional imaginary part.\n"
"This is equivalent to (real + imag*1j) where imag defaults to 0."));
for (auto& md : complex_methods) {
complex_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, complex_cls));
}
add_methods(complex_cls, complex_methods);
add_operators(complex_cls);
......
This diff is collapsed.
......@@ -1117,10 +1117,11 @@ static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void*
float_cls->giveAttr(name, new BoxedFunction(md, { None }));
}
static Box* floatConjugate(Box* b, void*) {
if (!PyFloat_Check(b))
raiseExcHelper(TypeError, "descriptor 'conjugate' requires a 'float' object but received a '%s'",
getTypeName(b));
static Box* float_conjugate(Box* b, void*) noexcept {
if (!PyFloat_Check(b)) {
PyErr_Format(TypeError, "descriptor 'conjugate' requires a 'float' object but received a '%s'", getTypeName(b));
return NULL;
}
if (b->cls == float_cls) {
return incref(b);
} else {
......@@ -1129,7 +1130,7 @@ static Box* floatConjugate(Box* b, void*) {
}
}
static Box* float0(Box*, void*) {
static Box* float0(Box*, void*) noexcept {
return boxFloat(0.0);
}
......@@ -1671,7 +1672,8 @@ static PyMethodDef float_methods[]
{ "as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS, NULL },
{ "__setformat__", (PyCFunction)float_setformat, METH_VARARGS | METH_CLASS, float_setformat_doc },
{ "is_integer", (PyCFunction)float_is_integer, METH_NOARGS, NULL },
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL } };
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL } };
void setupFloat() {
static PyNumberMethods float_as_number;
......@@ -1733,10 +1735,10 @@ void setupFloat() {
float_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)floatLong, UNKNOWN, 1)));
float_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)floatHash, BOXED_INT, 1)));
float_cls->giveAttrDescriptor("real", floatConjugate, NULL);
float_cls->giveAttrDescriptor("real", float_conjugate, NULL);
float_cls->giveAttrDescriptor("imag", float0, NULL);
float_cls->giveAttr("conjugate",
new BoxedFunction(FunctionMetadata::create((void*)floatConjugate, BOXED_FLOAT, 1)));
float_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)float_conjugate, BOXED_FLOAT, 1,
ParamNames::empty(), CAPI)));
float_cls->giveAttr("__doc__", boxString("float(x) -> floating point number\n"
"\n"
......@@ -1745,9 +1747,7 @@ void setupFloat() {
new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)floatGetFormat, STR, 1),
"__getformat__", floatGetFormatDoc));
for (auto& md : float_methods) {
float_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, float_cls));
}
add_methods(float_cls, float_methods);
add_operators(float_cls);
float_cls->freeze();
......
......@@ -79,7 +79,7 @@ public:
// * = unsupported in Pyston
// ** = getter supported, but setter unsupported
static BORROWED(Box*) code(Box* obj, void*) {
static BORROWED(Box*) code(Box* obj, void*) noexcept {
auto f = static_cast<BoxedFrame*>(obj);
if (!f->_code)
......@@ -88,9 +88,9 @@ public:
return f->_code;
}
static Box* f_code(Box* obj, void* arg) { return incref(code(obj, arg)); }
static Box* f_code(Box* obj, void* arg) noexcept { return incref(code(obj, arg)); }
static BORROWED(Box*) locals(Box* obj, void*) {
static BORROWED(Box*) locals(Box* obj, void*) noexcept {
auto f = static_cast<BoxedFrame*>(obj);
if (f->hasExited())
......@@ -99,9 +99,9 @@ public:
return f->frame_info->updateBoxedLocals();
}
static Box* f_locals(Box* obj, void* arg) { return incref(locals(obj, arg)); }
static Box* f_locals(Box* obj, void* arg) noexcept { return incref(locals(obj, arg)); }
static BORROWED(Box*) globals(Box* obj, void*) {
static BORROWED(Box*) globals(Box* obj, void*) noexcept {
auto f = static_cast<BoxedFrame*>(obj);
if (!f->_globals) {
......@@ -116,9 +116,9 @@ public:
return f->_globals;
}
static Box* f_globals(Box* obj, void* arg) { return incref(globals(obj, arg)); }
static Box* f_globals(Box* obj, void* arg) noexcept { return incref(globals(obj, arg)); }
static BORROWED(Box*) back(Box* obj, void*) {
static BORROWED(Box*) back(Box* obj, void*) noexcept {
auto f = static_cast<BoxedFrame*>(obj);
if (!f->_back) {
......@@ -131,9 +131,9 @@ public:
return f->_back;
}
static Box* f_back(Box* obj, void* arg) { return incref(back(obj, arg)); }
static Box* f_back(Box* obj, void* arg) noexcept { return incref(back(obj, arg)); }
static Box* lineno(Box* obj, void*) {
static Box* lineno(Box* obj, void*) noexcept {
auto f = static_cast<BoxedFrame*>(obj);
if (f->hasExited())
......
......@@ -500,7 +500,7 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
context = makeContext(stack_begin, (void (*)(intptr_t))generatorEntry);
}
Box* generatorName(Box* _self, void* context) {
Box* generator_name(Box* _self, void* context) noexcept {
assert(isSubclass(_self->cls, generator_cls));
BoxedGenerator* self = static_cast<BoxedGenerator*>(_self);
......@@ -715,7 +715,7 @@ void setupGenerator() {
= new BoxedFunction(FunctionMetadata::create((void*)generatorThrow, UNKNOWN, 4, false, false), { NULL, NULL });
generator_cls->giveAttr("throw", gthrow);
generator_cls->giveAttrDescriptor("__name__", generatorName, NULL);
generator_cls->giveAttrDescriptor("__name__", generator_name, NULL);
generator_cls->freeze();
generator_cls->tp_iter = PyObject_SelfIter;
......
......@@ -1395,7 +1395,7 @@ static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type,
int_cls->giveAttr(name, new BoxedFunction(md));
}
static Box* intIntGetset(Box* b, void*) {
static Box* int_int_getset(Box* b, void*) noexcept {
if (b->cls == int_cls) {
return incref(b);
} else {
......@@ -1404,11 +1404,11 @@ static Box* intIntGetset(Box* b, void*) {
}
}
static Box* int0(Box*, void*) {
static Box* int0(Box*, void*) noexcept {
return boxInt(0);
}
static Box* int1(Box*, void*) {
static Box* int1(Box*, void*) noexcept {
return boxInt(1);
}
......@@ -1608,10 +1608,11 @@ void setupInt() {
int_cls->giveAttr("bit_length", new BoxedFunction(FunctionMetadata::create((void*)intBitLength, BOXED_INT, 1)));
int_cls->giveAttrDescriptor("real", intIntGetset, NULL);
// int_int_getset doesn't throw at all, so we can cheat and use it as both a CAPI and CXX style function.
int_cls->giveAttrDescriptor("real", int_int_getset, NULL);
int_cls->giveAttrDescriptor("imag", int0, NULL);
int_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)intIntGetset, BOXED_INT, 1)));
int_cls->giveAttrDescriptor("numerator", intIntGetset, NULL);
int_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)int_int_getset, BOXED_INT, 1)));
int_cls->giveAttrDescriptor("numerator", int_int_getset, NULL);
int_cls->giveAttrDescriptor("denominator", int1, NULL);
add_operators(int_cls);
......
......@@ -787,7 +787,7 @@ Box* longInt(Box* v) {
return boxInt(n);
}
Box* longToLong(Box* self) {
Box* longToLong(Box* self) noexcept {
if (self->cls == long_cls) {
return incref(self);
} else {
......@@ -1678,15 +1678,15 @@ static PyObject* long_pow(PyObject* v, PyObject* w, PyObject* x) noexcept {
}
}
static Box* longDesc(Box* b, void*) {
static Box* long_desc(Box* b, void*) noexcept {
return longToLong(b);
}
static Box* long0(Box* b, void*) {
static Box* long0(Box* b, void*) noexcept {
return boxLong(0);
}
static Box* long1(Box* b, void*) {
static Box* long1(Box* b, void*) noexcept {
return boxLong(1);
}
......@@ -1763,10 +1763,11 @@ void setupLong() {
long_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)longIndex, LONG, 1)));
long_cls->giveAttr("bit_length", new BoxedFunction(FunctionMetadata::create((void*)longBitLength, LONG, 1)));
long_cls->giveAttrDescriptor("real", longDesc, NULL);
long_cls->giveAttrDescriptor("real", long_desc, NULL);
long_cls->giveAttrDescriptor("imag", long0, NULL);
long_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)longDesc, UNKNOWN, 1)));
long_cls->giveAttrDescriptor("numerator", longDesc, NULL);
// long_desc is both CAPI and CXX style since it doesn't throw
long_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)long_desc, UNKNOWN, 1)));
long_cls->giveAttrDescriptor("numerator", long_desc, NULL);
long_cls->giveAttrDescriptor("denominator", long1, NULL);
long_cls->giveAttr("__getnewargs__", new BoxedFunction(FunctionMetadata::create((void*)long_getnewargs, UNKNOWN, 1,
......
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include "runtime/set.h"
#include "capi/typeobject.h"
#include "runtime/objmodel.h"
namespace pyston {
......@@ -919,12 +920,10 @@ int BoxedSet::clear(Box* _o) noexcept {
return 0;
}
static PyMethodDef set_methods[] = {
{ "__reduce__", (PyCFunction)set_reduce, METH_NOARGS, NULL },
};
static PyMethodDef frozenset_methods[] = {
{ "__reduce__", (PyCFunction)set_reduce, METH_NOARGS, NULL },
};
static PyMethodDef set_methods[]
= { { "__reduce__", (PyCFunction)set_reduce, METH_NOARGS, NULL }, { NULL, NULL, 0, NULL } };
static PyMethodDef frozenset_methods[]
= { { "__reduce__", (PyCFunction)set_reduce, METH_NOARGS, NULL }, { NULL, NULL, 0, NULL } };
void setupSet() {
static PySequenceMethods set_as_sequence;
......@@ -1070,13 +1069,8 @@ void setupSet() {
frozenset_cls->giveAttr("copy", new BoxedFunction(FunctionMetadata::create((void*)frozensetCopy, UNKNOWN, 1)));
set_cls->giveAttr("pop", new BoxedFunction(FunctionMetadata::create((void*)setPop, UNKNOWN, 1)));
for (auto& md : set_methods) {
set_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, set_cls));
}
for (auto& md : frozenset_methods) {
frozenset_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, frozenset_cls));
}
add_methods(set_cls, set_methods);
add_methods(frozenset_cls, frozenset_methods);
set_cls->freeze();
frozenset_cls->freeze();
......
......@@ -2851,6 +2851,7 @@ static PyMethodDef string_methods[] = {
{ "__format__", (PyCFunction)string__format__, METH_VARARGS, NULL },
{ "_formatter_parser", (PyCFunction)_formatter_parser, METH_NOARGS, NULL },
{ "_formatter_field_name_split", (PyCFunction)_formatter_field_name_split, METH_NOARGS, NULL },
{ NULL, NULL, 0, NULL },
};
void setupStr() {
......@@ -2961,9 +2962,7 @@ void setupStr() {
str_cls->giveAttr("__iter__",
new BoxedFunction(FunctionMetadata::create((void*)strIter, typeFromClass(str_iterator_cls), 1)));
for (auto& md : string_methods) {
str_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, str_cls));
}
add_methods(str_cls, string_methods);
auto str_new = FunctionMetadata::create((void*)strNew<CXX>, UNKNOWN, 2, false, false,
ParamNames({ "", "object" }, "", ""), CXX);
......
......@@ -260,12 +260,9 @@ void setupSuper() {
"__init__", new BoxedFunction(FunctionMetadata::create((void*)superInit, UNKNOWN, 3, false, false), { NULL }));
super_cls->giveAttr("__get__", new BoxedFunction(FunctionMetadata::create((void*)superGet<CXX>, UNKNOWN, 3)));
super_cls->giveAttr("__thisclass__",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSuper, type)));
super_cls->giveAttr("__self__",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSuper, obj)));
super_cls->giveAttr("__self_class__",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSuper, obj_type)));
super_cls->giveAttrMember("__thisclass__", T_OBJECT, offsetof(BoxedSuper, type));
super_cls->giveAttrMember("__self__", T_OBJECT, offsetof(BoxedSuper, obj));
super_cls->giveAttrMember("__self_class__", T_OBJECT, offsetof(BoxedSuper, obj_type));
super_cls->freeze();
super_cls->tp_getattro = super_getattro;
......
This diff is collapsed.
......@@ -77,10 +77,9 @@ extern "C" BoxedString* EmptyString;
extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *enumerate_cls,
*xrange_cls, *member_descriptor_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls,
*property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls,
*builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls, *frame_cls, *capifunc_cls, *wrapperdescr_cls,
*wrapperobject_cls;
*xrange_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *property_cls, *staticmethod_cls,
*classmethod_cls, *attrwrapper_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls,
*frame_cls, *capifunc_cls;
}
#define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type)
......@@ -184,7 +183,7 @@ public:
HCAttrs attrs;
// TODO: these don't actually get deallocated right now
// Any new ics here need to get reflected in BoxedClass::dealloc
std::unique_ptr<CallattrCapiIC> next_ic;
std::unique_ptr<CallattrIC> hasnext_ic, repr_ic, iter_ic;
std::unique_ptr<NonzeroIC> nonzero_ic;
......@@ -1169,69 +1168,6 @@ static_assert(offsetof(BoxedSlice, start) == offsetof(PySliceObject, start), "")
static_assert(offsetof(BoxedSlice, stop) == offsetof(PySliceObject, stop), "");
static_assert(offsetof(BoxedSlice, step) == offsetof(PySliceObject, step), "");
class BoxedMemberDescriptor : public Box {
public:
enum MemberType {
BOOL = T_BOOL,
BYTE = T_BYTE,
INT = T_INT,
OBJECT = T_OBJECT,
OBJECT_EX = T_OBJECT_EX,
FLOAT = T_FLOAT,
SHORT = T_SHORT,
LONG = T_LONG,
DOUBLE = T_DOUBLE,
STRING = T_STRING,
STRING_INPLACE = T_STRING_INPLACE,
CHAR = T_CHAR,
UBYTE = T_UBYTE,
USHORT = T_USHORT,
UINT = T_UINT,
ULONG = T_ULONG,
LONGLONG = T_LONGLONG,
ULONGLONG = T_ULONGLONG,
PYSSIZET = T_PYSSIZET
} type;
int offset;
bool readonly;
BoxedMemberDescriptor(MemberType type, int offset, bool readonly = true)
: type(type), offset(offset), readonly(readonly) {}
BoxedMemberDescriptor(PyMemberDef* member)
: type((MemberType)member->type), offset(member->offset), readonly(member->flags & READONLY) {}
DEFAULT_CLASS_SIMPLE(member_descriptor_cls, false);
};
class BoxedGetsetDescriptor : public Box {
public:
Box* (*get)(Box*, void*);
union {
void* set;
void (*set_pyston)(Box*, Box*, void*);
int (*set_capi)(Box*, Box*, void*);
};
void* closure;
BoxedString* name;
BoxedGetsetDescriptor(BoxedString* name, Box* (*get)(Box*, void*), void (*set)(Box*, Box*, void*), void* closure)
: get(get), set_pyston(set), closure(closure), name(name) {
assert(this->cls == pyston_getset_cls);
Py_INCREF(name);
}
BoxedGetsetDescriptor(BoxedString* name, Box* (*get)(Box*, void*), int (*set)(Box*, Box*, void*), void* closure)
: get(get), set_capi(set), closure(closure), name(name) {
assert(this->cls == capi_getset_cls);
Py_INCREF(name);
}
static void dealloc(Box* b) noexcept;
// No DEFAULT_CLASS annotation here -- force callers to explicitly specifiy pyston_getset_cls or capi_getset_cls
};
class BoxedProperty : public Box {
public:
Box* prop_get;
......@@ -1338,78 +1274,6 @@ public:
DEFAULT_CLASS(generator_cls);
};
struct wrapper_def {
const llvm::StringRef name;
int offset;
void* function; // "generic" handler that gets put in the tp_* slot which proxies to the python version
wrapperfunc wrapper; // "wrapper" that ends up getting called by the Python-visible WrapperDescr
const llvm::StringRef doc;
int flags;
BoxedString* name_strobj;
};
class BoxedWrapperDescriptor : public Box {
public:
const wrapper_def* wrapper;
BoxedClass* type;
void* wrapped;
BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type, void* wrapped)
: wrapper(wrapper), type(type), wrapped(wrapped) {
Py_INCREF(type);
}
static void dealloc(Box* b) noexcept;
static int traverse(Box* _self, visitproc visit, void* arg) noexcept;
DEFAULT_CLASS(wrapperdescr_cls);
static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
};
class BoxedWrapperObject : public Box {
public:
BoxedWrapperDescriptor* descr;
Box* obj;
BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : descr(descr), obj(obj) {
Py_INCREF(descr);
Py_INCREF(obj);
}
DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
static void dealloc(Box* self) noexcept;
static int traverse(Box* self, visitproc visit, void* arg) noexcept;
};
class BoxedMethodDescriptor : public Box {
public:
PyMethodDef* method;
BoxedClass* type;
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) { Py_INCREF(type); }
DEFAULT_CLASS(method_cls);
static Box* descr_get(BoxedMethodDescriptor* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
static void dealloc(Box* self) noexcept;
static int traverse(Box* self, visitproc visit, void* arg) noexcept;
};
Box* objectSetattr(Box* obj, Box* attr, Box* value);
BORROWED(Box*) unwrapAttrWrapper(Box* b);
......
......@@ -25,9 +25,9 @@ def install_and_test_cffi():
# looks like clang 3.5 causes more errors like: 214 != -42 doing casts
if os.environ.has_key("CC") and "clang" in os.environ["CC"]:
expected = [{ "failed": 34, "passed": 1643, "skipped": 70, "xfailed": 4, "error": 5 }]
expected = [{ "failed": 20, "passed": 1657, "skipped": 70, "xfailed": 4, "error": 5 }]
else:
expected = [{ "failed": 25, "passed": 1652, "skipped": 70, "xfailed": 4, "error": 5 }]
expected = [{ "failed": 11, "passed": 1666, "skipped": 70, "xfailed": 4, "error": 5 }]
run_test([PYTEST_EXE], cwd=CFFI_DIR, expected=expected)
create_virtenv(ENV_NAME, ["pytest==2.8.7", "py==1.4.31", "pycparser==2.14"], force_create = True)
......
......@@ -46,8 +46,6 @@ if not os.path.exists(CYTHON_DIR):
else:
print ">>> Cython already installed."
NUMPY_PATCH_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "../integration/numpy_patch.patch"))
print_progress_header("Cloning up NumPy...")
if not os.path.exists(NUMPY_DIR):
url = "https://github.com/numpy/numpy"
......@@ -55,12 +53,6 @@ if not os.path.exists(NUMPY_DIR):
else:
print ">>> NumPy already installed."
PATCH_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "../integration/numpy_patch.patch"))
if USE_CUSTOM_PATCHES:
print_progress_header("Patching NumPy...")
subprocess.check_call(["patch", "-p1", "--input=" + PATCH_FILE], cwd=NUMPY_DIR)
try:
env = os.environ
CYTHON_BIN_DIR = os.path.abspath(os.path.join(ENV_NAME + "/bin"))
......@@ -76,25 +68,14 @@ try:
print_progress_header("Installing NumPy...")
subprocess.check_call([PYTHON_EXE, "setup.py", "install"], cwd=NUMPY_DIR, env=env)
except:
if USE_CUSTOM_PATCHES:
print_progress_header("Unpatching NumPy...")
cmd = ["patch", "-p1", "--forward", "-i", NUMPY_PATCH_FILE, "-R", "-d", NUMPY_DIR]
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
# TODO: I'm not sure we need to do this:
subprocess.check_call(["rm", "-rf", NUMPY_DIR + "/build"])
subprocess.check_call(["rm", "-rf", NUMPY_DIR + "/dist"])
raise
try:
test_helper.run_test(['sh', '-c', '. %s/bin/activate && python %s/numpy/tools/test-installed-numpy.py' % (ENV_DIR, ENV_DIR)],
ENV_NAME, [dict(ran=6139, errors=1, failures=1)])
finally:
if USE_CUSTOM_PATCHES:
print_progress_header("Unpatching NumPy...")
cmd = ["patch", "-p1", "--forward", "-i", NUMPY_PATCH_FILE, "-R", "-d", NUMPY_DIR]
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
test_helper.run_test(['sh', '-c', '. %s/bin/activate && python %s/numpy/tools/test-installed-numpy.py' % (ENV_DIR, ENV_DIR)],
ENV_NAME, [dict(ran=6139, failures=1)])
print
print "PASSED"
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index b9db3bb..2d24efc 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -1337,13 +1337,13 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
_ADDDOC(Type, new->tp_doc, new->tp_name);
}
else if (_TESTDOC2(MemberDescr)) {
- _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name);
+ /* _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name); */
}
else if (_TESTDOC2(GetSetDescr)) {
- _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name);
+ /* _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name); */
}
else if (_TESTDOC2(MethodDescr)) {
- _ADDDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name);
+ /* _ADDDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name); */
}
else {
PyObject *doc_attr;
......@@ -86,8 +86,6 @@ if not os.path.exists(CYTHON_DIR):
else:
print ">>> Cython already installed."
NUMPY_PATCH_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "numpy_patch.patch"))
print_progress_header("Cloning up NumPy...")
if not os.path.exists(NUMPY_DIR):
url = "https://github.com/numpy/numpy"
......@@ -95,12 +93,6 @@ if not os.path.exists(NUMPY_DIR):
else:
print ">>> NumPy already installed."
PATCH_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "numpy_patch.patch"))
if USE_CUSTOM_PATCHES:
print_progress_header("Patching NumPy...")
subprocess.check_call(["patch", "-p1", "--input=" + PATCH_FILE], cwd=NUMPY_DIR)
try:
env = os.environ
CYTHON_BIN_DIR = os.path.abspath(os.path.join(ENV_NAME + "/bin"))
......@@ -112,12 +104,6 @@ try:
print_progress_header("Installing NumPy...")
subprocess.check_call([PYTHON_EXE, "setup.py", "install"], cwd=NUMPY_DIR, env=env)
except:
if USE_CUSTOM_PATCHES:
print_progress_header("Unpatching NumPy...")
cmd = ["patch", "-p1", "--forward", "-i", NUMPY_PATCH_FILE, "-R", "-d", NUMPY_DIR]
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
# TODO: I'm not sure we need to do this:
subprocess.check_call(["rm", "-rf", NUMPY_DIR + "/build"])
subprocess.check_call(["rm", "-rf", NUMPY_DIR + "/dist"])
......@@ -190,10 +176,5 @@ print_progress_header("Running NumPy test suite...")
# when all the crashes are fixed.
# subprocess.check_call([PYTHON_EXE, "-c", numpy_test], cwd=CYTHON_DIR)
if USE_CUSTOM_PATCHES:
print_progress_header("Unpatching NumPy...")
cmd = ["patch", "-p1", "--forward", "-i", NUMPY_PATCH_FILE, "-R", "-d", NUMPY_DIR]
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
print
print "PASSED"
# This code was legal in CPython 2.7.3 but became illegal in 2.7.4
# (there is a methoddescr.expected file for this test)
for i in xrange(1000):
float.__dict__['fromhex'](float, "f0.04a")
......@@ -8,3 +8,4 @@ print type(None.__str__)
print(None.__str__.__name__)
print type(type(None).__str__.__get__(None, type(None)))
print u"".__len__.__call__()
print type(u'').__dict__['__len__'].__call__(u'')
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