Commit def49b2f authored by Marius Wachtler's avatar Marius Wachtler

Add setting func.func_code, PyCFunction_Call, vars() error handling

- in additon allow Py_TPFLAGS_HAVE_VERSION_TAG because even though we don't use it this flag shouldn't cause problems
- allow tp_del because AFAIK it's implemented.
- allow calling methods which specify METH_COEXIST because it doen't make a difference for the call
- disable PyCode_New call inside cython because we don't support it yet and it's unused.
- change cython to use PyCFunction_Call instead of the custom version it has for pypy
parent f1575546
...@@ -3358,7 +3358,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -3358,7 +3358,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
// unhandled fields: // unhandled fields:
int ALLOWABLE_FLAGS = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES int ALLOWABLE_FLAGS = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES
| Py_TPFLAGS_HAVE_NEWBUFFER; | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_HAVE_VERSION_TAG;
ALLOWABLE_FLAGS |= Py_TPFLAGS_INT_SUBCLASS | Py_TPFLAGS_LONG_SUBCLASS | Py_TPFLAGS_LIST_SUBCLASS ALLOWABLE_FLAGS |= Py_TPFLAGS_INT_SUBCLASS | Py_TPFLAGS_LONG_SUBCLASS | Py_TPFLAGS_LIST_SUBCLASS
| Py_TPFLAGS_TUPLE_SUBCLASS | Py_TPFLAGS_STRING_SUBCLASS | Py_TPFLAGS_UNICODE_SUBCLASS | Py_TPFLAGS_TUPLE_SUBCLASS | Py_TPFLAGS_STRING_SUBCLASS | Py_TPFLAGS_UNICODE_SUBCLASS
| Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_TYPE_SUBCLASS; | Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_TYPE_SUBCLASS;
......
...@@ -82,7 +82,11 @@ extern "C" Box* vars(Box* obj) { ...@@ -82,7 +82,11 @@ extern "C" Box* vars(Box* obj) {
if (!obj) if (!obj)
return fastLocalsToBoxedLocals(); return fastLocalsToBoxedLocals();
return obj->getAttrWrapper(); static BoxedString* dict_str = internStringImmortal("__dict__");
Box* rtn = getattrInternal<ExceptionStyle::CAPI>(obj, dict_str, NULL);
if (!rtn)
raiseExcHelper(TypeError, "vars() argument must have __dict__ attribute");
return rtn;
} }
extern "C" Box* abs_(Box* x) { extern "C" Box* abs_(Box* x) {
......
...@@ -1382,6 +1382,12 @@ extern "C" int PyCFunction_GetFlags(PyObject* op) noexcept { ...@@ -1382,6 +1382,12 @@ extern "C" int PyCFunction_GetFlags(PyObject* op) noexcept {
return static_cast<BoxedCApiFunction*>(op)->method_def->ml_flags; return static_cast<BoxedCApiFunction*>(op)->method_def->ml_flags;
} }
extern "C" PyObject* PyCFunction_Call(PyObject* func, PyObject* arg, PyObject* kw) noexcept {
assert(arg->cls == tuple_cls);
assert(!kw || kw->cls == dict_cls);
return BoxedCApiFunction::tppCall<CAPI>(func, NULL, ArgPassSpec(0, 0, true, true), arg, kw, NULL, NULL, NULL);
}
extern "C" int _PyEval_SliceIndex(PyObject* v, Py_ssize_t* pi) noexcept { extern "C" int _PyEval_SliceIndex(PyObject* v, Py_ssize_t* pi) noexcept {
if (v != NULL) { if (v != NULL) {
Py_ssize_t x; Py_ssize_t x;
...@@ -1491,7 +1497,6 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa ...@@ -1491,7 +1497,6 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10); STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10);
assert(_self->cls == capifunc_cls);
BoxedCApiFunction* self = static_cast<BoxedCApiFunction*>(_self); BoxedCApiFunction* self = static_cast<BoxedCApiFunction*>(_self);
if (rewrite_args) { if (rewrite_args) {
......
...@@ -2409,7 +2409,8 @@ public: ...@@ -2409,7 +2409,8 @@ public:
static Box* next(BoxedStringIterator* self) { static Box* next(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls); assert(self->cls == str_iterator_cls);
assert(hasnextUnboxed(self)); if (!hasnextUnboxed(self))
raiseExcHelper(StopIteration, (const char*)nullptr);
char c = *self->it; char c = *self->it;
++self->it; ++self->it;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/classobj.h" #include "runtime/classobj.h"
#include "runtime/code.h"
#include "runtime/complex.h" #include "runtime/complex.h"
#include "runtime/dict.h" #include "runtime/dict.h"
#include "runtime/file.h" #include "runtime/file.h"
...@@ -1684,6 +1685,25 @@ static Box* functionCode(Box* self, void*) { ...@@ -1684,6 +1685,25 @@ static Box* functionCode(Box* self, void*) {
return codeForFunction(func); return codeForFunction(func);
} }
static void functionSetCode(Box* self, Box* v, void*) {
assert(self->cls == function_cls);
if (v == NULL || !PyCode_Check(v))
raiseExcHelper(TypeError, "__code__ must be set to a code object");
BoxedFunction* func = static_cast<BoxedFunction*>(self);
BoxedCode* code = static_cast<BoxedCode*>(v);
if (!func->f->source || !code->f->source)
raiseExcHelper(TypeError, "__code__ can only be set on python functions");
RELEASE_ASSERT(!func->f->internal_callable.get<CXX>() && !func->f->internal_callable.get<CAPI>(),
"this could cause invalidation issues");
func->f = code->f;
func->dependent_ics.invalidateAll();
}
static Box* functionDefaults(Box* self, void*) { static Box* functionDefaults(Box* self, void*) {
assert(self->cls == function_cls); assert(self->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(self); BoxedFunction* func = static_cast<BoxedFunction*>(self);
...@@ -3867,7 +3887,8 @@ void setupRuntime() { ...@@ -3867,7 +3887,8 @@ void setupRuntime() {
function_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)functionGet, UNKNOWN, 3))); function_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)functionGet, UNKNOWN, 3)));
function_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)functionCall, UNKNOWN, 1, true, true))); function_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)functionCall, UNKNOWN, 1, true, true)));
function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1))); function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1)));
function_cls->giveAttr("func_code", new (pyston_getset_cls) BoxedGetsetDescriptor(functionCode, NULL, NULL)); function_cls->giveAttr("func_code",
new (pyston_getset_cls) BoxedGetsetDescriptor(functionCode, functionSetCode, NULL));
function_cls->giveAttr("__code__", function_cls->getattr(internStringMortal("func_code"))); function_cls->giveAttr("__code__", function_cls->getattr(internStringMortal("func_code")));
function_cls->giveAttr("func_name", function_cls->getattr(internStringMortal("__name__"))); function_cls->giveAttr("func_name", function_cls->getattr(internStringMortal("__name__")));
function_cls->giveAttr("func_defaults", function_cls->giveAttr("func_defaults",
......
From 0d1aaa649bd47a3f78e573eb4e5b9e35f9aa02d3 Mon Sep 17 00:00:00 2001 From 27b69179b90851da187d698a0817b0b8190a0449 Mon Sep 17 00:00:00 2001
From: Marius Wachtler <undingen@gmail.com> From: Marius Wachtler <undingen@gmail.com>
Date: Tue, 9 Jun 2015 19:26:44 +0200 Date: Tue, 9 Jun 2015 19:26:44 +0200
Subject: [PATCH] Pyston change: we don't support custom traceback entries yet Subject: [PATCH] Pyston change: we don't support custom traceback entries yet
--- ---
Cython/Compiler/ModuleNode.py | 8 ++++++-- Cython/Compiler/ExprNodes.py | 9 +++++++++
Cython/Utility/Exceptions.c | 7 ++++++- Cython/Compiler/ModuleNode.py | 8 ++++++--
Cython/Utility/Generator.c | 31 +++++++++++++++++++++---------- Cython/Utility/CythonFunction.c | 4 +++-
3 files changed, 33 insertions(+), 13 deletions(-) Cython/Utility/Exceptions.c | 7 ++++++-
Cython/Utility/Generator.c | 41 +++++++++++++++++++++++++++++------------
5 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index f99ec6e..7ab41f3 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -7784,12 +7784,21 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
@classmethod
def from_defnode(cls, node, binding):
+ """
+ # Pyston change: dont't generate custom code objects because we don't support them currently
return cls(node.pos,
def_node=node,
pymethdef_cname=node.entry.pymethdef_cname,
binding=binding or node.specialized_cpdefs,
specialized_cpdefs=node.specialized_cpdefs,
code_object=CodeObjectNode(node))
+ """
+ return cls(node.pos,
+ def_node=node,
+ pymethdef_cname=node.entry.pymethdef_cname,
+ binding=binding or node.specialized_cpdefs,
+ specialized_cpdefs=node.specialized_cpdefs,
+ code_object=None)
def analyse_types(self, env):
if self.binding:
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 4785858..699cd15 100644 index 4785858..699cd15 100644
--- a/Cython/Compiler/ModuleNode.py --- a/Cython/Compiler/ModuleNode.py
...@@ -29,6 +57,21 @@ index 4785858..699cd15 100644 ...@@ -29,6 +57,21 @@ index 4785858..699cd15 100644
code.putln("PyErr_Restore(etype, eval, etb);") code.putln("PyErr_Restore(etype, eval, etb);")
code.putln("}") code.putln("}")
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 9cc38f0..ab05ad1 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -561,7 +561,9 @@ __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
#endif
}
-#if CYTHON_COMPILING_IN_PYPY
+// Pyston change:
+// #if CYTHON_COMPILING_IN_PYPY
+#if 0 && CYTHON_COMPILING_IN_PYPY
// originally copied from PyCFunction_Call() in CPython's Objects/methodobject.c
// PyPy does not have this function
static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) {
diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c
index 354a776..8af3cb7 100644 index 354a776..8af3cb7 100644
--- a/Cython/Utility/Exceptions.c --- a/Cython/Utility/Exceptions.c
...@@ -52,7 +95,7 @@ index 354a776..8af3cb7 100644 ...@@ -52,7 +95,7 @@ index 354a776..8af3cb7 100644
+} +}
+#endif +#endif
diff --git a/Cython/Utility/Generator.c b/Cython/Utility/Generator.c diff --git a/Cython/Utility/Generator.c b/Cython/Utility/Generator.c
index 0310570..bcd0eb2 100644 index 0310570..70e550c 100644
--- a/Cython/Utility/Generator.c --- a/Cython/Utility/Generator.c
+++ b/Cython/Utility/Generator.c +++ b/Cython/Utility/Generator.c
@@ -43,7 +43,9 @@ static void __Pyx_Generator_Replace_StopIteration(void) { @@ -43,7 +43,9 @@ static void __Pyx_Generator_Replace_StopIteration(void) {
...@@ -66,17 +109,30 @@ index 0310570..bcd0eb2 100644 ...@@ -66,17 +109,30 @@ index 0310570..bcd0eb2 100644
typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *); typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
@@ -487,7 +489,8 @@ static void __Pyx_Generator_dealloc(PyObject *self) { @@ -473,6 +475,9 @@ static int __Pyx_Generator_clear(PyObject *self) {
return 0;
}
+// Pyston change: add forward decl
+static void __Pyx_Generator_del(PyObject *self);
+
static void __Pyx_Generator_dealloc(PyObject *self) {
__pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
@@ -486,8 +491,10 @@ static void __Pyx_Generator_dealloc(PyObject *self) {
#if PY_VERSION_HEX >= 0x030400a1
if (PyObject_CallFinalizerFromDealloc(self)) if (PyObject_CallFinalizerFromDealloc(self))
#else #else
Py_TYPE(gen)->tp_del(self); - Py_TYPE(gen)->tp_del(self);
- if (self->ob_refcnt > 0) - if (self->ob_refcnt > 0)
+ // Pyston change: + // Pyston change: call __Pyx_Generator_del directly and assume obj resurrected
+ // Py_TYPE(gen)->tp_del(self);
+ // if (self->ob_refcnt > 0) + // if (self->ob_refcnt > 0)
+ __Pyx_Generator_del(self);
#endif #endif
{ {
// resurrected. :( // resurrected. :(
@@ -509,9 +512,10 @@ static void __Pyx_Generator_del(PyObject *self) { @@ -509,9 +516,10 @@ static void __Pyx_Generator_del(PyObject *self) {
return ; return ;
#if PY_VERSION_HEX < 0x030400a1 #if PY_VERSION_HEX < 0x030400a1
...@@ -90,7 +146,7 @@ index 0310570..bcd0eb2 100644 ...@@ -90,7 +146,7 @@ index 0310570..bcd0eb2 100644
#endif #endif
// Save the current exception, if any. // Save the current exception, if any.
@@ -530,18 +534,25 @@ static void __Pyx_Generator_del(PyObject *self) { @@ -530,18 +538,25 @@ static void __Pyx_Generator_del(PyObject *self) {
#if PY_VERSION_HEX < 0x030400a1 #if PY_VERSION_HEX < 0x030400a1
// Undo the temporary resurrection; can't use DECREF here, it would // Undo the temporary resurrection; can't use DECREF here, it would
// cause a recursive call. // cause a recursive call.
...@@ -121,5 +177,17 @@ index 0310570..bcd0eb2 100644 ...@@ -121,5 +177,17 @@ index 0310570..bcd0eb2 100644
} }
#if CYTHON_COMPILING_IN_CPYTHON #if CYTHON_COMPILING_IN_CPYTHON
assert(PyType_IS_GC(self->ob_type) && assert(PyType_IS_GC(self->ob_type) &&
@@ -692,7 +707,9 @@ static PyTypeObject __pyx_GeneratorType_type = {
#if PY_VERSION_HEX >= 0x030400a1
0, /*tp_del*/
#else
- __Pyx_Generator_del, /*tp_del*/
+ // Pyston change: we don't currently support types which set a tp_dealloc and tp_del
+ // __Pyx_Generator_del, /*tp_del*/
+ 0,
#endif
0, /*tp_version_tag*/
#if PY_VERSION_HEX >= 0x030400a1
-- --
2.1.4 1.9.1
...@@ -65,6 +65,10 @@ class C(object): ...@@ -65,6 +65,10 @@ class C(object):
def __init__(self): def __init__(self):
self.a = 1 self.a = 1
print vars(C()).items() print vars(C()).items()
try:
print vars(42)
except TypeError, e:
print e
print globals().get("not a real variable") print globals().get("not a real variable")
print globals().get("not a real variable", 1) print globals().get("not a real variable", 1)
......
...@@ -53,3 +53,22 @@ print os.renames.__globals__ == globals() ...@@ -53,3 +53,22 @@ print os.renames.__globals__ == globals()
d = {} d = {}
exec "def foo(): pass" in d exec "def foo(): pass" in d
print d["foo"].func_globals == d print d["foo"].func_globals == d
func_without_defaults.func_code = func_with_defaults.func_code
print func_without_defaults.func_name, func_without_defaults.func_code.co_name
try:
func_without_defaults(2)
except TypeError, e:
print e
func_without_defaults(2, 3)
def foo():
return 0
def bar():
return 1
s = 0
for i in xrange(1000):
s += foo()
if not i % 100:
foo.func_code, bar.func_code = bar.func_code, foo.func_code
print s
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