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 {
// unhandled fields:
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
| 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;
......
......@@ -82,7 +82,11 @@ extern "C" Box* vars(Box* obj) {
if (!obj)
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) {
......
......@@ -1382,6 +1382,12 @@ extern "C" int PyCFunction_GetFlags(PyObject* op) noexcept {
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 {
if (v != NULL) {
Py_ssize_t x;
......@@ -1491,7 +1497,6 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10);
assert(_self->cls == capifunc_cls);
BoxedCApiFunction* self = static_cast<BoxedCApiFunction*>(_self);
if (rewrite_args) {
......
......@@ -2409,7 +2409,8 @@ public:
static Box* next(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls);
assert(hasnextUnboxed(self));
if (!hasnextUnboxed(self))
raiseExcHelper(StopIteration, (const char*)nullptr);
char c = *self->it;
++self->it;
......
......@@ -34,6 +34,7 @@
#include "core/stats.h"
#include "core/types.h"
#include "runtime/classobj.h"
#include "runtime/code.h"
#include "runtime/complex.h"
#include "runtime/dict.h"
#include "runtime/file.h"
......@@ -1684,6 +1685,25 @@ static Box* functionCode(Box* self, void*) {
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*) {
assert(self->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(self);
......@@ -3867,7 +3887,8 @@ void setupRuntime() {
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("__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("func_name", function_cls->getattr(internStringMortal("__name__")));
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>
Date: Tue, 9 Jun 2015 19:26:44 +0200
Subject: [PATCH] Pyston change: we don't support custom traceback entries yet
---
Cython/Compiler/ModuleNode.py | 8 ++++++--
Cython/Utility/Exceptions.c | 7 ++++++-
Cython/Utility/Generator.c | 31 +++++++++++++++++++++----------
3 files changed, 33 insertions(+), 13 deletions(-)
Cython/Compiler/ExprNodes.py | 9 +++++++++
Cython/Compiler/ModuleNode.py | 8 ++++++--
Cython/Utility/CythonFunction.c | 4 +++-
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
index 4785858..699cd15 100644
--- a/Cython/Compiler/ModuleNode.py
......@@ -29,6 +57,21 @@ index 4785858..699cd15 100644
code.putln("PyErr_Restore(etype, eval, etb);")
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
index 354a776..8af3cb7 100644
--- a/Cython/Utility/Exceptions.c
......@@ -52,7 +95,7 @@ index 354a776..8af3cb7 100644
+}
+#endif
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
+++ b/Cython/Utility/Generator.c
@@ -43,7 +43,9 @@ static void __Pyx_Generator_Replace_StopIteration(void) {
......@@ -66,17 +109,30 @@ index 0310570..bcd0eb2 100644
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))
#else
Py_TYPE(gen)->tp_del(self);
- Py_TYPE(gen)->tp_del(self);
- 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)
+ __Pyx_Generator_del(self);
#endif
{
// resurrected. :(
@@ -509,9 +512,10 @@ static void __Pyx_Generator_del(PyObject *self) {
@@ -509,9 +516,10 @@ static void __Pyx_Generator_del(PyObject *self) {
return ;
#if PY_VERSION_HEX < 0x030400a1
......@@ -90,7 +146,7 @@ index 0310570..bcd0eb2 100644
#endif
// 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
// Undo the temporary resurrection; can't use DECREF here, it would
// cause a recursive call.
......@@ -121,5 +177,17 @@ index 0310570..bcd0eb2 100644
}
#if CYTHON_COMPILING_IN_CPYTHON
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):
def __init__(self):
self.a = 1
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", 1)
......
......@@ -53,3 +53,22 @@ print os.renames.__globals__ == globals()
d = {}
exec "def foo(): pass" in 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