Commit 2d2406d5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #633 from kmod/cleanup

Some capi/descr code cleanup
parents df9ec460 15928944
......@@ -28,7 +28,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
asm_writing/rewriter.cpp
capi/abstract.cpp
capi/codecs.cpp
capi/descrobject.cpp
capi/errors.cpp
capi/modsupport.cpp
capi/object.cpp
......
......@@ -1416,6 +1416,77 @@ Fail:
return NULL;
}
extern "C" PyObject* PySequence_Repeat(PyObject* o, Py_ssize_t count) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_InPlaceConcat(PyObject* o1, PyObject* o2) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_InPlaceRepeat(PyObject* o, Py_ssize_t count) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept {
try {
// Not sure if this is really the same:
return getitem(o, boxInt(i));
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PySequence_GetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2) noexcept {
try {
// Not sure if this is really the same:
return getitem(o, createSlice(boxInt(i1), boxInt(i2), None));
} catch (ExcInfo e) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
}
extern "C" int PySequence_SetItem(PyObject* o, Py_ssize_t i, PyObject* v) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" int PySequence_DelItem(PyObject* o, Py_ssize_t i) noexcept {
try {
// Not sure if this is really the same:
delitem(o, boxInt(i));
return 0;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
extern "C" int PySequence_SetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2, PyObject* v) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" int PySequence_DelSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" Py_ssize_t PySequence_Count(PyObject* o, PyObject* value) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" PyObject* PyObject_CallFunction(PyObject* callable, const char* format, ...) noexcept {
va_list va;
PyObject* args;
......
// Copyright (c) 2014-2015 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/types.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
namespace pyston {
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10);
BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
assert(self->cls == method_cls);
assert(varargs->cls == tuple_cls);
assert(kwargs->cls == dict_cls);
int ml_flags = self->method->ml_flags;
int call_flags;
if (ml_flags & METH_CLASS) {
if (!isSubclass(obj->cls, type_cls))
raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name,
getFullTypeName(obj).c_str());
call_flags = ml_flags & (~METH_CLASS);
} else {
if (!isSubclass(obj->cls, self->type))
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' object but received a '%s'",
self->method->ml_name, getFullNameOfClass(self->type).c_str(), getFullTypeName(obj).c_str());
call_flags = ml_flags;
}
threading::GLPromoteRegion _gil_lock;
Box* rtn;
if (call_flags == METH_NOARGS) {
RELEASE_ASSERT(varargs->size() == 0, "");
RELEASE_ASSERT(kwargs->d.size() == 0, "");
rtn = (Box*)self->method->ml_meth(obj, NULL);
} else if (call_flags == METH_VARARGS) {
RELEASE_ASSERT(kwargs->d.size() == 0, "");
rtn = (Box*)self->method->ml_meth(obj, varargs);
} else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) {
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs);
} else if (call_flags == METH_O) {
RELEASE_ASSERT(kwargs->d.size() == 0, "");
RELEASE_ASSERT(varargs->size() == 1, "");
rtn = (Box*)self->method->ml_meth(obj, varargs->elts[0]);
} else {
RELEASE_ASSERT(0, "0x%x", call_flags);
}
checkAndThrowCAPIException();
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
Box* BoxedMethodDescriptor::callInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
// TODO: could also handle cases where we have starargs but no positional args,
// and similarly for kwargs but no keywords
if (!rewrite_args || argspec.has_kwargs || argspec.has_starargs || argspec.num_keywords > 0 || argspec.num_args > 4)
return callFunc(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
assert(argspec.num_args >= 2);
int passed_varargs = argspec.num_args - 2;
assert(arg1->cls == method_cls);
BoxedMethodDescriptor* self = static_cast<BoxedMethodDescriptor*>(arg1);
Box* obj = arg2;
RewriterVar* r_obj = rewrite_args->arg2;
// We could also guard on the fields of the method object, but lets just guard on the object itself
// for now.
// TODO: what if it gets GC'd?
rewrite_args->arg1->addGuard((intptr_t)self);
int ml_flags = self->method->ml_flags;
RELEASE_ASSERT((ml_flags & METH_CLASS) == 0, "unimplemented");
if (!isSubclass(obj->cls, self->type))
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' object but received a '%s'", self->method->ml_name,
getFullNameOfClass(self->type).c_str(), getFullTypeName(obj).c_str());
r_obj->addAttrGuard(offsetof(Box, cls), (intptr_t)obj->cls);
int call_flags = ml_flags;
Box* rtn;
RewriterVar* r_rtn;
if (call_flags == METH_NOARGS) {
RELEASE_ASSERT(passed_varargs == 0, "");
rtn = (Box*)(self->method->ml_meth)(obj, NULL);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj,
rewrite_args->rewriter->loadConst(0, Location::forArg(1)));
} else if (call_flags & METH_VARARGS) {
RELEASE_ASSERT(call_flags == METH_VARARGS || call_flags == (METH_VARARGS | METH_KEYWORDS), "");
Box* varargs;
RewriterVar* r_varargs;
if (passed_varargs == 0) {
varargs = EmptyTuple;
r_varargs = rewrite_args->rewriter->loadConst((intptr_t)EmptyTuple, Location::forArg(1));
} else if (passed_varargs == 1) {
varargs = BoxedTuple::create1(arg3);
r_varargs = rewrite_args->rewriter->call(false, (void*)BoxedTuple::create1, rewrite_args->arg3);
} else if (passed_varargs == 2) {
varargs = BoxedTuple::create2(arg3, args[0]);
r_varargs = rewrite_args->rewriter->call(false, (void*)BoxedTuple::create2, rewrite_args->arg3,
rewrite_args->args->getAttr(0, Location::forArg(1)));
} else {
RELEASE_ASSERT(0, "");
}
if (call_flags & METH_KEYWORDS) {
Box* kwargs = NULL;
RewriterVar* r_kwargs = rewrite_args->rewriter->loadConst(0);
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, r_varargs, r_kwargs);
} else {
rtn = (Box*)(self->method->ml_meth)(obj, varargs);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, r_varargs);
}
} else if (call_flags == METH_O) {
RELEASE_ASSERT(passed_varargs == 1, "");
rtn = (Box*)(self->method->ml_meth)(obj, arg3);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, rewrite_args->arg3);
} else {
RELEASE_ASSERT(0, "0x%x", call_flags);
}
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->out_rtn = r_rtn;
rewrite_args->out_success = true;
return rtn;
}
}
......@@ -21,7 +21,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/dict.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -15,7 +15,6 @@
#ifndef PYSTON_CAPI_TYPES_H
#define PYSTON_CAPI_TYPES_H
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -24,18 +23,6 @@ namespace pyston {
typedef PyObject* (*wrapperfunc)(PyObject* self, PyObject* args, void* wrapped);
typedef PyObject* (*wrapperfunc_kwds)(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds);
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;
// exists in CPython: PyObject *name_strobj
};
extern "C" BoxedClass* capifunc_cls, *wrapperdescr_cls, *wrapperobject_cls;
class BoxedCApiFunction : public Box {
public:
PyMethodDef* method_def;
......@@ -132,114 +119,6 @@ static_assert(offsetof(BoxedCApiFunction, method_def) == offsetof(PyCFunctionObj
static_assert(offsetof(BoxedCApiFunction, passthrough) == offsetof(PyCFunctionObject, m_self), "");
static_assert(offsetof(BoxedCApiFunction, module) == offsetof(PyCFunctionObject, m_module), "");
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) {}
DEFAULT_CLASS(wrapperdescr_cls);
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == wrapperdescr_cls);
BoxedWrapperDescriptor* o = static_cast<BoxedWrapperDescriptor*>(_o);
boxGCHandler(v, o);
v->visit(o->type);
}
};
class BoxedWrapperObject : public Box {
public:
BoxedWrapperDescriptor* descr;
Box* obj;
BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : descr(descr), obj(obj) {}
DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) {
STAT_TIMER(t0, "us_timer_boxedwrapperobject__call__", (self->cls->is_user_defined ? 1 : 2));
assert(self->cls == wrapperobject_cls);
assert(args->cls == tuple_cls);
assert(kwds->cls == dict_cls);
int flags = self->descr->wrapper->flags;
wrapperfunc wrapper = self->descr->wrapper->wrapper;
assert(self->descr->wrapper->offset > 0);
Box* rtn;
if (flags == PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
rtn = (*wk)(self->obj, args, self->descr->wrapped, kwds);
} else if (flags == PyWrapperFlag_PYSTON || flags == 0) {
rtn = (*wrapper)(self->obj, args, self->descr->wrapped);
} else {
RELEASE_ASSERT(0, "%d", flags);
}
checkAndThrowCAPIException();
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == wrapperobject_cls);
BoxedWrapperObject* o = static_cast<BoxedWrapperObject*>(_o);
boxGCHandler(v, o);
v->visit(o->obj);
}
};
class BoxedMethodDescriptor : public Box {
public:
PyMethodDef* method;
BoxedClass* type;
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) {}
DEFAULT_CLASS(method_cls);
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == method_cls, "");
// CPython handles this differently: they create the equivalent of different BoxedMethodDescriptor
// objects but with different class objects, which define different __get__ and __call__ methods.
if (self->method->ml_flags & METH_CLASS)
return boxInstanceMethod(owner, self, self->type);
if (self->method->ml_flags & METH_STATIC)
Py_FatalError("unimplemented");
if (self->method->ml_flags & METH_COEXIST)
Py_FatalError("unimplemented");
if (inst == None)
return self;
else
return boxInstanceMethod(inst, self, self->type);
}
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
static Box* callInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == method_cls);
BoxedMethodDescriptor* o = static_cast<BoxedMethodDescriptor*>(_o);
boxGCHandler(v, o);
v->visit(o->type);
}
};
PyObject* convert_3way_to_object(int op, int c) noexcept;
int default_3way_compare(PyObject* v, PyObject* w);
......
......@@ -34,7 +34,6 @@
#include "core/stats.h"
#include "core/thread_utils.h"
#include "core/util.h"
#include "runtime/capi.h"
#include "runtime/generator.h"
#include "runtime/import.h"
#include "runtime/inline/boxing.h"
......
......@@ -38,7 +38,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "core/util.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -33,7 +33,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -27,7 +27,6 @@
#include "core/ast.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/file.h"
#include "runtime/ics.h"
......
......@@ -21,7 +21,6 @@
#include "capi/typeobject.h"
#include "core/threading.h"
#include "core/types.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
......@@ -53,47 +52,6 @@ extern "C" {
int Py_Py3kWarningFlag;
BoxedClass* capifunc_cls;
BoxedClass* wrapperdescr_cls, *wrapperobject_cls;
}
Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == wrapperdescr_cls, "");
if (inst == None)
return self;
if (!isSubclass(inst->cls, self->type))
raiseExcHelper(TypeError, "Descriptor '' for '%s' objects doesn't apply to '%s' object",
getFullNameOfClass(self->type).c_str(), getFullTypeName(inst).c_str());
return new BoxedWrapperObject(self, inst);
}
Box* BoxedWrapperDescriptor::descr_get(Box* _self, Box* inst, Box* owner) noexcept {
RELEASE_ASSERT(_self->cls == wrapperdescr_cls, "");
BoxedWrapperDescriptor* self = static_cast<BoxedWrapperDescriptor*>(_self);
if (inst == None)
return self;
if (!isSubclass(inst->cls, self->type))
PyErr_Format(TypeError, "Descriptor '' for '%s' objects doesn't apply to '%s' object",
getFullNameOfClass(self->type).c_str(), getFullTypeName(inst).c_str());
return new BoxedWrapperObject(self, inst);
}
Box* BoxedWrapperDescriptor::__call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args) {
RELEASE_ASSERT(descr->cls == wrapperdescr_cls, "");
BoxedDict* kw = static_cast<BoxedDict*>(_args[0]);
if (!isSubclass(self->cls, descr->type))
raiseExcHelper(TypeError, "descriptor '' requires a '%s' object but received a '%s'",
getFullNameOfClass(descr->type).c_str(), getFullTypeName(self).c_str());
auto wrapper = new BoxedWrapperObject(descr, self);
return BoxedWrapperObject::__call__(wrapper, args, kw);
}
extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) noexcept {
......@@ -675,77 +633,6 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept {
return internal_print(obj, fp, flags, 0);
};
extern "C" PyObject* PySequence_Repeat(PyObject* o, Py_ssize_t count) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_InPlaceConcat(PyObject* o1, PyObject* o2) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_InPlaceRepeat(PyObject* o, Py_ssize_t count) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept {
try {
// Not sure if this is really the same:
return getitem(o, boxInt(i));
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PySequence_GetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2) noexcept {
try {
// Not sure if this is really the same:
return getitem(o, createSlice(boxInt(i1), boxInt(i2), None));
} catch (ExcInfo e) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
}
extern "C" int PySequence_SetItem(PyObject* o, Py_ssize_t i, PyObject* v) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" int PySequence_DelItem(PyObject* o, Py_ssize_t i) noexcept {
try {
// Not sure if this is really the same:
delitem(o, boxInt(i));
return 0;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
extern "C" int PySequence_SetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2, PyObject* v) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" int PySequence_DelSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" Py_ssize_t PySequence_Count(PyObject* o, PyObject* value) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
}
extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
try {
Box* hasnext = iter->hasnextOrNullIC();
......@@ -1570,56 +1457,6 @@ extern "C" char* PyModule_GetFilename(PyObject* m) noexcept {
return PyString_AsString(fileobj);
}
BoxedModule* importCExtension(const std::string& full_name, const std::string& last_name, const std::string& path) {
void* handle = dlopen(path.c_str(), RTLD_NOW);
if (!handle) {
// raiseExcHelper(ImportError, "%s", dlerror());
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
assert(handle);
std::string initname = "init" + last_name;
void (*init)() = (void (*)())dlsym(handle, initname.c_str());
char* error;
if ((error = dlerror()) != NULL) {
// raiseExcHelper(ImportError, "%s", error);
fprintf(stderr, "%s\n", error);
exit(1);
}
assert(init);
// Let the GC know about the static variables.
uintptr_t bss_start = (uintptr_t)dlsym(handle, "__bss_start");
uintptr_t bss_end = (uintptr_t)dlsym(handle, "_end");
RELEASE_ASSERT(bss_end - bss_start < 100000, "Large BSS section detected - there maybe something wrong");
// only track void* aligned memory
bss_start = (bss_start + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1);
bss_end -= bss_end % sizeof(void*);
gc::registerPotentialRootRange((void*)bss_start, (void*)bss_end);
char* packagecontext = strdup(full_name.c_str());
char* oldcontext = _Py_PackageContext;
_Py_PackageContext = packagecontext;
(*init)();
_Py_PackageContext = oldcontext;
free(packagecontext);
checkAndThrowCAPIException();
BoxedDict* sys_modules = getSysModulesDict();
Box* s = boxString(full_name);
Box* _m = sys_modules->d[s];
RELEASE_ASSERT(_m, "dynamic module not initialized properly");
assert(_m->cls == module_cls);
BoxedModule* m = static_cast<BoxedModule*>(_m);
m->setattr("__file__", boxString(path), NULL);
return m;
}
Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
......@@ -1645,21 +1482,6 @@ Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* r
return r;
}
static Box* methodGetDoc(Box* b, void*) {
assert(b->cls == method_cls);
const char* s = static_cast<BoxedMethodDescriptor*>(b)->method->ml_doc;
if (s)
return boxString(s);
return None;
}
static Box* wrapperdescrGetDoc(Box* b, void*) {
assert(b->cls == wrapperdescr_cls);
auto s = static_cast<BoxedWrapperDescriptor*>(b)->wrapper->doc;
assert(s.size());
return boxString(s);
}
/* extension modules might be compiled with GC support so these
functions must always be available */
......@@ -1719,10 +1541,6 @@ extern "C" void _Py_FatalError(const char* fmt, const char* function, const char
abort();
}
extern "C" PyObject* PyClassMethod_New(PyObject* callable) noexcept {
return new BoxedClassmethod(callable);
}
void setupCAPI() {
capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
......@@ -1736,27 +1554,6 @@ void setupCAPI() {
"__module__", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedCApiFunction, module)));
capifunc_cls->freeze();
method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true);
method_call_cl->internal_callable = BoxedMethodDescriptor::callInternal;
method_cls->giveAttr("__call__", new BoxedFunction(method_call_cl));
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze();
wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__call__,
UNKNOWN, 2, 0, true, true)));
wrapperdescr_cls->giveAttr("__doc__",
new (pyston_getset_cls) BoxedGetsetDescriptor(wrapperdescrGetDoc, NULL, NULL));
wrapperdescr_cls->freeze();
wrapperdescr_cls->tp_descr_get = BoxedWrapperDescriptor::descr_get;
wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->freeze();
}
void teardownCAPI() {
......
// Copyright (c) 2014-2015 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_RUNTIME_CAPI_H
#define PYSTON_RUNTIME_CAPI_H
#include <string>
namespace pyston {
class Box;
class BoxedModule;
BoxedModule* importCExtension(const std::string& full_name, const std::string& last_name, const std::string& path);
void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
struct ExcInfo;
void setCAPIException(const ExcInfo& e);
#define fatalOrError(exception, message) \
do { \
if (CONTINUE_AFTER_FATAL) \
PyErr_SetString((exception), (message)); \
else \
Py_FatalError((message)); \
} while (0)
}
#endif
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include "runtime/import.h"
#include <dlfcn.h>
#include <limits.h>
#include "llvm/Support/FileSystem.h"
......@@ -23,7 +24,6 @@
#include "codegen/parser.h"
#include "codegen/unwinding.h"
#include "core/ast.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
namespace pyston {
......@@ -777,6 +777,56 @@ Box* impLoadDynamic(Box* _name, Box* _pathname, Box* _file) {
return importCExtension(name->s(), shortname, pathname->s());
}
BoxedModule* importCExtension(const std::string& full_name, const std::string& last_name, const std::string& path) {
void* handle = dlopen(path.c_str(), RTLD_NOW);
if (!handle) {
// raiseExcHelper(ImportError, "%s", dlerror());
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
assert(handle);
std::string initname = "init" + last_name;
void (*init)() = (void (*)())dlsym(handle, initname.c_str());
char* error;
if ((error = dlerror()) != NULL) {
// raiseExcHelper(ImportError, "%s", error);
fprintf(stderr, "%s\n", error);
exit(1);
}
assert(init);
// Let the GC know about the static variables.
uintptr_t bss_start = (uintptr_t)dlsym(handle, "__bss_start");
uintptr_t bss_end = (uintptr_t)dlsym(handle, "_end");
RELEASE_ASSERT(bss_end - bss_start < 100000, "Large BSS section detected - there maybe something wrong");
// only track void* aligned memory
bss_start = (bss_start + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1);
bss_end -= bss_end % sizeof(void*);
gc::registerPotentialRootRange((void*)bss_start, (void*)bss_end);
char* packagecontext = strdup(full_name.c_str());
char* oldcontext = _Py_PackageContext;
_Py_PackageContext = packagecontext;
(*init)();
_Py_PackageContext = oldcontext;
free(packagecontext);
checkAndThrowCAPIException();
BoxedDict* sys_modules = getSysModulesDict();
Box* s = boxString(full_name);
Box* _m = sys_modules->d[s];
RELEASE_ASSERT(_m, "dynamic module not initialized properly");
assert(_m->cls == module_cls);
BoxedModule* m = static_cast<BoxedModule*>(_m);
m->setattr("__file__", boxString(path), NULL);
return m;
}
Box* impGetSuffixes() {
BoxedList* list = new BoxedList;
// For now only add *.py
......
......@@ -21,6 +21,7 @@ namespace pyston {
extern "C" Box* import(int level, Box* from_imports, llvm::StringRef module_name);
extern Box* importModuleLevel(llvm::StringRef module_name, Box* globals, Box* from_imports, int level);
BoxedModule* importCExtension(const std::string& full_name, const std::string& last_name, const std::string& path);
}
#endif
......@@ -13,7 +13,6 @@
// limitations under the License.
#include "core/types.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -24,7 +24,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/float.h"
#include "runtime/inline/boxing.h"
#include "runtime/long.h"
......
......@@ -27,7 +27,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/inline/boxing.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -39,7 +39,6 @@
#include "core/types.h"
#include "gc/collector.h"
#include "gc/heap.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/dict.h"
#include "runtime/file.h"
......
......@@ -17,7 +17,6 @@
#include <llvm/Support/raw_ostream.h>
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
namespace pyston {
......
......@@ -29,7 +29,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/dict.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
......
......@@ -24,7 +24,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
......
......@@ -32,7 +32,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/complex.h"
#include "runtime/dict.h"
......
......@@ -88,7 +88,8 @@ extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_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;
*capi_getset_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls, *frame_cls, *capifunc_cls,
*wrapperdescr_cls, *wrapperobject_cls;
}
#define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type)
......@@ -869,6 +870,62 @@ 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;
// exists in CPython: PyObject *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) {}
DEFAULT_CLASS(wrapperdescr_cls);
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
static void gcHandler(GCVisitor* v, Box* _o);
};
class BoxedWrapperObject : public Box {
public:
BoxedWrapperDescriptor* descr;
Box* obj;
BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : descr(descr), obj(obj) {}
DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds);
static void gcHandler(GCVisitor* v, Box* _o);
};
class BoxedMethodDescriptor : public Box {
public:
PyMethodDef* method;
BoxedClass* type;
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) {}
DEFAULT_CLASS(method_cls);
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner);
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
static Box* callInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
static void gcHandler(GCVisitor* v, Box* _o);
};
extern "C" void boxGCHandler(GCVisitor* v, Box* b);
Box* objectNewNoArgs(BoxedClass* cls);
......@@ -905,6 +962,19 @@ AST* unboxAst(Box* b);
// Our default for tp_alloc:
extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept;
void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
struct ExcInfo;
void setCAPIException(const ExcInfo& e);
#define fatalOrError(exception, message) \
do { \
if (CONTINUE_AFTER_FATAL) \
PyErr_SetString((exception), (message)); \
else \
Py_FatalError((message)); \
} while (0)
// A descriptor that you can add to your class to provide instances with a __dict__ accessor.
// Classes created in Python get this automatically, but builtin types (including extension types)
// are supposed to add one themselves. type_cls and function_cls do this, for example.
......
......@@ -15,7 +15,6 @@
#include "runtime/util.h"
#include "core/options.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
import weakref
import gc
num_destroyed = 0
def cb(wr):
print "object was destroyed", wr()
global num_destroyed
num_destroyed += 1
def doStuff():
def meth():
......@@ -11,18 +13,7 @@ def doStuff():
wr = weakref.ref(meth, cb)
return wr
def fact(n):
if n <= 1:
return n
return n * fact(n-1)
w = doStuff()
fact(10) # try to clear some memory
def recurse(f, n):
if n:
return recurse(f, n - 1)
return f()
recurse(gc.collect, 50)
l = [doStuff() for i in xrange(5)]
gc.collect()
assert num_destroyed >= 1
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