Commit 0d1017f8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Centralize the PyType code into a new typeobject.cpp

parent 7096bf08
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "capi/typeobject.h"
#include "capi/types.h"
#include "runtime/objmodel.h"
namespace pyston {
// FIXME duplicated with objmodel.cpp
static const std::string _new_str("__new__");
PyObject* Py_CallPythonNew(PyTypeObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
// TODO: runtime ICs?
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCall(new_attr, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
abort();
}
}
PyObject* Py_CallPythonCall(PyObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
// TODO: runtime ICs?
return runtimeCall(self, ArgPassSpec(0, 0, true, true), args, kwds, NULL, NULL, NULL);
} catch (Box* e) {
abort();
}
}
bool update_slot(BoxedClass* self, const std::string& attr) {
if (attr == "__new__") {
self->tp_new = &Py_CallPythonNew;
// TODO update subclasses
return true;
}
if (attr == "__call__") {
self->tp_call = &Py_CallPythonCall;
// TODO update subclasses
return true;
}
return false;
}
void fixup_slot_dispatchers(BoxedClass* self) {
// This will probably share a lot in common with Py_TypeReady:
if (!self->tp_new) {
self->tp_new = &Py_CallPythonNew;
} else if (self->tp_new != Py_CallPythonNew) {
ASSERT(0, "need to set __new__?");
}
if (!self->tp_call) {
self->tp_call = &Py_CallPythonCall;
} else if (self->tp_call != Py_CallPythonCall) {
ASSERT(0, "need to set __call__?");
}
}
} // namespace pyston
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CAPI_TYPEOBJECT_H
#define PYSTON_CAPI_TYPEOBJECT_H
#include "runtime/types.h"
namespace pyston {
bool update_slot(BoxedClass* self, const std::string& attr);
void fixup_slot_dispatchers(BoxedClass* self);
}
#endif
...@@ -192,6 +192,17 @@ PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds) { ...@@ -192,6 +192,17 @@ PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds) {
return self->tp_new(subtype, new_args, kwds); return self->tp_new(subtype, new_args, kwds);
} }
static void add_operators(PyTypeObject* cls) {
if (cls->tp_new) {
cls->giveAttr("__new__",
new BoxedCApiFunction(METH_VARARGS | METH_KEYWORDS, cls, "__new__", (PyCFunction)tp_new_wrapper));
}
if (cls->tp_call) {
cls->giveAttr("__call__", new BoxedWrapperDescriptor(&call_wrapper, cls));
}
}
extern "C" int PyType_Ready(PyTypeObject* cls) { extern "C" int PyType_Ready(PyTypeObject* cls) {
gc::registerNonheapRootObject(cls); gc::registerNonheapRootObject(cls);
...@@ -255,19 +266,12 @@ extern "C" int PyType_Ready(PyTypeObject* cls) { ...@@ -255,19 +266,12 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
if (!cls->tp_new && base != object_cls) if (!cls->tp_new && base != object_cls)
cls->tp_new = base->tp_new; cls->tp_new = base->tp_new;
if (cls->tp_new) {
cls->giveAttr("__new__",
new BoxedCApiFunction(METH_VARARGS | METH_KEYWORDS, cls, "__new__", (PyCFunction)tp_new_wrapper));
}
if (cls->tp_call) {
cls->giveAttr("__call__", new BoxedWrapperDescriptor(&call_wrapper, cls));
}
if (!cls->tp_alloc) { if (!cls->tp_alloc) {
cls->tp_alloc = reinterpret_cast<decltype(cls->tp_alloc)>(PyType_GenericAlloc); cls->tp_alloc = reinterpret_cast<decltype(cls->tp_alloc)>(PyType_GenericAlloc);
} }
add_operators(cls);
for (PyMethodDef* method = cls->tp_methods; method && method->ml_name; ++method) { for (PyMethodDef* method = cls->tp_methods; method && method->ml_name; ++method) {
cls->giveAttr(method->ml_name, new BoxedMethodDescriptor(method, cls)); cls->giveAttr(method->ml_name, new BoxedMethodDescriptor(method, cls));
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "asm_writing/icinfo.h" #include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h" #include "asm_writing/rewriter.h"
#include "capi/typeobject.h"
#include "codegen/ast_interpreter.h" #include "codegen/ast_interpreter.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
...@@ -332,45 +333,11 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) { ...@@ -332,45 +333,11 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) {
return &elts[0]; return &elts[0];
} }
PyObject* Py_CallPythonNew(PyTypeObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCallInternal(new_attr, NULL, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
abort();
}
}
PyObject* Py_CallPythonCall(PyObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
return runtimeCallInternal(self, NULL, ArgPassSpec(0, 0, true, true), args, kwds, NULL, NULL, NULL);
} catch (Box* e) {
abort();
}
}
void BoxedClass::freeze() { void BoxedClass::freeze() {
assert(!is_constant); assert(!is_constant);
assert(getattr("__name__")); // otherwise debugging will be very hard assert(getattr("__name__")); // otherwise debugging will be very hard
// This will probably share a lot in common with Py_TypeReady: fixup_slot_dispatchers(this);
if (!tp_new) {
this->tp_new = &Py_CallPythonNew;
} else if (tp_new != Py_CallPythonNew) {
ASSERT(0, "need to set __new__?");
}
if (!tp_call) {
this->tp_call = &Py_CallPythonCall;
} else if (tp_call != Py_CallPythonCall) {
ASSERT(0, "need to set __call__?");
}
is_constant = true; is_constant = true;
} }
...@@ -1485,21 +1452,11 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite ...@@ -1485,21 +1452,11 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite
if (attr == "__base__" && self->getattr("__base__")) if (attr == "__base__" && self->getattr("__base__"))
raiseExcHelper(TypeError, "readonly attribute"); raiseExcHelper(TypeError, "readonly attribute");
if (attr == "__new__") { bool touched_slot = update_slot(self, attr);
self->tp_new = &Py_CallPythonNew; if (touched_slot)
// TODO update subclasses
rewrite_args = NULL; rewrite_args = NULL;
} }
if (attr == "__call__") {
self->tp_call = &Py_CallPythonCall;
// TODO update subclasses
rewrite_args = NULL;
}
}
Box* _set_ = NULL; Box* _set_ = NULL;
RewriterVar* r_set = NULL; RewriterVar* r_set = NULL;
if (descr) { if (descr) {
......
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