Commit 787c7d7c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add a number of C API functions

Working towards getting _sre.c to link (it compiles with the previous include/ additions)
parent de372d48
...@@ -262,20 +262,20 @@ CLANG_CXX := $(CXX_ENV) $(CLANG_CXX) ...@@ -262,20 +262,20 @@ CLANG_CXX := $(CXX_ENV) $(CLANG_CXX)
# Not sure if ccache_basedir actually helps at all (I think the generated files make them different?) # Not sure if ccache_basedir actually helps at all (I think the generated files make them different?)
LLVM_BUILD_ENV += CCACHE_DIR=$(HOME)/.ccache_llvm CCACHE_BASEDIR=$(LLVM_SRC) LLVM_BUILD_ENV += CCACHE_DIR=$(HOME)/.ccache_llvm CCACHE_BASEDIR=$(LLVM_SRC)
MAIN_SRCS := $(wildcard codegen/*.cpp) $(wildcard asm_writing/*.cpp) $(wildcard codegen/irgen/*.cpp) $(wildcard codegen/opt/*.cpp) $(wildcard analysis/*.cpp) $(wildcard core/*.cpp) jit.cpp codegen/profiling/profiling.cpp codegen/profiling/dumprof.cpp $(wildcard runtime/*.cpp) $(wildcard runtime/builtin_modules/*.cpp) $(wildcard gc/*.cpp) MAIN_SRCS := $(wildcard codegen/*.cpp) $(wildcard asm_writing/*.cpp) $(wildcard codegen/irgen/*.cpp) $(wildcard codegen/opt/*.cpp) $(wildcard analysis/*.cpp) $(wildcard core/*.cpp) jit.cpp codegen/profiling/profiling.cpp codegen/profiling/dumprof.cpp $(wildcard runtime/*.cpp) $(wildcard runtime/builtin_modules/*.cpp) $(wildcard gc/*.cpp) $(wildcard capi/*.cpp)
STDLIB_SRCS := $(wildcard runtime/inline/*.cpp) STDLIB_SRCS := $(wildcard runtime/inline/*.cpp)
SRCS := $(MAIN_SRCS) $(STDLIB_SRCS) SRCS := $(MAIN_SRCS) $(STDLIB_SRCS)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o
STDLIB_RELEASE_OBJS := stdlib.release.bc.o STDLIB_RELEASE_OBJS := stdlib.release.bc.o
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c md5.c md5module.c $(EXTRA_STDMODULE_SRCS) STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c md5.c md5module.c $(EXTRA_STDMODULE_SRCS)
STDMODULE_SRCS := $(addprefix ../lib_python/2.7_Modules/,$(STDMODULE_SRCS)) FROM_CPYTHON_SRCS := $(addprefix ../lib_python/2.7_Modules/,$(STDMODULE_SRCS)) $(wildcard capi/*.c)
# The stdlib objects have slightly longer dependency chains, # The stdlib objects have slightly longer dependency chains,
# so put them first in the list: # so put them first in the list:
OBJS := $(STDLIB_OBJS) $(SRCS:.cpp=.o) $(STDMODULE_SRCS:.c=.o) OBJS := $(STDLIB_OBJS) $(SRCS:.cpp=.o) $(FROM_CPYTHON_SRCS:.c=.o)
PROFILE_OBJS := $(STDLIB_RELEASE_OBJS) $(MAIN_SRCS:.cpp=.prof.o) $(STDLIB_SRCS:.cpp=.release.o) $(STDMODULE_SRCS:.c=.release.o) PROFILE_OBJS := $(STDLIB_RELEASE_OBJS) $(MAIN_SRCS:.cpp=.prof.o) $(STDLIB_SRCS:.cpp=.release.o) $(FROM_CPYTHON_SRCS:.c=.release.o)
OPT_OBJS := $(STDLIB_RELEASE_OBJS) $(SRCS:.cpp=.release.o) $(STDMODULE_SRCS:.c=.release.o) OPT_OBJS := $(STDLIB_RELEASE_OBJS) $(SRCS:.cpp=.release.o) $(FROM_CPYTHON_SRCS:.c=.release.o)
OPTIONAL_SRCS := codegen/profiling/oprofile.cpp codegen/profiling/pprof.cpp OPTIONAL_SRCS := codegen/profiling/oprofile.cpp codegen/profiling/pprof.cpp
TOOL_SRCS := $(wildcard $(TOOLS_DIR)/*.cpp) TOOL_SRCS := $(wildcard $(TOOLS_DIR)/*.cpp)
...@@ -881,10 +881,14 @@ ext: ../test/test_extension/test.so ...@@ -881,10 +881,14 @@ ext: ../test/test_extension/test.so
../test/test_extension/test.o: ../test/test_extension/test.c $(wildcard ../include/*.h) $(BUILD_SYSTEM_DEPS) ../test/test_extension/test.o: ../test/test_extension/test.c $(wildcard ../include/*.h) $(BUILD_SYSTEM_DEPS)
$(CLANG_EXE) -O2 -fPIC -Wimplicit -I../include -c $< -o $@ -g $(CLANG_EXE) -O2 -fPIC -Wimplicit -I../include -c $< -o $@ -g
../lib_python/2.7_Modules/%.o: ../lib_python/2.7_Modules/%.c $(BUILD_SYSTEM_DEPS) $(FROM_CPYTHON_SRCS:.c=.o): %.o: %.c $(BUILD_SYSTEM_DEPS)
$(ECHO) Compiling extension file $@ $(ECHO) Compiling C file to $@
$(VERB) $(CC) $(EXT_CFLAGS) -c $< -o $@ -g -MMD -MP -MF $<.d -O0 $(VERB) $(CC) $(EXT_CFLAGS) -c $< -o $@ -g -MMD -MP -MF $<.d -O0
../lib_python/2.7_Modules/%.release.o: ../lib_python/2.7_Modules/%.c $(BUILD_SYSTEM_DEPS) $(FROM_CPYTHON_SRCS:.c=.release.o): %.release.o: %.c $(BUILD_SYSTEM_DEPS)
$(ECHO) Compiling extension file $@ $(ECHO) Compiling C file to $@
$(VERB) $(CC) $(EXT_CFLAGS) -c $< -o $@ -g -MMD -MP -MF $<.d $(VERB) $(CC) $(EXT_CFLAGS) -c $< -o $@ -g -MMD -MP -MF $<.d
# These are necessary until we support unicode:
../lib_python/2.7_Modules/_sre.o: EXT_CFLAGS += -Wno-sometimes-uninitialized
../lib_python/2.7_Modules/_sre.release.o: EXT_CFLAGS += -Wno-sometimes-uninitialized
// 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.
// Hopefully soon we will be able to switch to CPython's getargs.c, instead of having
// to reimplement it. For now, it's easier to create simple versions of the functions
// instead of trying to support all of the internals of getargs.c
#include <dlfcn.h>
#include <stdarg.h>
#include <string.h>
#include "Python.h"
#include "codegen/compvars.h"
#include "core/threading.h"
#include "core/types.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
namespace pyston {
#define FLAG_COMPAT 1
#define FLAG_SIZE_T 2
// This function is named after the CPython one:
static int vgetargs1(PyObject* _tuple, const char* fmt, va_list* ap, int flags) {
RELEASE_ASSERT(_tuple->cls == tuple_cls, "");
BoxedTuple* tuple = static_cast<BoxedTuple*>(_tuple);
bool now_optional = false;
int arg_idx = 0;
int tuple_size = tuple->elts.size();
while (char c = *fmt) {
fmt++;
if (c == ':') {
break;
} else if (c == '|') {
now_optional = true;
continue;
} else {
if (arg_idx >= tuple_size) {
RELEASE_ASSERT(now_optional, "");
break;
}
PyObject* arg = tuple->elts[arg_idx];
switch (c) {
case 's': {
if (*fmt == '*') {
Py_buffer* p = (Py_buffer*)va_arg(*ap, Py_buffer*);
RELEASE_ASSERT(arg->cls == str_cls, "");
PyBuffer_FillInfo(p, arg, PyString_AS_STRING(arg), PyString_GET_SIZE(arg), 1, 0);
fmt++;
} else if (*fmt == ':') {
break;
} else {
RELEASE_ASSERT(0, "");
}
break;
}
case 'O': {
PyObject** p = (PyObject**)va_arg(*ap, PyObject**);
*p = arg;
break;
}
default:
RELEASE_ASSERT(0, "Unhandled format character: '%c'", c);
}
}
}
return 1;
}
extern "C" int PyArg_VaParse(PyObject* _tuple, const char* fmt, va_list ap) {
va_list lva;
__va_copy(lva, ap);
return vgetargs1(_tuple, fmt, &lva, 0);
}
extern "C" int PyArg_ParseTuple(PyObject* _tuple, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
int r = vgetargs1(_tuple, fmt, &ap, 0);
va_end(ap);
return r;
}
extern "C" int _PyArg_ParseTuple_SizeT(PyObject* args, char* format, ...) {
int retval;
va_list va;
va_start(va, format);
retval = vgetargs1(args, format, &va, FLAG_SIZE_T);
va_end(va);
return retval;
}
extern "C" int PyArg_ParseTupleAndKeywords(PyObject* args, PyObject* kwargs, const char* format, char** kwlist, ...) {
assert(kwargs->cls == dict_cls);
RELEASE_ASSERT(static_cast<BoxedDict*>(kwargs)->d.size() == 0, "");
va_list ap;
va_start(ap, kwlist);
int r = vgetargs1(args, format, &ap, 0);
va_end(ap);
return r;
}
extern "C" int _PyArg_ParseTupleAndKeywords_SizeT(PyObject* args, PyObject* keywords, const char* format, char** kwlist,
...) {
if ((args == NULL || !PyTuple_Check(args)) || (keywords != NULL && !PyDict_Check(keywords)) || format == NULL
|| kwlist == NULL) {
PyErr_BadInternalCall();
return 0;
}
assert(keywords->cls == dict_cls);
RELEASE_ASSERT(static_cast<BoxedDict*>(keywords)->d.size() == 0, "");
va_list ap;
va_start(ap, kwlist);
int r = vgetargs1(args, format, &ap, FLAG_SIZE_T);
va_end(ap);
return r;
}
extern "C" int PyArg_UnpackTuple(PyObject* args, const char* name, Py_ssize_t min, Py_ssize_t max, ...) {
RELEASE_ASSERT(args->cls == tuple_cls, "");
BoxedTuple* t = static_cast<BoxedTuple*>(args);
RELEASE_ASSERT(min <= t->elts.size() && t->elts.size() <= max, "");
va_list ap;
va_start(ap, max);
for (auto e : t->elts) {
PyObject** p = (PyObject**)va_arg(ap, PyObject**);
*p = e;
}
va_end(ap);
return true;
}
} // namespace pyston
...@@ -376,13 +376,23 @@ public: ...@@ -376,13 +376,23 @@ public:
Box* getattr(const std::string& attr) { return getattr(attr, NULL); } Box* getattr(const std::string& attr) { return getattr(attr, NULL); }
void delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args); void delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args);
}; };
static_assert(offsetof(Box, cls) == offsetof(struct _object, ob_type), "");
// CPython C API compatibility class:
class BoxVar : public Box {
public:
Py_ssize_t ob_size;
BoxVar(BoxedClass* cls, Py_ssize_t ob_size) : Box(cls), ob_size(ob_size) {}
};
static_assert(offsetof(BoxVar, ob_size) == offsetof(struct _varobject, ob_size), "");
extern "C" const std::string* getTypeName(Box* o); extern "C" const std::string* getTypeName(Box* o);
class BoxedClass : public Box { class BoxedClass : public BoxVar {
public: public:
Py_ssize_t ob_size; // CPython API compatibility
PyTypeObject_BODY; PyTypeObject_BODY;
HCAttrs attrs; HCAttrs attrs;
......
...@@ -395,9 +395,11 @@ BoxedClass* notimplemented_cls; ...@@ -395,9 +395,11 @@ BoxedClass* notimplemented_cls;
BoxedModule* builtins_module; BoxedModule* builtins_module;
// TODO looks like CPython and pypy put this into an "exceptions" module: // TODO looks like CPython and pypy put this into an "exceptions" module:
extern "C" {
BoxedClass* Exception, *AssertionError, *AttributeError, *GeneratorExit, *TypeError, *NameError, *KeyError, *IndexError, BoxedClass* Exception, *AssertionError, *AttributeError, *GeneratorExit, *TypeError, *NameError, *KeyError, *IndexError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError,
*StopIteration, *Warning, *SyntaxError; *StopIteration, *Warning, *SyntaxError, *OverflowError, *DeprecationWarning;
}
Box* exceptionNew1(BoxedClass* cls) { Box* exceptionNew1(BoxedClass* cls) {
return exceptionNew2(cls, boxStrConstant("")); return exceptionNew2(cls, boxStrConstant(""));
...@@ -554,9 +556,10 @@ void setupBuiltins() { ...@@ -554,9 +556,10 @@ void setupBuiltins() {
StopIteration = makeBuiltinException(Exception, "StopIteration"); StopIteration = makeBuiltinException(Exception, "StopIteration");
Warning = makeBuiltinException(Exception, "Warning"); Warning = makeBuiltinException(Exception, "Warning");
SyntaxError = makeBuiltinException(Exception, "SyntaxError"); SyntaxError = makeBuiltinException(Exception, "SyntaxError");
OverflowError = makeBuiltinException(Exception, "OverflowError");
/*ImportWarning =*/makeBuiltinException(Warning, "ImportWarning"); /*ImportWarning =*/makeBuiltinException(Warning, "ImportWarning");
/*PendingDeprecationWarning =*/makeBuiltinException(Warning, "PendingDeprecationWarning"); /*PendingDeprecationWarning =*/makeBuiltinException(Warning, "PendingDeprecationWarning");
/*DeprecationWarning =*/makeBuiltinException(Warning, "DeprecationWarning"); DeprecationWarning = makeBuiltinException(Warning, "DeprecationWarning");
/*BytesWarning =*/makeBuiltinException(Warning, "BytesWarning"); /*BytesWarning =*/makeBuiltinException(Warning, "BytesWarning");
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1)); repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1));
......
...@@ -74,6 +74,17 @@ extern "C" int PyModule_AddIntConstant(PyObject* _m, const char* name, long valu ...@@ -74,6 +74,17 @@ extern "C" int PyModule_AddIntConstant(PyObject* _m, const char* name, long valu
return 0; return 0;
} }
#define MAKE_CHECK(NAME, cls_name) \
extern "C" bool Py##NAME##_Check(PyObject* op) { return isSubclass(op->cls, cls_name); }
MAKE_CHECK(Int, int_cls)
MAKE_CHECK(String, str_cls)
MAKE_CHECK(Long, long_cls)
MAKE_CHECK(List, list_cls)
MAKE_CHECK(Tuple, tuple_cls)
MAKE_CHECK(Dict, dict_cls)
#undef MAKE_CHECK
extern "C" PyObject* PyDict_New() { extern "C" PyObject* PyDict_New() {
return new BoxedDict(); return new BoxedDict();
} }
...@@ -333,100 +344,112 @@ extern "C" void PyBuffer_Release(Py_buffer* view) { ...@@ -333,100 +344,112 @@ extern "C" void PyBuffer_Release(Py_buffer* view) {
view->obj = NULL; view->obj = NULL;
} }
int vPyArg_ParseTuple(PyObject* _tuple, const char* fmt, va_list ap) { extern "C" void Py_FatalError(const char* msg) {
RELEASE_ASSERT(_tuple->cls == tuple_cls, ""); fprintf(stderr, "%s", msg);
BoxedTuple* tuple = static_cast<BoxedTuple*>(_tuple); abort();
}
bool now_optional = false; extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) {
int arg_idx = 0; abort();
}
int tuple_size = tuple->elts.size(); extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) {
RELEASE_ASSERT(op, "");
RELEASE_ASSERT(tp, "");
Py_TYPE(op) = tp;
return op;
}
while (char c = *fmt) { extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_ssize_t size) {
fmt++; abort(); // "var" objects not tested yet
if (c == ':') { RELEASE_ASSERT(op, "");
break; RELEASE_ASSERT(tp, "");
} else if (c == '|') { Py_TYPE(op) = tp;
now_optional = true; op->ob_size = size;
continue; return op;
} else { }
if (arg_idx >= tuple_size) {
RELEASE_ASSERT(now_optional, "");
break;
}
PyObject* arg = tuple->elts[arg_idx]; extern "C" PyObject* _PyObject_New(PyTypeObject* cls) {
assert(cls->tp_itemsize == 0);
auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
rtn->cls = cls;
return rtn;
}
switch (c) { extern "C" void PyObject_Free(void* p) {
case 's': { gc::gc_free(p);
if (*fmt == '*') { ASSERT(0, "I think this is good enough but I'm not sure; should test");
Py_buffer* p = (Py_buffer*)va_arg(ap, Py_buffer*); }
RELEASE_ASSERT(arg->cls == str_cls, ""); extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) {
PyBuffer_FillInfo(p, arg, PyString_AS_STRING(arg), PyString_GET_SIZE(arg), 1, 0); RELEASE_ASSERT(args, ""); // actually it looks like this is allowed to be NULL
fmt++; RELEASE_ASSERT(args->cls == tuple_cls, "");
} else if (*fmt == ':') {
break; // TODO do something like this? not sure if this is safe; will people expect that calling into a known function
} else { // won't end up doing a GIL check?
RELEASE_ASSERT(0, ""); // threading::GLDemoteRegion _gil_demote;
}
break; try {
} Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
case 'O': { return r;
PyObject** p = (PyObject**)va_arg(ap, PyObject**); } catch (Box* b) {
*p = arg; abort();
break;
}
default:
RELEASE_ASSERT(0, "Unhandled format character: '%c'", c);
}
}
} }
return 1;
} }
extern "C" int PyArg_ParseTuple(PyObject* _tuple, const char* fmt, ...) { extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) {
va_list ap; // TODO do something like this? not sure if this is safe; will people expect that calling into a known function
va_start(ap, fmt); // won't end up doing a GIL check?
// threading::GLDemoteRegion _gil_demote;
int r = vPyArg_ParseTuple(_tuple, fmt, ap); try {
return getattr(o, attr);
} catch (Box* b) {
abort();
}
}
va_end(ap);
return r; extern "C" void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) {
abort();
} }
extern "C" int PyArg_ParseTupleAndKeywords(PyObject* args, PyObject* kwargs, const char* format, char** kwlist, ...) { extern "C" void PyErr_Clear() {
assert(kwargs->cls == dict_cls); PyErr_Restore(NULL, NULL, NULL);
RELEASE_ASSERT(static_cast<BoxedDict*>(kwargs)->d.size() == 0, ""); }
va_list ap; extern "C" void PyErr_SetString(PyObject* exception, const char* string) {
va_start(ap, kwlist); PyErr_SetObject(exception, boxStrConstant(string));
}
int r = vPyArg_ParseTuple(args, format, ap); extern "C" void PyErr_SetObject(PyObject* exception, PyObject* value) {
PyErr_Restore(exception, value, NULL);
}
va_end(ap); extern "C" PyObject* PyErr_Format(PyObject* exception, const char* format, ...) {
abort();
}
return r; extern "C" PyObject* PyErr_NoMemory() {
abort();
} }
extern "C" PyObject* _PyObject_New(PyTypeObject* cls) { extern "C" int PyErr_CheckSignals() {
assert(cls->tp_itemsize == 0); abort();
auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
rtn->cls = cls;
return rtn;
} }
extern "C" void PyObject_Free(void* p) { extern "C" int PyErr_ExceptionMatches(PyObject* exc) {
gc::gc_free(p); abort();
ASSERT(0, "I think this is good enough but I'm not sure; should test");
} }
extern "C" PyObject* PyErr_Occurred() { extern "C" PyObject* PyErr_Occurred() {
abort();
/*
printf("need to hook exception handling -- make sure errors dont propagate into C code, and error codes get " printf("need to hook exception handling -- make sure errors dont propagate into C code, and error codes get "
"checked coming out\n"); "checked coming out\n");
return NULL; return NULL;
*/
} }
BoxedModule* importTestExtension() { BoxedModule* importTestExtension() {
......
...@@ -82,6 +82,11 @@ Box* dictLen(BoxedDict* self) { ...@@ -82,6 +82,11 @@ Box* dictLen(BoxedDict* self) {
return boxInt(self->d.size()); return boxInt(self->d.size());
} }
extern "C" Py_ssize_t PyDict_Size(PyObject* op) {
RELEASE_ASSERT(PyDict_Check(op), "");
return static_cast<BoxedDict*>(op)->d.size();
}
Box* dictGetitem(BoxedDict* self, Box* k) { Box* dictGetitem(BoxedDict* self, Box* k) {
assert(self->cls == dict_cls); assert(self->cls == dict_cls);
......
...@@ -31,9 +31,23 @@ ...@@ -31,9 +31,23 @@
namespace pyston { namespace pyston {
extern "C" long PyInt_AsLong(PyObject* obj) { extern "C" long PyInt_AsLong(PyObject* op) {
assert(obj->cls == int_cls); RELEASE_ASSERT(op->cls == int_cls, "");
return static_cast<BoxedInt*>(obj)->n; return static_cast<BoxedInt*>(op)->n;
}
extern "C" Py_ssize_t PyInt_AsSsize_t(PyObject* op) {
RELEASE_ASSERT(op->cls == int_cls, "");
return static_cast<BoxedInt*>(op)->n;
}
extern "C" PyObject* PyInt_FromSize_t(size_t ival) {
RELEASE_ASSERT(ival <= LONG_MAX, "");
return boxInt(ival);
}
extern "C" PyObject* PyInt_FromSsize_t(Py_ssize_t ival) {
return boxInt(ival);
} }
BoxedInt* interned_ints[NUM_INTERNED_INTS]; BoxedInt* interned_ints[NUM_INTERNED_INTS];
......
...@@ -30,6 +30,15 @@ ...@@ -30,6 +30,15 @@
namespace pyston { namespace pyston {
extern "C" int PyList_Append(PyObject* op, PyObject* newitem) {
try {
listAppend(op, newitem);
} catch (Box* b) {
abort();
}
return 0;
}
extern "C" Box* listRepr(BoxedList* self) { extern "C" Box* listRepr(BoxedList* self) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
...@@ -87,7 +96,13 @@ extern "C" Box* listPop(BoxedList* self, Box* idx) { ...@@ -87,7 +96,13 @@ extern "C" Box* listPop(BoxedList* self, Box* idx) {
return rtn; return rtn;
} }
extern "C" Py_ssize_t PyList_Size(PyObject* self) {
RELEASE_ASSERT(self->cls == list_cls, "");
return static_cast<BoxedList*>(self)->size;
}
extern "C" Box* listLen(BoxedList* self) { extern "C" Box* listLen(BoxedList* self) {
assert(self->cls == list_cls);
return boxInt(self->size); return boxInt(self->size);
} }
...@@ -117,12 +132,10 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step) { ...@@ -117,12 +132,10 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step) {
return rtn; return rtn;
} }
extern "C" Box* listGetitemInt(BoxedList* self, BoxedInt* slice) { extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
assert(self->cls == list_cls); assert(self->cls == list_cls);
assert(slice->cls == int_cls);
int64_t n = slice->n;
if (n < 0) if (n < 0)
n = self->size + n; n = self->size + n;
...@@ -133,6 +146,21 @@ extern "C" Box* listGetitemInt(BoxedList* self, BoxedInt* slice) { ...@@ -133,6 +146,21 @@ extern "C" Box* listGetitemInt(BoxedList* self, BoxedInt* slice) {
return rtn; return rtn;
} }
extern "C" Box* listGetitemInt(BoxedList* self, BoxedInt* slice) {
assert(slice->cls == int_cls);
return listGetitemUnboxed(self, slice->n);
}
extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) {
RELEASE_ASSERT(PyList_Check(op), "");
RELEASE_ASSERT(i >= 0, ""); // unlike list.__getitem__, PyList_GetItem doesn't do index wrapping
try {
return listGetitemUnboxed(static_cast<BoxedList*>(op), i);
} catch (Box* b) {
abort();
}
}
extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) { extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
...@@ -466,6 +494,18 @@ extern "C" Box* listNew(Box* cls, Box* container) { ...@@ -466,6 +494,18 @@ extern "C" Box* listNew(Box* cls, Box* container) {
return rtn; return rtn;
} }
extern "C" PyObject* PyList_New(Py_ssize_t size) {
// This function is supposed to return a list of `size` NULL elements.
// That will probably trip an assert somewhere if we try to create that (ex
// I think the GC will expect them to be real objects so they can be relocated).
RELEASE_ASSERT(size == 0, "");
try {
return new BoxedList();
} catch (Box* b) {
abort();
}
}
Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) { Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
int lsz = lhs->size; int lsz = lhs->size;
int rsz = rhs->size; int rsz = rhs->size;
......
...@@ -33,6 +33,21 @@ namespace pyston { ...@@ -33,6 +33,21 @@ namespace pyston {
BoxedClass* long_cls; BoxedClass* long_cls;
extern "C" unsigned long PyLong_AsUnsignedLong(PyObject* vv) {
RELEASE_ASSERT(PyLong_Check(vv), "");
BoxedLong* l = static_cast<BoxedLong*>(vv);
// TODO Will this error on negative values?
RELEASE_ASSERT(mpz_fits_ulong_p(l->n), "");
return mpz_get_ui(l->n);
}
extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) {
BoxedLong* rtn = new BoxedLong(long_cls);
mpz_init_set_ui(rtn->n, ival);
return rtn;
}
extern "C" Box* createLong(const std::string* s) { extern "C" Box* createLong(const std::string* s) {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong(long_cls);
int r = mpz_init_set_str(rtn->n, s->c_str(), 10); int r = mpz_init_set_str(rtn->n, s->c_str(), 10);
......
...@@ -382,7 +382,7 @@ extern "C" void checkUnpackingLength(i64 expected, i64 given) { ...@@ -382,7 +382,7 @@ extern "C" void checkUnpackingLength(i64 expected, i64 given) {
BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined) bool is_user_defined)
: Box(type_cls), tp_basicsize(instance_size), tp_dealloc(NULL), base(base), gc_visit(gc_visit), : BoxVar(type_cls, 0), tp_basicsize(instance_size), tp_dealloc(NULL), base(base), gc_visit(gc_visit),
attrs_offset(attrs_offset), is_constant(false), is_user_defined(is_user_defined) { attrs_offset(attrs_offset), is_constant(false), is_user_defined(is_user_defined) {
assert(tp_dealloc == NULL); assert(tp_dealloc == NULL);
......
...@@ -65,8 +65,7 @@ Box* _tupleSlice(BoxedTuple* self, i64 start, i64 stop, i64 step) { ...@@ -65,8 +65,7 @@ Box* _tupleSlice(BoxedTuple* self, i64 start, i64 stop, i64 step) {
return new BoxedTuple(std::move(velts)); return new BoxedTuple(std::move(velts));
} }
Box* tupleGetitemInt(BoxedTuple* self, BoxedInt* slice) { Box* tupleGetitemUnboxed(BoxedTuple* self, i64 n) {
i64 n = slice->n;
i64 size = self->elts.size(); i64 size = self->elts.size();
if (n < 0) if (n < 0)
...@@ -78,6 +77,20 @@ Box* tupleGetitemInt(BoxedTuple* self, BoxedInt* slice) { ...@@ -78,6 +77,20 @@ Box* tupleGetitemInt(BoxedTuple* self, BoxedInt* slice) {
return rtn; return rtn;
} }
Box* tupleGetitemInt(BoxedTuple* self, BoxedInt* slice) {
return tupleGetitemUnboxed(self, slice->n);
}
extern "C" PyObject* PyTuple_GetItem(PyObject* op, Py_ssize_t i) {
RELEASE_ASSERT(PyTuple_Check(op), "");
RELEASE_ASSERT(i >= 0, ""); // unlike tuple.__getitem__, PyTuple_GetItem doesn't do index wrapping
try {
return tupleGetitemUnboxed(static_cast<BoxedTuple*>(op), i);
} catch (Box* b) {
abort();
}
}
Box* tupleGetitemSlice(BoxedTuple* self, BoxedSlice* slice) { Box* tupleGetitemSlice(BoxedTuple* self, BoxedSlice* slice) {
assert(self->cls == tuple_cls); assert(self->cls == tuple_cls);
assert(slice->cls == slice_cls); assert(slice->cls == slice_cls);
...@@ -115,6 +128,11 @@ Box* tupleLen(BoxedTuple* t) { ...@@ -115,6 +128,11 @@ Box* tupleLen(BoxedTuple* t) {
return boxInt(t->elts.size()); return boxInt(t->elts.size());
} }
extern "C" Py_ssize_t PyTuple_Size(PyObject* op) {
RELEASE_ASSERT(PyTuple_Check(op), "");
return static_cast<BoxedTuple*>(op)->elts.size();
}
Box* tupleRepr(BoxedTuple* t) { Box* tupleRepr(BoxedTuple* t) {
assert(t->cls == tuple_cls); assert(t->cls == tuple_cls);
...@@ -286,6 +304,40 @@ extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) { ...@@ -286,6 +304,40 @@ extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) {
return new BoxedTuple(std::move(velts)); return new BoxedTuple(std::move(velts));
} }
extern "C" int PyTuple_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) {
RELEASE_ASSERT(PyTuple_Check(op), "");
BoxedTuple* t = static_cast<BoxedTuple*>(op);
RELEASE_ASSERT(i >= 0 && i < t->elts.size(), "");
t->elts[i] = newitem;
return 0;
}
extern "C" PyObject* PyTuple_Pack(Py_ssize_t n, ...) {
va_list vargs;
va_start(vargs, n);
PyObject* result = PyTuple_New(n);
if (result == NULL) {
va_end(vargs);
return NULL;
}
for (Py_ssize_t i = 0; i < n; i++) {
PyObject* o = va_arg(vargs, PyObject*);
PyTuple_SetItem(result, i, o);
}
va_end(vargs);
return result;
}
extern "C" PyObject* PyTuple_New(Py_ssize_t size) {
RELEASE_ASSERT(size >= 0, "");
return new BoxedTuple(BoxedTuple::GCVector(size, NULL));
}
BoxedClass* tuple_iterator_cls = NULL; BoxedClass* tuple_iterator_cls = NULL;
extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) { extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
......
...@@ -74,9 +74,9 @@ BoxedList* getSysPath(); ...@@ -74,9 +74,9 @@ BoxedList* getSysPath();
Box* getSysStdout(); Box* getSysStdout();
extern "C" { extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls, *none_cls, extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_cls, *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls,
*method_cls, *closure_cls, *generator_cls; *member_cls, *method_cls, *closure_cls, *generator_cls;
} }
extern "C" { extern Box* None, *NotImplemented, *True, *False; } extern "C" { extern Box* None, *NotImplemented, *True, *False; }
extern "C" { extern "C" {
...@@ -253,12 +253,10 @@ public: ...@@ -253,12 +253,10 @@ public:
class BoxedTuple : public Box { class BoxedTuple : public Box {
public: public:
typedef std::vector<Box*, StlCompatAllocator<Box*> > GCVector; typedef std::vector<Box*, StlCompatAllocator<Box*> > GCVector;
const GCVector elts; GCVector elts;
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >& elts) __attribute__((visibility("default"))) BoxedTuple(GCVector& elts) __attribute__((visibility("default"))) : Box(tuple_cls), elts(elts) {}
: Box(tuple_cls), elts(elts) {} BoxedTuple(GCVector&& elts) __attribute__((visibility("default"))) : Box(tuple_cls), elts(std::move(elts)) {}
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default")))
: Box(tuple_cls), elts(std::move(elts)) {}
}; };
extern "C" BoxedTuple* EmptyTuple; extern "C" BoxedTuple* EmptyTuple;
...@@ -370,7 +368,7 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b); ...@@ -370,7 +368,7 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b);
Box* exceptionNew1(BoxedClass* cls); Box* exceptionNew1(BoxedClass* cls);
Box* exceptionNew2(BoxedClass* cls, Box* message); Box* exceptionNew2(BoxedClass* cls, Box* message);
extern BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError, extern "C" BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError,
*StopIteration, *GeneratorExit, *SyntaxError; *StopIteration, *GeneratorExit, *SyntaxError;
......
import os import os
import sys import sys
def verify_include(_, dir, files): def file_is_from_cpython(fn):
return '2.7' in fn
def verify_include_guard(_, dir, files):
for bn in files: for bn in files:
fn = os.path.join(dir, bn) fn = os.path.join(dir, bn)
if not bn.endswith(".h"): if not bn.endswith(".h"):
continue continue
if file_is_from_cpython(fn):
continue
expected_guard = "PYSTON" + fn[1:-2].replace('_', '').replace('/', '_').upper() + "_H" expected_guard = "PYSTON" + fn[1:-2].replace('_', '').replace('/', '_').upper() + "_H"
with open(fn) as f: with open(fn) as f:
while True: while True:
...@@ -24,6 +30,9 @@ def verify_license(_, dir, files): ...@@ -24,6 +30,9 @@ def verify_license(_, dir, files):
if bn.endswith(".h") or bn.endswith(".cpp"): if bn.endswith(".h") or bn.endswith(".cpp"):
s = open(fn).read(1024) s = open(fn).read(1024)
if file_is_from_cpython(fn):
assert "This file is originally from CPython 2.7, with modifications for Pyston" in s, fn
else:
assert "Copyright (c) 2014 Dropbox, Inc." in s, fn assert "Copyright (c) 2014 Dropbox, Inc." in s, fn
assert "Apache License, Version 2.0" in s, fn assert "Apache License, Version 2.0" in s, fn
...@@ -147,7 +156,7 @@ def verify_include_order(_, dir, files): ...@@ -147,7 +156,7 @@ def verify_include_order(_, dir, files):
if __name__ == "__main__": if __name__ == "__main__":
os.path.walk('.', verify_include, None) os.path.walk('.', verify_include_guard, None)
os.path.walk('.', verify_include_order, None) os.path.walk('.', verify_include_order, None)
os.path.walk('.', verify_license, None) os.path.walk('.', verify_license, None)
os.path.walk('../tools', verify_license, None) os.path.walk('../tools', verify_license, None)
......
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