Commit 181d5850 authored by Marius Wachtler's avatar Marius Wachtler

Merge remote-tracking branch 'upstream/master' into intern

parents d7d47656 9030ec59
......@@ -23,6 +23,7 @@ addons:
- clang-3.5
- cmake
- g++-4.8
- gdb
- libgmp3-dev
- liblzma-dev
- libncurses5-dev
......@@ -51,7 +52,7 @@ script:
- ccache -z
- ninja -j4 pyston
- ccache -s
- ninja check-pyston
- PYSTON_RUN_ARGS=G ninja check-pyston
os:
- linux
......
......@@ -112,12 +112,25 @@ ifeq ($(NEED_OLD_JIT),1)
LLVM_LINK_LIBS += jit
endif
LLVM_CONFIG_DBG := $(LLVM_BUILD)/Release+Asserts/bin/llvm-config
ifneq ($(wildcard $(LLVM_CONFIG_DBG)),)
LLVM_CXXFLAGS := $(shell $(LLVM_BUILD)/Release+Asserts/bin/llvm-config --cxxflags)
LLVM_LDFLAGS := $(shell $(LLVM_BUILD)/Release+Asserts/bin/llvm-config --ldflags --system-libs --libs $(LLVM_LINK_LIBS))
LLVM_LIB_DEPS := $(wildcard $(LLVM_BUILD)/Release+Asserts/lib/*)
else
LLVM_CXXFLAGS := DBG_NOT_BUILT
LLVM_LDFLAGS := DBG_NOT_BUILT
LLVM_LIB_DEPS := DBG_NOT_BUILT
endif
LLVM_CONFIG_DEBUG := $(LLVM_BUILD)/Debug+Asserts/bin/llvm-config
ifneq ($(wildcard $(LLVM_CONFIG_DBG)),)
LLVM_DEBUG_LDFLAGS := $(shell $(LLVM_BUILD)/Debug+Asserts/bin/llvm-config --ldflags --system-libs --libs $(LLVM_LINK_LIBS))
LLVM_DEBUG_LIB_DEPS := $(wildcard $(LLVM_BUILD)/Debug+Asserts/lib/*)
else
LLVM_DEBUG_LDFLAGS := DEBUG_NOT_BUILT
LLVM_DEBUG_LIB_DEPS := DEBUG_NOT_BUILT
endif
LLVM_CONFIG_RELEASE := $(LLVM_BUILD)/Release/bin/llvm-config
ifneq ($(wildcard $(LLVM_CONFIG_RELEASE)),)
......
......@@ -27,6 +27,8 @@
#define SIZEOF_INT 4
#define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8
#define SIZEOF_DOUBLE 8
#define SIZEOF_FLOAT 4
#define SIZEOF_OFF_T 8
#define SIZEOF_PTHREAD_T 8
#define HAVE_COPYSIGN 1
......@@ -59,6 +61,9 @@
#define HAVE_STRUCT_TM_TM_ZONE 1
#define HAVE_MKTIME 1
#define TIME_WITH_SYS_TIME
#define HAVE_GETTIMEOFDAY 1
#define PY_FORMAT_LONG_LONG "ll"
#define PY_FORMAT_SIZE_T "z"
......
......@@ -55,7 +55,9 @@ typedef struct BLOCK {
struct BLOCK *leftlink;
} block;
#define MAXFREEBLOCKS 10
// Pyston change: disable free block cache
// #define MAXFREEBLOCKS 10
#define MAXFREEBLOCKS 0
static Py_ssize_t numfreeblocks = 0;
static block *freeblocks[MAXFREEBLOCKS];
......
from django.template.base import Origin, Template, Context, TemplateDoesNotExist
from django.conf import settings
from django.apps import apps
import time
try:
import __pyston__
pyston_loaded = True
except:
pyston_loaded = False
template_source = """
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
<div id="content-main">
{% if app_list %}
{% for app in app_list %}
<div class="app-{{ app.app_label }} module">
<table>
<caption>
<a href="{{ app.app_url }}" class="section" title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a>
</caption>
{% for model in app.models %}
<tr class="model-{{ model.object_name|lower }}">
{% if model.admin_url %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.add_url %}
<td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.admin_url %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
{% block sidebar %}
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>{% trans 'Recent Actions' %}</h2>
<h3>{% trans 'My Actions' %}</h3>
{% load log %}
{% get_admin_log 10 as admin_log for_user user %}
{% if not admin_log %}
<p>{% trans 'None available' %}</p>
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
{% if entry.is_deletion or not entry.get_admin_url %}
{{ entry.object_repr }}
{% else %}
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
{% endif %}
<br/>
{% if entry.content_type %}
<span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
{% else %}
<span class="mini quiet">{% trans 'Unknown content' %}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}
"""
settings.configure()
apps.populate((
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
))
elapsed = 0
for i in xrange(500):
#if pyston_loaded:
# __pyston__.clearStats()
start = time.time()
template = Template(template_source, None, "admin/index.html")
elapsed = time.time() - start
print "took %4.1fms for last iteration" % (elapsed * 1000.0,)
......@@ -30,7 +30,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
capi/codecs.cpp
capi/descrobject.cpp
capi/errors.cpp
capi/float.cpp
capi/modsupport.cpp
capi/object.cpp
capi/typeobject.cpp
......
......@@ -557,8 +557,29 @@ extern "C" int PyObject_CheckReadBuffer(PyObject* obj) noexcept {
}
extern "C" int PyObject_AsReadBuffer(PyObject* obj, const void** buffer, Py_ssize_t* buffer_len) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
PyBufferProcs* pb;
void* pp;
Py_ssize_t len;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
return -1;
}
pb = obj->cls->tp_as_buffer;
if (pb == NULL || pb->bf_getreadbuffer == NULL || pb->bf_getsegcount == NULL) {
PyErr_SetString(PyExc_TypeError, "expected a readable buffer object");
return -1;
}
if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
PyErr_SetString(PyExc_TypeError, "expected a single-segment buffer object");
return -1;
}
len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
if (len < 0)
return -1;
*buffer = pp;
*buffer_len = len;
return 0;
}
static PyObject* call_function_tail(PyObject* callable, PyObject* args) {
......@@ -1818,6 +1839,21 @@ extern "C" PyObject* PyNumber_Long(PyObject* o) noexcept {
}
extern "C" PyObject* PyNumber_Float(PyObject* o) noexcept {
if (o == NULL)
return null_error();
if (o->cls == float_cls)
return o;
if (PyInt_Check(o))
return boxFloat(((BoxedInt*)o)->n);
else if (PyLong_Check(o)) {
double result = PyLong_AsDouble(o);
if (result == -1.0 && PyErr_Occurred())
return NULL;
return boxFloat(result);
}
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
......
......@@ -18,6 +18,7 @@
namespace pyston {
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__");
BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
assert(self->cls == method_cls);
......
This diff is collapsed.
......@@ -58,6 +58,7 @@ static int hackcheck(PyObject* self, setattrofunc func, const char* what) noexce
}
static PyObject* wrap_setattr(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_setattr");
setattrofunc func = (setattrofunc)wrapped;
int res;
PyObject* name, *value;
......@@ -74,6 +75,7 @@ static PyObject* wrap_setattr(PyObject* self, PyObject* args, void* wrapped) noe
}
static PyObject* wrap_delattr(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delattr");
setattrofunc func = (setattrofunc)wrapped;
int res;
PyObject* name;
......@@ -91,6 +93,7 @@ static PyObject* wrap_delattr(PyObject* self, PyObject* args, void* wrapped) noe
}
static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_hashfunc");
hashfunc func = (hashfunc)wrapped;
long res;
......@@ -103,12 +106,14 @@ static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) no
}
static PyObject* wrap_call(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_wrap_call");
ternaryfunc func = (ternaryfunc)wrapped;
return (*func)(self, args, kwds);
}
static PyObject* wrap_richcmpfunc(PyObject* self, PyObject* args, void* wrapped, int op) noexcept {
STAT_TIMER(t0, "us_timer_wrap_richcmpfunc");
richcmpfunc func = (richcmpfunc)wrapped;
PyObject* other;
......@@ -132,6 +137,7 @@ RICHCMP_WRAPPER(gt, Py_GT)
RICHCMP_WRAPPER(ge, Py_GE)
static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) {
STAT_TIMER(t0, "us_timer_wrap_next");
unaryfunc func = (unaryfunc)wrapped;
PyObject* res;
......@@ -144,6 +150,7 @@ static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) {
}
static PyObject* wrap_descr_get(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_descr_get");
descrgetfunc func = (descrgetfunc)wrapped;
PyObject* obj;
PyObject* type = NULL;
......@@ -162,6 +169,7 @@ static PyObject* wrap_descr_get(PyObject* self, PyObject* args, void* wrapped) n
}
static PyObject* wrap_coercefunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_coercefunc");
coercion func = (coercion)wrapped;
PyObject* other, *res;
int ok;
......@@ -188,6 +196,7 @@ static PyObject* wrap_coercefunc(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_ternaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ternaryfunc");
ternaryfunc func = (ternaryfunc)wrapped;
PyObject* other;
PyObject* third = Py_None;
......@@ -200,6 +209,7 @@ static PyObject* wrap_ternaryfunc(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_ternaryfunc_r(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ternaryfunc_r");
ternaryfunc func = (ternaryfunc)wrapped;
PyObject* other;
PyObject* third = Py_None;
......@@ -212,6 +222,7 @@ static PyObject* wrap_ternaryfunc_r(PyObject* self, PyObject* args, void* wrappe
}
static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_unaryfunc");
unaryfunc func = (unaryfunc)wrapped;
if (!check_num_args(args, 0))
......@@ -220,6 +231,7 @@ static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) n
}
static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_inquirypred");
inquiry func = (inquiry)wrapped;
int res;
......@@ -232,6 +244,7 @@ static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrapInquirypred(PyObject* self, PyObject* args, void* wrapped) {
STAT_TIMER(t0, "us_timer_wrapInquirypred");
inquiry func = (inquiry)wrapped;
int res;
......@@ -244,6 +257,7 @@ static PyObject* wrapInquirypred(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc");
binaryfunc func = (binaryfunc)wrapped;
PyObject* other;
......@@ -254,6 +268,7 @@ static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_binaryfunc_l(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc_l");
binaryfunc func = (binaryfunc)wrapped;
PyObject* other;
......@@ -268,6 +283,7 @@ static PyObject* wrap_binaryfunc_l(PyObject* self, PyObject* args, void* wrapped
}
static PyObject* wrap_binaryfunc_r(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc_r");
binaryfunc func = (binaryfunc)wrapped;
PyObject* other;
......@@ -300,6 +316,7 @@ static Py_ssize_t getindex(PyObject* self, PyObject* arg) noexcept {
}
static PyObject* wrap_lenfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_lenfunc");
lenfunc func = (lenfunc)wrapped;
Py_ssize_t res;
......@@ -312,6 +329,7 @@ static PyObject* wrap_lenfunc(PyObject* self, PyObject* args, void* wrapped) noe
}
static PyObject* wrap_indexargfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_indexargfunc");
ssizeargfunc func = (ssizeargfunc)wrapped;
PyObject* o;
Py_ssize_t i;
......@@ -325,6 +343,7 @@ static PyObject* wrap_indexargfunc(PyObject* self, PyObject* args, void* wrapped
}
static PyObject* wrap_sq_item(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_item");
ssizeargfunc func = (ssizeargfunc)wrapped;
PyObject* arg;
Py_ssize_t i;
......@@ -342,6 +361,7 @@ static PyObject* wrap_sq_item(PyObject* self, PyObject* args, void* wrapped) noe
}
static PyObject* wrap_ssizessizeargfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ssizessizeargfunc");
ssizessizeargfunc func = (ssizessizeargfunc)wrapped;
Py_ssize_t i, j;
......@@ -351,6 +371,7 @@ static PyObject* wrap_ssizessizeargfunc(PyObject* self, PyObject* args, void* wr
}
static PyObject* wrap_sq_setitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_setitem");
ssizeobjargproc func = (ssizeobjargproc)wrapped;
Py_ssize_t i;
int res;
......@@ -369,6 +390,7 @@ static PyObject* wrap_sq_setitem(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_sq_delitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_delitem");
ssizeobjargproc func = (ssizeobjargproc)wrapped;
Py_ssize_t i;
int res;
......@@ -388,6 +410,7 @@ static PyObject* wrap_sq_delitem(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ssizessizeobjargproc");
ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
Py_ssize_t i, j;
int res;
......@@ -403,6 +426,7 @@ static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void*
}
static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delslice");
ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
Py_ssize_t i, j;
int res;
......@@ -418,6 +442,7 @@ static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) no
/* XXX objobjproc is a misnomer; should be objargpred */
static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_objobjproc");
objobjproc func = (objobjproc)wrapped;
int res;
PyObject* value;
......@@ -433,6 +458,7 @@ static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped)
}
static PyObject* wrap_objobjargproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_objobjargproc");
objobjargproc func = (objobjargproc)wrapped;
int res;
PyObject* key, *value;
......@@ -447,6 +473,7 @@ static PyObject* wrap_objobjargproc(PyObject* self, PyObject* args, void* wrappe
}
static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delitem");
objobjargproc func = (objobjargproc)wrapped;
int res;
PyObject* key;
......@@ -462,6 +489,7 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe
}
static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_cmpfunc");
cmpfunc func = (cmpfunc)wrapped;
int res;
PyObject* other;
......@@ -482,6 +510,7 @@ static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noe
static PyObject* wrap_init(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_wrap_init");
initproc func = (initproc)wrapped;
if (func(self, args, kwds) < 0)
......
......@@ -54,6 +54,7 @@ public:
}
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs) {
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__");
assert(self->cls == capifunc_cls);
assert(varargs->cls == tuple_cls);
assert(kwargs->cls == dict_cls);
......@@ -111,6 +112,8 @@ public:
DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) {
STAT_TIMER(t0, "us_timer_boxedwrapperobject__call__");
assert(self->cls == wrapperobject_cls);
assert(args->cls == tuple_cls);
assert(kwds->cls == dict_cls);
......
......@@ -284,6 +284,8 @@ public:
Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block, AST_stmt* start_at) {
threading::allowGLReadPreemption();
STAT_TIMER(t0, "us_timer_astinterpreter_execute");
void* frame_addr = __builtin_frame_address(0);
RegisterHelper frame_registerer(&interpreter, frame_addr);
......@@ -340,12 +342,7 @@ Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type
void ASTInterpreter::doStore(InternedString name, Value value) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
if (vst == ScopeInfo::VarScopeType::GLOBAL) {
if (globals->cls == module_cls) {
setattr(static_cast<BoxedModule*>(globals), name.c_str(), value.o);
} else {
assert(globals->cls == dict_cls);
static_cast<BoxedDict*>(globals)->d[boxString(name.str())] = value.o;
}
setGlobal(globals, name, value.o);
} else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(frame_info.boxedLocals != NULL);
// TODO should probably pre-box the names when it's a scope that usesNameLookup
......@@ -540,6 +537,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
arg_array.push_back(it.second);
}
STAT_TIMER(t0, "us_timer_astinterpreter_jump_osrexit");
CompiledFunction* partial_func = compilePartialFuncInternal(&exit);
auto arg_tuple = getTupleFromArgsArray(&arg_array[0], arg_array.size());
Box* r = partial_func->call(std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
......@@ -876,7 +874,6 @@ Value ASTInterpreter::visit_delete(AST_Delete* node) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id);
if (vst == ScopeInfo::VarScopeType::GLOBAL) {
// Can't use delattr since the errors are different:
delGlobal(globals, &target->id.str());
continue;
} else if (vst == ScopeInfo::VarScopeType::NAME) {
......@@ -927,6 +924,8 @@ Value ASTInterpreter::visit_print(AST_Print* node) {
static const std::string newline_str("\n");
static const std::string space_str(" ");
STAT_TIMER(t0, "us_timer_visit_print");
Box* dest = node->dest ? visit_expr(node->dest).o : getSysStdout();
int nvals = node->values.size();
assert(nvals <= 1 && "cfg should have lowered it to 0 or 1 values");
......
......@@ -362,7 +362,7 @@ static void handle_sigint(int signum) {
// For now, just call abort(), so that we get a traceback at least.
fprintf(stderr, "SIGINT!\n");
joinRuntime();
Stats::dump();
Stats::dump(false);
abort();
}
......
......@@ -182,6 +182,7 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) {
// The codegen_lock needs to be held in W mode before calling this function:
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel effort,
const OSREntryDescriptor* entry_descriptor) {
STAT_TIMER(t0, "us_timer_compileFunction");
Timer _t("for compileFunction()", 1000);
assert((entry_descriptor != NULL) + (spec != NULL) == 1);
......@@ -315,10 +316,13 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
assert(cf->clfunc->versions.size());
}
if (cf->is_interpreted)
if (cf->is_interpreted) {
STAT_TIMER(t0, "us_timer_interpreted_module_toplevel");
astInterpretFunction(cf, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
else
} else {
STAT_TIMER(t1, "us_timer_jitted_module_toplevel");
((void (*)())cf->code)();
}
}
Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) {
......
......@@ -982,6 +982,7 @@ AST_Module* parse_string(const char* code) {
}
AST_Module* parse_file(const char* fn) {
STAT_TIMER(t0, "us_timer_cpyton_parsing");
Timer _t("parsing");
if (ENABLE_PYPA_PARSER) {
......@@ -1071,9 +1072,10 @@ static ParseResult _reparse(const char* fn, const std::string& cache_fn, AST_Mod
// it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms).
AST_Module* caching_parse_file(const char* fn) {
STAT_TIMER(t0, "us_timer_caching_parse_file");
static StatCounter us_parsing("us_parsing");
Timer _t("parsing");
_t.setExitCallback([](long t) { us_parsing.log(t); });
_t.setExitCallback([](uint64_t t) { us_parsing.log(t); });
int code;
std::string cache_fn = std::string(fn) + "c";
......
......@@ -494,6 +494,7 @@ void unwindPythonStack(std::function<bool(std::unique_ptr<PythonFrameIteratorImp
}
static std::unique_ptr<PythonFrameIteratorImpl> getTopPythonFrame() {
STAT_TIMER(t0, "us_timer_getTopPythonFrame");
std::unique_ptr<PythonFrameIteratorImpl> rtn(nullptr);
unwindPythonStack([&](std::unique_ptr<PythonFrameIteratorImpl> iter) {
rtn = std::move(iter);
......@@ -514,6 +515,7 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) {
static StatCounter us_gettraceback("us_gettraceback");
BoxedTraceback* getTraceback() {
STAT_TIMER(t0, "us_timer_gettraceback");
if (!ENABLE_FRAME_INTROSPECTION) {
static bool printed_warning = false;
if (!printed_warning) {
......@@ -597,6 +599,8 @@ CompiledFunction* getTopCompiledFunction() {
Box* getGlobals() {
auto it = getTopPythonFrame();
if (!it)
return NULL;
return it->getGlobals();
}
......
......@@ -22,9 +22,105 @@
namespace pyston {
#if !DISABLE_STATS
std::vector<long>* Stats::counts;
#if STAT_TIMERS
extern "C" const char* getStatTimerNameById(int id) {
return Stats::getStatName(id).c_str();
}
extern "C" int getStatTimerId() {
return StatTimer::getStack()->getId();
}
extern "C" const char* getStatTimerName() {
return getStatTimerNameById(getStatTimerId());
}
__thread StatTimer* StatTimer::stack;
StatTimer::StatTimer(int statid, bool push) {
uint64_t at_time = getCPUTicks();
_start_time = 0;
_statid = statid;
if (!push) {
_prev = NULL;
return;
}
_prev = stack;
stack = this;
if (_prev) {
_prev->pause(at_time);
}
resume(at_time);
}
StatTimer::StatTimer(int statid, uint64_t at_time) {
_start_time = 0;
_statid = statid;
_prev = stack;
stack = this;
if (_prev) {
_prev->pause(at_time);
}
resume(at_time);
}
StatTimer::~StatTimer() {
assert(stack == this);
uint64_t at_time;
if (!isPaused()) {
at_time = getCPUTicks();
pause(at_time);
} else {
// fprintf (stderr, "WARNING: timer was paused.\n");
at_time = _last_pause_time;
}
stack = _prev;
if (stack) {
stack->resume(at_time);
}
}
void StatTimer::pause(uint64_t at_time) {
assert(!isPaused());
assert(at_time > _start_time);
uint64_t _duration = at_time - _start_time;
Stats::log(_statid, _duration);
_start_time = 0;
_last_pause_time = at_time;
// fprintf (stderr, "paused %d at %lu\n", _statid, at_time);
}
void StatTimer::resume(uint64_t at_time) {
assert(isPaused());
_start_time = at_time;
// fprintf (stderr, "resumed %d at %lu\n", _statid, at_time);
}
StatTimer* StatTimer::swapStack(StatTimer* s, uint64_t at_time) {
StatTimer* prev_stack = stack;
if (stack) {
stack->pause(at_time);
}
stack = s;
if (stack) {
stack->resume(at_time);
}
return prev_stack;
}
#endif
std::vector<uint64_t>* Stats::counts;
std::unordered_map<int, std::string>* Stats::names;
bool Stats::enabled;
timespec Stats::start_ts;
uint64_t Stats::start_tick;
StatCounter::StatCounter(const std::string& name) : id(Stats::getStatId(name)) {
}
......@@ -38,7 +134,7 @@ int Stats::getStatId(const std::string& name) {
// hacky but easy way of getting around static constructor ordering issues for now:
static std::unordered_map<int, std::string> names;
Stats::names = &names;
static std::vector<long> counts;
static std::vector<uint64_t> counts;
Stats::counts = &counts;
static std::unordered_map<std::string, int> made;
......@@ -52,11 +148,36 @@ int Stats::getStatId(const std::string& name) {
return rtn;
}
std::string Stats::getStatName(int id) {
return (*names)[id];
}
void Stats::startEstimatingCPUFreq() {
if (!Stats::enabled)
return;
clock_gettime(CLOCK_REALTIME, &Stats::start_ts);
Stats::start_tick = getCPUTicks();
}
// returns our estimate of the MHz of the cpu. MHz is handy because we're mostly interested in microsoecond-resolution
// timing.
double Stats::estimateCPUFreq() {
timespec dump_ts;
clock_gettime(CLOCK_REALTIME, &dump_ts);
uint64_t end_tick = getCPUTicks();
uint64_t wall_clock_ns = (dump_ts.tv_sec - start_ts.tv_sec) * 1000000000 + (dump_ts.tv_nsec - start_ts.tv_nsec);
return (double)(end_tick - Stats::start_tick) * 1000 / wall_clock_ns;
}
void Stats::dump(bool includeZeros) {
if (!Stats::enabled)
return;
double cycles_per_us = Stats::estimateCPUFreq();
fprintf(stderr, "Stats:\n");
fprintf(stderr, "estimated_cpu_mhz: %5.5f\n", cycles_per_us);
gc::dumpHeapStatistics(0);
......@@ -69,11 +190,41 @@ void Stats::dump(bool includeZeros) {
std::sort(pairs.begin(), pairs.end());
uint64_t ticks_in_main = 0;
uint64_t accumulated_stat_timer_ticks = 0;
for (int i = 0; i < pairs.size(); i++) {
if (includeZeros || (*counts)[pairs[i].second] > 0)
fprintf(stderr, "%s: %ld\n", pairs[i].first.c_str(), (*counts)[pairs[i].second]);
if (includeZeros || (*counts)[pairs[i].second] > 0) {
if (startswith(pairs[i].first, "us_") || startswith(pairs[i].first, "_init_us_")) {
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(),
(uint64_t)((*counts)[pairs[i].second] / cycles_per_us));
} else
fprintf(stderr, "%s: %lu\n", pairs[i].first.c_str(), (*counts)[pairs[i].second]);
if (startswith(pairs[i].first, "us_timer_"))
accumulated_stat_timer_ticks += (*counts)[pairs[i].second];
if (pairs[i].first == "ticks_in_main")
ticks_in_main = (*counts)[pairs[i].second];
}
}
if (includeZeros || accumulated_stat_timer_ticks > 0)
fprintf(stderr, "ticks_all_timers: %lu\n", accumulated_stat_timer_ticks);
#if 0
// I want to enable this, but am leaving it disabled for the time
// being because it causes test failures due to:
//
// 1) some tests exit from main from inside catch blocks, without
// going through the logic to stop the timers.
// 2) some tests create multiple threads which causes problems
// with our non-per thread stat timers.
if (ticks_in_main && ticks_in_main != accumulated_stat_timer_ticks) {
fprintf(stderr, "WARNING: accumulated stat timer ticks != ticks in main - don't trust timer output.");
}
#endif
fprintf(stderr, "(End of stats)\n");
}
......
......@@ -22,23 +22,48 @@
#include <vector>
#include "core/options.h"
#include "core/util.h"
namespace pyston {
#define DISABLE_STATS 0
#define STAT_ALLOCATIONS 0 && !DISABLE_STATS
#define STAT_TIMERS 0 && !DISABLE_STATS
#if STAT_TIMERS
#define STAT_TIMER(id, name) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id)
#define STAT_TIMER2(id, name, at_time) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id, at_time)
#else
#define STAT_TIMER(id, name) StatTimer _st##id(0);
#define STAT_TIMER2(id, name, at_time) StatTimer _st##id(0);
#endif
#define STAT_TIMER_NAME(id) _st##id
#if !DISABLE_STATS
struct Stats {
private:
static std::vector<long>* counts;
static std::vector<uint64_t>* counts;
static std::unordered_map<int, std::string>* names;
static bool enabled;
static timespec start_ts;
static uint64_t start_tick;
public:
static void startEstimatingCPUFreq();
static double estimateCPUFreq();
static int getStatId(const std::string& name);
static std::string getStatName(int id);
static void setEnabled(bool enabled) { Stats::enabled = enabled; }
static void log(int id, int count = 1) { (*counts)[id] += count; }
static void log(int id, uint64_t count = 1) { (*counts)[id] += count; }
static void clear() { std::fill(counts->begin(), counts->end(), 0); }
static void dump(bool includeZeros = true);
......@@ -52,7 +77,7 @@ private:
public:
StatCounter(const std::string& name);
void log(int count = 1) { Stats::log(id, count); }
void log(uint64_t count = 1) { Stats::log(id, count); }
};
struct StatPerThreadCounter {
......@@ -62,24 +87,74 @@ private:
public:
StatPerThreadCounter(const std::string& name);
void log(int count = 1) { Stats::log(id, count); }
void log(uint64_t count = 1) { Stats::log(id, count); }
};
#else
struct Stats {
static void startEstimatingCPUFreq() {}
static double estimateCPUFreq() { return 0; }
static void setEnabled(bool enabled) {}
static void dump() { printf("(Stats disabled)\n"); }
static void dump(bool includeZeros = true) { printf("(Stats disabled)\n"); }
static void clear() {}
static void log(int id, int count = 1) {}
static int getStatId(const std::string& name) { return 0; }
static void endOfInit() {}
};
struct StatCounter {
StatCounter(const char* name) {}
void log(int count = 1){};
void log(uint64_t count = 1){};
};
struct StatPerThreadCounter {
StatPerThreadCounter(const char* name) {}
void log(int count = 1){};
void log(uint64_t count = 1){};
};
#endif
#if STAT_TIMERS
class StatTimer {
private:
static __thread StatTimer* stack;
// the start time of the current active segment (0 == paused)
uint64_t _start_time;
uint64_t _last_pause_time;
StatTimer* _prev;
int _statid;
public:
StatTimer(int statid, bool push = true);
StatTimer(int statid, uint64_t at_time);
~StatTimer();
void pause(uint64_t at_time);
void resume(uint64_t at_time);
bool isPaused() const { return _start_time == 0; }
int getId() const { return _statid; }
static StatTimer* getStack() { return stack; }
static StatTimer* swapStack(StatTimer* s, uint64_t at_time);
static void assertActive() { RELEASE_ASSERT(stack && !stack->isPaused(), ""); }
};
#else
struct StatTimer {
StatTimer(int statid, bool push = true) {}
StatTimer(int statid, uint64_t at_time) {}
~StatTimer() {}
bool isPaused() const { return false; }
void pause(uint64_t at_time) {}
void resume(uint64_t at_time) {}
static StatTimer* getStack() { return NULL; }
static StatTimer* swapStack(StatTimer* s, uint64_t at_time) { return NULL; }
static void assertActive() {}
};
#endif
}
......
......@@ -80,6 +80,8 @@ public:
return *this->_str < *rhs._str;
}
operator llvm::StringRef() { return llvm::StringRef(*_str); }
friend class InternedStringPool;
friend struct std::hash<InternedString>;
friend struct std::less<InternedString>;
......
......@@ -485,13 +485,26 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
return Box::operator new(size, default_cls); \
}
#if STAT_ALLOCATIONS
#define ALLOC_STATS(cls) \
std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
Stats::log(Stats::getStatId(per_name_alloc_name)); \
Stats::log(Stats::getStatId(per_name_allocsize_name), size);
#else
#define ALLOC_STATS(cls)
#endif
// The restrictions on when you can use the SIMPLE (ie fast) variant are encoded as
// asserts in the 1-arg operator new function:
#define DEFAULT_CLASS_SIMPLE(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
ALLOC_STATS(cls); \
return Box::operator new(size, cls); \
} \
void* operator new(size_t size) __attribute__((visibility("default"))) { \
ALLOC_STATS(default_cls); \
/* In the simple cases, we can inline the following methods and simplify things a lot: \
* - Box::operator new \
* - cls->tp_alloc \
......
......@@ -16,6 +16,9 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
......@@ -26,6 +29,18 @@
namespace pyston {
static inline uint64_t rdtsc() {
unsigned long lo, hi;
asm("rdtsc" : "=a"(lo), "=d"(hi));
return (lo | (hi << 32));
}
uint64_t getCPUTicks() {
// unsigned int _unused;
// return __rdtscp(&_unused);
return rdtsc();
}
int Timer::level = 0;
Timer::Timer(const char* desc, long min_usec) : min_usec(min_usec), ended(true) {
......@@ -36,7 +51,7 @@ void Timer::restart(const char* newdesc) {
assert(ended);
desc = newdesc;
gettimeofday(&start_time, NULL);
start_time = getCPUTicks();
Timer::level++;
ended = false;
}
......@@ -46,14 +61,14 @@ void Timer::restart(const char* newdesc, long new_min_usec) {
restart(newdesc);
}
long Timer::end() {
uint64_t Timer::end(uint64_t* ended_at) {
if (!ended) {
timeval end;
gettimeofday(&end, NULL);
long us = 1000000L * (end.tv_sec - start_time.tv_sec) + (end.tv_usec - start_time.tv_usec);
uint64_t end = getCPUTicks();
uint64_t duration = end - start_time;
Timer::level--;
if (VERBOSITY("time") >= 2 && desc) {
uint64_t us = (uint64_t)(duration / Stats::estimateCPUFreq());
if (us > min_usec) {
for (int i = 0; i < Timer::level; i++) {
putchar(' ');
......@@ -70,15 +85,17 @@ long Timer::end() {
fflush(stdout);
}
}
if (ended_at)
*ended_at = end;
ended = true;
return us;
return duration;
}
return -1;
}
Timer::~Timer() {
if (!ended) {
long t = end();
uint64_t t = end();
if (exit_callback)
exit_callback(t);
}
......
......@@ -24,30 +24,36 @@
namespace pyston {
uint64_t getCPUTicks();
class Timer {
private:
static int level;
timeval start_time;
uint64_t start_time;
const char* desc;
long min_usec;
bool ended;
std::function<void(long)> exit_callback;
std::function<void(uint64_t)> exit_callback;
public:
Timer(const char* desc = NULL, long min_usec = -1);
~Timer();
void setExitCallback(std::function<void(long)> _exit_callback) { exit_callback = _exit_callback; }
void setExitCallback(std::function<void(uint64_t)> _exit_callback) { exit_callback = _exit_callback; }
void restart(const char* newdesc, long new_min_usec);
void restart(const char* newdesc = NULL);
long end();
long split(const char* newdesc = NULL) {
long rtn = end();
// returns the duration. if @ended_at is non-null, it's filled in
// with the tick the timer stopped at.
uint64_t end(uint64_t* ended_at = NULL);
uint64_t split(const char* newdesc = NULL) {
uint64_t rtn = end();
restart(newdesc);
return rtn;
}
uint64_t getStartTime() const { return start_time; }
};
bool startswith(const std::string& s, const std::string& pattern);
......
......@@ -339,6 +339,8 @@ void runCollection() {
static StatCounter sc("gc_collections");
sc.log();
STAT_TIMER(t0, "us_timer_gc_collection");
ncollections++;
if (VERBOSITY("gc") >= 2)
......
......@@ -28,7 +28,9 @@ namespace pyston {
namespace gc {
static StatCounter gc_alloc_bytes("zzz_gc_alloc_bytes");
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
STAT_TIMER(t0, "us_timer_gc_alloc");
size_t alloc_bytes = bytes + sizeof(GCAllocation);
#ifndef NVALGRIND
......@@ -89,8 +91,10 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
// if (VERBOSITY()) printf("Allocated %ld bytes at [%p, %p)\n", bytes, r, (char*)r + bytes);
#endif
// printf("Allocated %p\n", r);
#if STAT_ALLOCATIONS
gc_alloc_bytes.log(bytes);
#endif
return r;
}
......@@ -128,6 +132,10 @@ extern "C" inline void* gc_realloc(void* ptr, size_t bytes) {
alloc->kind_data = bytes;
}
#if STAT_ALLOCATIONS
gc_alloc_bytes.log(bytes);
#endif
return rtn;
}
......
This diff is collapsed.
......@@ -13,6 +13,7 @@
// limitations under the License.
#include <algorithm>
#include <cfloat>
#include <cstddef>
#include <err.h>
......@@ -303,6 +304,7 @@ extern "C" Box* ord(Box* obj) {
}
Box* range(Box* start, Box* stop, Box* step) {
STAT_TIMER(t0, "us_timer_builtin_range");
i64 istart, istop, istep;
if (stop == NULL) {
istart = 0;
......@@ -346,6 +348,7 @@ Box* notimplementedRepr(Box* self) {
}
Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) {
STAT_TIMER(t0, "us_timer_builtin_sorted");
Box* reverse = args[0];
BoxedList* rtn = new BoxedList();
......@@ -358,6 +361,7 @@ Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) {
}
Box* isinstance_func(Box* obj, Box* cls) {
STAT_TIMER(t0, "us_timer_builtin_isinstance");
int rtn = PyObject_IsInstance(obj, cls);
if (rtn < 0)
checkAndThrowCAPIException();
......@@ -365,16 +369,29 @@ Box* isinstance_func(Box* obj, Box* cls) {
}
Box* issubclass_func(Box* child, Box* parent) {
STAT_TIMER(t0, "us_timer_builtin_issubclass");
int rtn = PyObject_IsSubclass(child, parent);
if (rtn < 0)
checkAndThrowCAPIException();
return boxBool(rtn);
}
Box* intern_func(Box* str) {
if (!PyString_CheckExact(str)) // have to use exact check!
raiseExcHelper(TypeError, "can't intern subclass of string");
PyString_InternInPlace(&str);
checkAndThrowCAPIException();
return str;
}
Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) {
Box* fromlist = args[0];
Box* level = args[1];
// __import__ takes a 'locals' argument, but it doesn't get used in CPython.
// Well, it gets passed to PyImport_ImportModuleLevel() and then import_module_level(),
// which ignores it. So we don't even pass it through.
name = coerceUnicodeToStr(name);
if (name->cls != str_cls) {
......@@ -586,7 +603,6 @@ public:
static Box* __reduce__(Box* self) {
RELEASE_ASSERT(isSubclass(self->cls, BaseException), "");
BoxedException* exc = static_cast<BoxedException*>(self);
return BoxedTuple::create({ self->cls, EmptyTuple, self->getAttrWrapper() });
}
};
......@@ -973,16 +989,38 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
raiseExcHelper(TypeError, "a float is required");
BoxedFloat* number = (BoxedFloat*)_number;
double x = number->d;
if (isSubclass(_ndigits->cls, int_cls)) {
BoxedInt* ndigits = (BoxedInt*)_ndigits;
/* interpret 2nd argument as a Py_ssize_t; clip on overflow */
Py_ssize_t ndigits = PyNumber_AsSsize_t(_ndigits, NULL);
if (ndigits == -1 && PyErr_Occurred())
throwCAPIException();
if (ndigits->n == 0)
return boxFloat(round(number->d));
/* nans, infinities and zeros round to themselves */
if (!std::isfinite(x) || x == 0.0)
return boxFloat(x);
/* Deal with extreme values for ndigits. For ndigits > NDIGITS_MAX, x
always rounds to itself. For ndigits < NDIGITS_MIN, x always
rounds to +-0.0. Here 0.30103 is an upper bound for log10(2). */
#define NDIGITS_MAX ((int)((DBL_MANT_DIG - DBL_MIN_EXP) * 0.30103))
#define NDIGITS_MIN (-(int)((DBL_MAX_EXP + 1) * 0.30103))
if (ndigits > NDIGITS_MAX)
/* return x */
return boxFloat(x);
else if (ndigits < NDIGITS_MIN)
/* return 0.0, but with sign of x */
return boxFloat(0.0 * x);
else {
/* finite x, and ndigits is not unreasonably large */
/* _Py_double_round is defined in floatobject.c */
Box* rtn = _Py_double_round(x, (int)ndigits);
if (!rtn)
throwCAPIException();
return rtn;
}
fatalOrError(PyExc_NotImplementedError, "unimplemented");
throwCAPIException();
#undef NDIGITS_MAX
#undef NDIGITS_MIN
}
Box* builtinCmp(Box* a, Box* b) {
......@@ -1109,6 +1147,9 @@ void setupBuiltins() {
= new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)issubclass_func, BOXED_BOOL, 2), "issubclass");
builtins_module->giveAttr("issubclass", issubclass_obj);
Box* intern_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)intern_func, UNKNOWN, 1), "intern");
builtins_module->giveAttr("intern", intern_obj);
CLFunction* import_func = boxRTFunction((void*)bltinImport, UNKNOWN, 5, 4, false, false,
ParamNames({ "name", "globals", "locals", "fromlist", "level" }, "", ""));
builtins_module->giveAttr("__import__", new BoxedBuiltinFunctionOrMethod(import_func, "__import__",
......
......@@ -48,6 +48,7 @@ Box* dictRepr(BoxedDict* self) {
}
Box* dictClear(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictClear");
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'clear' requires a 'dict' object but received a '%s'", getTypeName(self));
......@@ -56,6 +57,7 @@ Box* dictClear(BoxedDict* self) {
}
Box* dictCopy(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictCopy");
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'copy' requires a 'dict' object but received a '%s'", getTypeName(self));
......@@ -65,6 +67,7 @@ Box* dictCopy(BoxedDict* self) {
}
Box* dictItems(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictItems");
BoxedList* rtn = new BoxedList();
rtn->ensure(self->d.size());
......@@ -77,6 +80,7 @@ Box* dictItems(BoxedDict* self) {
}
Box* dictValues(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictValues");
BoxedList* rtn = new BoxedList();
rtn->ensure(self->d.size());
for (const auto& p : self->d) {
......@@ -86,6 +90,7 @@ Box* dictValues(BoxedDict* self) {
}
Box* dictKeys(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictKeys");
RELEASE_ASSERT(isSubclass(self->cls, dict_cls), "");
BoxedList* rtn = new BoxedList();
......@@ -182,6 +187,7 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept {
}
Box* dictGetitem(BoxedDict* self, Box* k) {
STAT_TIMER(t0, "us_timer_dictGetitem");
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'",
getTypeName(self));
......@@ -306,6 +312,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
}
Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
STAT_TIMER(t0, "us_timer_dictSetitem");
// printf("Starting setitem\n");
Box*& pos = self->d[k];
// printf("Got the pos\n");
......@@ -320,6 +327,7 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
}
Box* dictDelitem(BoxedDict* self, Box* k) {
STAT_TIMER(t0, "us_timer_dictDelitem");
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__delitem__' requires a 'dict' object but received a '%s'",
getTypeName(self));
......
This diff is collapsed.
......@@ -86,28 +86,36 @@ Context* getReturnContextForGeneratorFrame(void* frame_addr) {
}
void generatorEntry(BoxedGenerator* g) {
assert(g->cls == generator_cls);
assert(g->function->cls == function_cls);
{
STAT_TIMER2(t0, "us_timer_generator_toplevel", g->timer_time);
threading::pushGenerator(g, g->stack_begin, g->returnContext);
assert(g->cls == generator_cls);
assert(g->function->cls == function_cls);
try {
RegisterHelper context_registerer(g, __builtin_frame_address(0));
threading::pushGenerator(g, g->stack_begin, g->returnContext);
try {
RegisterHelper context_registerer(g, __builtin_frame_address(0));
// call body of the generator
BoxedFunctionBase* func = g->function;
// call body of the generator
BoxedFunctionBase* func = g->function;
Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2,
g->arg3, args);
} catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller
g->exception = e;
}
Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2,
g->arg3, args);
} catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller
g->exception = e;
}
// we returned from the body of the generator. next/send/throw will notify the caller
g->entryExited = true;
threading::popGenerator();
// we returned from the body of the generator. next/send/throw will notify the caller
g->entryExited = true;
threading::popGenerator();
#if STAT_TIMERS
g->timer_time = getCPUTicks(); // store off the timer that our caller (in g->returnContext) will resume at
STAT_TIMER_NAME(t0).pause(g->timer_time);
#endif
}
swapContext(&g->context, g->returnContext, 0);
}
......@@ -130,7 +138,21 @@ Box* generatorSend(Box* s, Box* v) {
self->returnValue = v;
self->running = true;
#if STAT_TIMERS
// store off the time that the generator will use to initialize its toplevel timer
self->timer_time = getCPUTicks();
StatTimer* current_timers = StatTimer::swapStack(self->statTimers, self->timer_time);
#endif
swapContext(&self->returnContext, self->context, (intptr_t)self);
#if STAT_TIMERS
// if the generator exited we use the time that generatorEntry stored in self->timer_time (the same time it paused
// its timer at).
self->statTimers = StatTimer::swapStack(current_timers, self->entryExited ? self->timer_time : getCPUTicks());
#endif
self->running = false;
// propagate exception to the caller
......
......@@ -21,6 +21,7 @@
#include "codegen/irgen/hooks.h"
#include "codegen/parser.h"
#include "codegen/unwinding.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
......@@ -267,7 +268,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
if (globals == NULL || globals == None || level == 0)
return None;
BoxedString* pkgname = static_cast<BoxedString*>(getattrInternal(globals, package_str, NULL));
BoxedString* pkgname = static_cast<BoxedString*>(getFromGlobals(globals, package_str));
if (pkgname != NULL && pkgname != None) {
/* __package__ is set, so use it */
if (pkgname->cls != str_cls) {
......@@ -286,17 +287,11 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
buf += pkgname->s;
} else {
/* __package__ not set, so figure it out and set it */
BoxedString* modname = static_cast<BoxedString*>(getattrInternal(globals, name_str, NULL));
BoxedString* modname = static_cast<BoxedString*>(getFromGlobals(globals, name_str));
if (modname == NULL || modname->cls != str_cls)
return None;
Box* modpath = NULL;
try {
modpath = getattrInternal(globals, path_str, NULL);
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
raiseRaw(e);
}
Box* modpath = getFromGlobals(globals, path_str);
if (modpath != NULL) {
/* __path__ is set, so modname is already the package name */
......@@ -304,7 +299,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
raiseExcHelper(ValueError, "Module name too long");
}
buf += modname->s;
globals->setattr(package_str, modname, NULL);
setGlobal(globals, package_str, modname);
} else {
/* Normal module, so work out the package name if any */
size_t lastdot = modname->s.rfind('.');
......@@ -312,7 +307,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
raiseExcHelper(ValueError, "Attempted relative import in non-package");
}
if (lastdot == std::string::npos) {
globals->setattr(package_str, None, NULL);
setGlobal(globals, package_str, None);
return None;
}
if (lastdot >= PATH_MAX) {
......@@ -320,7 +315,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
}
buf = std::string(modname->s, 0, lastdot);
globals->setattr(package_str, boxStringPtr(&buf), NULL);
setGlobal(globals, package_str, boxStringPtr(&buf));
}
}
......@@ -471,7 +466,6 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf,
static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive);
Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) {
RELEASE_ASSERT(!globals || globals == None || isSubclass(globals->cls, module_cls), "");
bool return_first = from_imports == None;
static StatCounter slowpath_import("slowpath_import");
......@@ -665,7 +659,7 @@ Box* nullImporterFindModule(Box* self, Box* fullname, Box* path) {
extern "C" Box* import(int level, Box* from_imports, const std::string* module_name) {
std::string _module_name(*module_name);
return importModuleLevel(_module_name, getCurrentModule(), from_imports, level);
return importModuleLevel(_module_name, getGlobals(), from_imports, level);
}
Box* impFindModule(Box* _name, BoxedList* path) {
......
......@@ -200,7 +200,7 @@ extern "C" PyObject* PyInt_FromString(const char* s, char** pend, int base) noex
if (x < 0)
return PyLong_FromString(s, pend, base);
} else
x = strtoul(s, &end, base);
x = strtol(s, &end, base);
if (end == s || !isalnum(Py_CHARMASK(end[-1])))
goto bad;
while (*end && isspace(Py_CHARMASK(*end)))
......@@ -672,8 +672,13 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if (rhs->n < 0)
raiseExcHelper(ValueError, "negative shift count");
// TODO overflow?
return boxInt(lhs->n << rhs->n);
bool undefined = rhs->n >= sizeof(rhs->n) * 8;
if (!undefined) {
int64_t res = lhs->n << rhs->n;
if ((res >> rhs->n) == lhs->n)
return boxInt(lhs->n << rhs->n);
}
return longLshift(boxLong(lhs->n), rhs);
}
extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
......
......@@ -109,7 +109,7 @@ Box* seqiterNext(Box* s) {
}
static void seqiterGCVisit(GCVisitor* v, Box* b) {
assert(b->cls == seqiter_cls);
assert(b->cls == seqiter_cls || b->cls == seqreviter_cls);
boxGCHandler(v, b);
BoxedSeqIter* si = static_cast<BoxedSeqIter*>(b);
......@@ -182,7 +182,8 @@ void setupIter() {
seqiter_cls->freeze();
seqiter_cls->tpp_hasnext = seqiterHasnextUnboxed;
seqreviter_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedSeqIter), false, "reversed");
seqreviter_cls
= BoxedHeapClass::create(type_cls, object_cls, seqiterGCVisit, 0, 0, sizeof(BoxedSeqIter), false, "reversed");
seqreviter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
seqreviter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqreviterHasnext, BOXED_BOOL, 1)));
......
......@@ -25,6 +25,7 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "gc/roots.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
......@@ -423,23 +424,21 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
size_t v_size;
Box** v_elts;
RootedBox v_as_seq((Box*)nullptr);
if (!v) {
v_size = 0;
v_elts = NULL;
} else if (v->cls == list_cls || isSubclass(v->cls, list_cls)) {
BoxedList* lv = static_cast<BoxedList*>(v);
v_size = lv->size;
} else {
v_as_seq = RootedBox(PySequence_Fast(v, "can only assign an iterable"));
if (v_as_seq == NULL)
throwCAPIException();
v_size = PySequence_Fast_GET_SIZE(v_as_seq);
// If lv->size is 0, lv->elts->elts is garbage
if (v_size)
v_elts = lv->elts->elts;
v_elts = PySequence_Fast_ITEMS(v_as_seq);
else
v_elts = NULL;
} else if (v->cls == tuple_cls || isSubclass(v->cls, tuple_cls)) {
BoxedTuple* tv = static_cast<BoxedTuple*>(v);
v_size = tv->size();
v_elts = &tv->elts[0];
} else {
RELEASE_ASSERT(0, "unsupported type for list slice assignment: '%s'", getTypeName(v));
}
// If self->size is 0, self->elts->elts is garbage
......@@ -542,6 +541,8 @@ extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) {
}
Box* listMul(BoxedList* self, Box* rhs) {
STAT_TIMER(t0, "us_timer_listMul");
if (rhs->cls != int_cls) {
raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs));
}
......@@ -961,7 +962,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
}
Box* listLt(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented;
}
......@@ -971,7 +972,7 @@ Box* listLt(BoxedList* self, Box* rhs) {
}
Box* listLe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented;
}
......@@ -981,7 +982,7 @@ Box* listLe(BoxedList* self, Box* rhs) {
}
Box* listGt(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented;
}
......@@ -991,7 +992,7 @@ Box* listGt(BoxedList* self, Box* rhs) {
}
Box* listGe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented;
}
......
......@@ -116,7 +116,48 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(PyObject* vv) noe
}
extern "C" PY_LONG_LONG PyLong_AsLongLong(PyObject* vv) noexcept {
Py_FatalError("unimplemented");
PY_LONG_LONG bytes;
int one = 1;
int res;
if (vv == NULL) {
PyErr_BadInternalCall();
return -1;
}
if (!PyLong_Check(vv)) {
PyNumberMethods* nb;
PyObject* io;
if (PyInt_Check(vv))
return (PY_LONG_LONG)PyInt_AsLong(vv);
if ((nb = vv->cls->tp_as_number) == NULL || nb->nb_int == NULL) {
PyErr_SetString(PyExc_TypeError, "an integer is required");
return -1;
}
io = (*nb->nb_int)(vv);
if (io == NULL)
return -1;
if (PyInt_Check(io)) {
bytes = PyInt_AsLong(io);
Py_DECREF(io);
return bytes;
}
if (PyLong_Check(io)) {
bytes = PyLong_AsLongLong(io);
Py_DECREF(io);
return bytes;
}
Py_DECREF(io);
PyErr_SetString(PyExc_TypeError, "integer conversion failed");
return -1;
}
res = _PyLong_AsByteArray((PyLongObject*)vv, (unsigned char*)&bytes, SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
/* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
if (res < 0)
return (PY_LONG_LONG)-1;
else
return bytes;
}
extern "C" PY_LONG_LONG PyLong_AsLongLongAndOverflow(PyObject* obj, int* overflow) noexcept {
......@@ -442,7 +483,12 @@ extern "C" void* PyLong_AsVoidPtr(PyObject* vv) noexcept {
extern "C" int _PyLong_AsByteArray(PyLongObject* v, unsigned char* bytes, size_t n, int little_endian,
int is_signed) noexcept {
Py_FatalError("unimplemented");
RELEASE_ASSERT(little_endian == 1, "not implemented");
RELEASE_ASSERT(n == 8, "did not yet check if the behaviour is correct for sizes other than 8");
size_t count = 0;
mpz_export(bytes, &count, -1, n, 0, 0, ((BoxedLong*)v)->n);
RELEASE_ASSERT(count <= n, "overflow handling is not yet implemented");
return 0;
}
extern "C" PyObject* _PyLong_FromByteArray(const unsigned char* bytes, size_t n, int little_endian,
......
This diff is collapsed.
......@@ -183,7 +183,13 @@ inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int
// The `globals` argument can be either a BoxedModule or a BoxedDict
// Corresponds to a name lookup with GLOBAL scope. Checks the passed globals object, then the builtins,
// and if not found raises an exception.
extern "C" Box* getGlobal(Box* globals, const std::string* name);
// Checks for the name just in the passed globals object, and returns NULL if it is not found.
// This includes if the globals object defined a custom __getattr__ method that threw an AttributeError.
Box* getFromGlobals(Box* globals, llvm::StringRef name);
void setGlobal(Box* globals, llvm::StringRef name, Box* value);
extern "C" void delGlobal(Box* globals, const std::string* name);
extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val);
......
......@@ -96,6 +96,7 @@ void unwindExc(Box* exc_obj) {
void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__));
void raiseRaw(const ExcInfo& e) {
STAT_TIMER(t0, "us_timer_raiseraw");
// Should set these to None before getting here:
assert(e.type);
assert(e.value);
......@@ -197,6 +198,7 @@ extern "C" void abort() {
__builtin_unreachable();
}
#if 0
extern "C" void exit(int code) {
static void (*libc_exit)(int) = (void (*)(int))dlsym(RTLD_NEXT, "exit");
......@@ -218,6 +220,7 @@ extern "C" void exit(int code) {
libc_exit(code);
__builtin_unreachable();
}
#endif
extern "C" void raise0() {
ExcInfo* exc_info = getFrameExcInfo();
......
......@@ -1112,6 +1112,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
}
extern "C" Box* strMul(BoxedString* lhs, Box* rhs) {
STAT_TIMER(t0, "us_timer_strMul");
assert(isSubclass(lhs->cls, str_cls));
int n;
......@@ -1514,6 +1515,7 @@ failed:
}
extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
STAT_TIMER(t0, "us_timer_unicodeHashUnboxed");
if (self->hash != -1)
return self->hash;
......@@ -1524,6 +1526,7 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
}
extern "C" Box* strHash(BoxedString* self) {
STAT_TIMER(t0, "us_timer_strHash");
assert(isSubclass(self->cls, str_cls));
StringHash<char> H;
......@@ -2302,8 +2305,17 @@ extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexce
return boxStrConstantSize(s, n);
}
static /*const*/ char* string_getbuffer(register PyObject* op) noexcept {
char* s;
Py_ssize_t len;
if (PyString_AsStringAndSize(op, &s, &len))
return NULL;
return s;
}
extern "C" char* PyString_AsString(PyObject* o) noexcept {
RELEASE_ASSERT(isSubclass(o->cls, str_cls), "");
if (!PyString_Check(o))
return string_getbuffer(o);
BoxedString* s = static_cast<BoxedString*>(o);
return getWriteableStringContents(s);
......
......@@ -168,6 +168,7 @@ Box* tupleAdd(BoxedTuple* self, Box* rhs) {
}
Box* tupleMul(BoxedTuple* self, Box* rhs) {
STAT_TIMER(t0, "us_timer_tupleMul");
if (rhs->cls != int_cls) {
raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs));
}
......@@ -337,6 +338,7 @@ Box* tupleIndex(BoxedTuple* self, Box* elt) {
}
Box* tupleHash(BoxedTuple* self) {
STAT_TIMER(t0, "us_timer_tupleHash");
assert(isSubclass(self->cls, tuple_cls));
int64_t rtn = 3527539;
......
......@@ -978,7 +978,39 @@ Box* sliceRepr(BoxedSlice* self) {
extern "C" int PySlice_GetIndices(PySliceObject* r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
Py_ssize_t* step) noexcept {
Py_FatalError("unimplemented");
/* XXX support long ints */
if (r->step == Py_None) {
*step = 1;
} else {
if (!PyInt_Check(r->step) && !PyLong_Check(r->step))
return -1;
*step = PyInt_AsSsize_t(r->step);
}
if (r->start == Py_None) {
*start = *step < 0 ? length - 1 : 0;
} else {
if (!PyInt_Check(r->start) && !PyLong_Check(r->step))
return -1;
*start = PyInt_AsSsize_t(r->start);
if (*start < 0)
*start += length;
}
if (r->stop == Py_None) {
*stop = *step < 0 ? -1 : length;
} else {
if (!PyInt_Check(r->stop) && !PyLong_Check(r->step))
return -1;
*stop = PyInt_AsSsize_t(r->stop);
if (*stop < 0)
*stop += length;
}
if (*stop > length)
return -1;
if (*start >= length)
return -1;
if (*step == 0)
return -1;
return 0;
}
extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
......@@ -1238,6 +1270,8 @@ public:
}
static Box* setitem(Box* _self, Box* _key, Box* value) {
STAT_TIMER(t0, "us_timer_AttrWrapper_setitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1250,6 +1284,7 @@ public:
}
static Box* setdefault(Box* _self, Box* _key, Box* value) {
STAT_TIMER(t0, "us_timer_AttrWrapper_setdefault");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1265,6 +1300,7 @@ public:
}
static Box* get(Box* _self, Box* _key, Box* def) {
STAT_TIMER(t0, "us_timer_AttrWrapper_get");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1279,6 +1315,7 @@ public:
}
static Box* getitem(Box* _self, Box* _key) {
STAT_TIMER(t0, "us_timer_AttrWrapper_getitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1312,6 +1349,7 @@ public:
}
static Box* delitem(Box* _self, Box* _key) {
STAT_TIMER(t0, "us_timer_AttrWrapper_delitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1377,6 +1415,7 @@ public:
}
static Box* values(Box* _self) {
STAT_TIMER(t0, "us_timer_AttrWrapper_values");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1391,6 +1430,7 @@ public:
}
static Box* items(Box* _self) {
STAT_TIMER(t0, "us_timer_AttrWrapper_items");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -1429,6 +1469,7 @@ public:
}
static Box* update(Box* _self, Box* _container) {
STAT_TIMER(t0, "us_timer_AttrWrapper_update");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......
......@@ -410,12 +410,37 @@ public:
size_t size() { return s.size(); }
void* operator new(size_t size, size_t ssize) __attribute__((visibility("default"))) {
#if STAT_ALLOCATIONS
static StatCounter alloc_str("alloc.str");
static StatCounter alloc_str1("alloc.str(1)");
static StatCounter allocsize_str("allocsize.str");
if (ssize == 1)
alloc_str1.log();
else
alloc_str.log();
allocsize_str.log(str_cls->tp_basicsize + ssize + 1);
#endif
Box* rtn = static_cast<Box*>(gc_alloc(str_cls->tp_basicsize + ssize + 1, gc::GCKind::PYTHON));
rtn->cls = str_cls;
return rtn;
}
void* operator new(size_t size, BoxedClass* cls, size_t ssize) __attribute__((visibility("default"))) {
#if STAT_ALLOCATIONS
static StatCounter alloc_str("alloc.str");
static StatCounter alloc_str1("alloc.str(1)");
static StatCounter allocsize_str("allocsize.str");
if (ssize == 1)
alloc_str1.log();
else
alloc_str.log();
allocsize_str.log(cls->tp_basicsize + ssize + 1);
#endif
Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, ssize + 1));
rtn->cls = cls;
return rtn;
......@@ -517,12 +542,43 @@ public:
Box** elts;
void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) {
#if STAT_ALLOCATIONS
static StatCounter alloc_tuple("alloc.tuple");
static StatCounter alloc_tuple0("alloc.tuple(0)");
static StatCounter allocsize_tuple("allocsize.tuple");
static StatCounter allocsize_tuple0("allocsize.tuple(0)");
if (nelts == 0) {
alloc_tuple0.log();
allocsize_tuple0.log(_PyObject_VAR_SIZE(tuple_cls, nelts + 1));
} else {
alloc_tuple.log();
allocsize_tuple.log(_PyObject_VAR_SIZE(tuple_cls, nelts + 1));
}
#endif
Box* rtn = static_cast<Box*>(gc_alloc(_PyObject_VAR_SIZE(tuple_cls, nelts + 1), gc::GCKind::PYTHON));
rtn->cls = tuple_cls;
return rtn;
}
void* operator new(size_t size, BoxedClass* cls, size_t nelts) __attribute__((visibility("default"))) {
#if STAT_ALLOCATIONS
static StatCounter alloc_tuple("alloc.tuple");
static StatCounter alloc_tuple0("alloc.tuple(0)");
static StatCounter allocsize_tuple("allocsize.tuple");
static StatCounter allocsize_tuple0("allocsize.tuple(0)");
if (nelts == 0) {
alloc_tuple0.log();
allocsize_tuple0.log(_PyObject_VAR_SIZE(cls, nelts + 1));
} else {
alloc_tuple.log();
allocsize_tuple.log(_PyObject_VAR_SIZE(cls, nelts + 1));
}
#endif
Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, nelts));
rtn->cls = cls;
return rtn;
......@@ -817,6 +873,11 @@ public:
struct Context* context, *returnContext;
void* stack_begin;
#if STAT_TIMERS
StatTimer* statTimers;
uint64_t timer_time;
#endif
BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
DEFAULT_CLASS(generator_cls);
......
......@@ -21,9 +21,10 @@ set -e
set -ux
python -c 'import __future__'
python -c 'import sys; print sys.executable'
pip install bcrypt==1.1.0 python-gflags==2.0
pip install bcrypt==1.1.0 python-gflags==2.0 sqlalchemy==1.0.0
python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"'
python -c 'import gflags; print "gflags imports"'
python -c 'import sqlalchemy; print "sqlalchemy imports"'
""".strip()
# print sh_script
......
......@@ -105,8 +105,8 @@ print callable(lambda: 1)
print range(5L, 7L)
print round(-1.1), round(-1.9)
print round(0.5), round(-0.5)
for n in [0, 1, 2, 3, 4, 5]:
print round(-1.1, n), round(-1.9, n), round(0.5, n), round(-0.5, n), round(-0.123456789, n)
print list(iter(xrange(100).__iter__().next, 20))
......
import test_package.import_target
import import_target
print
s = """
import import_target
print import_target.__file__.replace(".pyc", ".py")
"""
def test(g):
print "Testing with globals:", "None" if g is None else ("globals" if g is globals() else sorted(g.items()))
print __import__("import_target", g).__file__.replace(".pyc", ".py")
exec s in g
print "Resulting globals:", "None" if g is None else ("globals" if g is globals() else sorted(g.keys()))
print
test(None)
test(globals())
test({"__package__":"test_package"})
test({"__name__":"test_package.foo"})
test({"__name__":"test_package"})
test({"__name__":"test_package", "__path__":"foo"})
......@@ -66,6 +66,9 @@ class L(object):
print type(int(L()))
print int(u'123')
print int("9223372036854775808", 0)
print 1 << 63, 1 << 64, -1 << 63, -1 << 64, 2 << 63
print type(1 << 63), type(1 << 64), type(-1 << 63), type(-1 << 64), type(2 << 63)
for b in range(26):
try:
......
......@@ -124,7 +124,13 @@ for i in xrange(3):
l[j:k] = ["added"]
print i, j, k, l
def G():
yield "a"
yield "b"
yield "c"
l = [0, 1, 2, 3, 4, 5]
l[1:] = G()
print l
l = [1, 3, 5, 7, 2, 4]
print l.sort(key=lambda x:x%3)
......
......@@ -13,5 +13,26 @@ print len(MyList.__new__(MyList))
l[:] = l[:]
print l
print [1,2,3] == MyList((1,2,3))
print [1,2,3] != MyList((1,2,3))
print [1,2,3] == MyList((1,2,3,4))
print [1,2,3] != MyList((1,2,3,4))
print [1,2,3,4] > MyList((1,2,3))
print [1,2,3,4] < MyList((1,2,3))
print [1,2,3] > MyList((1,2,3,4))
print [1,2,3] < MyList((1,2,3,4))
print [1,2,3] >= MyList((1,2,3))
print [1,2,3] <= MyList((1,2,3))
print MyList((1,2,3)) == MyList((1,2,3,4))
print MyList((1,2,3)) != MyList((1,2,3,4))
print MyList((1,2,3,4)) > MyList((1,2,3))
print MyList((1,2,3,4)) < MyList((1,2,3))
print MyList((1,2,3)) > MyList((1,2,3,4))
print MyList((1,2,3)) < MyList((1,2,3,4))
print MyList((1,2,3)) >= MyList((1,2,3))
print MyList((1,2,3)) <= MyList((1,2,3))
......@@ -157,6 +157,9 @@ def run_test(fn, check_stats, run_memcheck):
code = p.wait()
elapsed = time.time() - start
if code >= 128:
code -= 256
return determine_test_result(fn, opts, code, out, stderr, elapsed)
def get_test_options(fn, check_stats, run_memcheck):
......
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