Commit fb62db02 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'master' into HEAD

parents f2632e45 0defcec2
...@@ -112,12 +112,25 @@ ifeq ($(NEED_OLD_JIT),1) ...@@ -112,12 +112,25 @@ ifeq ($(NEED_OLD_JIT),1)
LLVM_LINK_LIBS += jit LLVM_LINK_LIBS += jit
endif 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_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_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/*) 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_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/*) 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 LLVM_CONFIG_RELEASE := $(LLVM_BUILD)/Release/bin/llvm-config
ifneq ($(wildcard $(LLVM_CONFIG_RELEASE)),) ifneq ($(wildcard $(LLVM_CONFIG_RELEASE)),)
...@@ -779,11 +792,16 @@ endef ...@@ -779,11 +792,16 @@ endef
PASS_SRCS := codegen/opt/aa.cpp PASS_SRCS := codegen/opt/aa.cpp
PASS_OBJS := $(PASS_SRCS:.cpp=.standalone.o) PASS_OBJS := $(PASS_SRCS:.cpp=.standalone.o)
ifneq ($(USE_CMAKE),1)
$(call make_compile_config,,$(CXXFLAGS_DBG)) $(call make_compile_config,,$(CXXFLAGS_DBG))
$(call make_compile_config,.release,$(CXXFLAGS_RELEASE)) $(call make_compile_config,.release,$(CXXFLAGS_RELEASE))
$(call make_compile_config,.grwl,$(CXXFLAGS_RELEASE) -DTHREADING_USE_GRWL=1 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_grwl) $(call make_compile_config,.grwl,$(CXXFLAGS_RELEASE) -DTHREADING_USE_GRWL=1 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_grwl)
$(call make_compile_config,.grwl_dbg,$(CXXFLAGS_DBG) -DTHREADING_USE_GRWL=1 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_grwl_dbg -UBINARY_STRIPPED_SUFFIX -DBINARY_STRIPPED_SUFFIX=) $(call make_compile_config,.grwl_dbg,$(CXXFLAGS_DBG) -DTHREADING_USE_GRWL=1 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_grwl_dbg -UBINARY_STRIPPED_SUFFIX -DBINARY_STRIPPED_SUFFIX=)
$(call make_compile_config,.nosync,$(CXXFLAGS_RELEASE) -DTHREADING_USE_GRWL=0 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_nosync) $(call make_compile_config,.nosync,$(CXXFLAGS_RELEASE) -DTHREADING_USE_GRWL=0 -DTHREADING_USE_GIL=0 -UBINARY_SUFFIX -DBINARY_SUFFIX=_nosync)
else
%.o: %.cpp $(CMAKE_SETUP_DBG)
$(NINJA) -C $(HOME)/pyston-build-dbg src/CMakeFiles/PYSTON_OBJECTS.dir/$(patsubst src/%.o,%.cpp.o,$@) $(NINJAFLAGS)
endif
$(UNITTEST_SRCS:.cpp=.o): CXXFLAGS += -isystem $(GTEST_DIR)/include $(UNITTEST_SRCS:.cpp=.o): CXXFLAGS += -isystem $(GTEST_DIR)/include
......
...@@ -61,6 +61,9 @@ ...@@ -61,6 +61,9 @@
#define HAVE_STRUCT_TM_TM_ZONE 1 #define HAVE_STRUCT_TM_TM_ZONE 1
#define HAVE_MKTIME 1 #define HAVE_MKTIME 1
#define TIME_WITH_SYS_TIME
#define HAVE_GETTIMEOFDAY 1
#define PY_FORMAT_LONG_LONG "ll" #define PY_FORMAT_LONG_LONG "ll"
#define PY_FORMAT_SIZE_T "z" #define PY_FORMAT_SIZE_T "z"
......
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,)
...@@ -76,14 +76,21 @@ private: ...@@ -76,14 +76,21 @@ private:
} }
} }
Status::Usage getStatusFirst(InternedString name) const {
auto it = statuses.find(name);
if (it == statuses.end())
return Status::NONE;
return it->second.first;
}
public: public:
LivenessBBVisitor(LivenessAnalysis* analysis) : analysis(analysis) {} LivenessBBVisitor(LivenessAnalysis* analysis) : analysis(analysis) {}
bool firstIsUse(InternedString name) { return statuses[name].first == Status::USED; } bool firstIsUse(InternedString name) const { return getStatusFirst(name) == Status::USED; }
bool firstIsDef(InternedString name) { return statuses[name].first == Status::DEFINED; } bool firstIsDef(InternedString name) const { return getStatusFirst(name) == Status::DEFINED; }
bool isKilledAt(AST_Name* node, bool is_live_at_end) { bool isKilledAt(AST_Name* node, bool is_live_at_end) const {
if (kills.count(node)) if (kills.count(node))
return true; return true;
...@@ -163,6 +170,9 @@ LivenessAnalysis::LivenessAnalysis(CFG* cfg) : cfg(cfg) { ...@@ -163,6 +170,9 @@ LivenessAnalysis::LivenessAnalysis(CFG* cfg) : cfg(cfg) {
us_liveness.log(_t.end()); us_liveness.log(_t.end());
} }
LivenessAnalysis::~LivenessAnalysis() {
}
bool LivenessAnalysis::isKill(AST_Name* node, CFGBlock* parent_block) { bool LivenessAnalysis::isKill(AST_Name* node, CFGBlock* parent_block) {
if (node->id.str()[0] != '#') if (node->id.str()[0] != '#')
return false; return false;
...@@ -487,11 +497,18 @@ bool PhiAnalysis::isPotentiallyUndefinedAt(InternedString name, CFGBlock* block) ...@@ -487,11 +497,18 @@ bool PhiAnalysis::isPotentiallyUndefinedAt(InternedString name, CFGBlock* block)
return definedness.defined_at_beginning[block][name] != DefinednessAnalysis::Defined; return definedness.defined_at_beginning[block][name] != DefinednessAnalysis::Defined;
} }
LivenessAnalysis* computeLivenessInfo(CFG* cfg) { std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG* cfg) {
return new LivenessAnalysis(cfg); static StatCounter counter("num_liveness_analysis");
counter.log();
return std::unique_ptr<LivenessAnalysis>(new LivenessAnalysis(cfg));
} }
PhiAnalysis* computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info) { std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnalysis* liveness,
ScopeInfo* scope_info) {
static StatCounter counter("num_phi_analysis");
counter.log();
llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map; llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map;
for (auto e : args.args) for (auto e : args.args)
...@@ -501,11 +518,15 @@ PhiAnalysis* computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnaly ...@@ -501,11 +518,15 @@ PhiAnalysis* computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnaly
if (args.kwarg.size()) if (args.kwarg.size())
initial_map[scope_info->internString(args.kwarg)] = DefinednessAnalysis::Defined; initial_map[scope_info->internString(args.kwarg)] = DefinednessAnalysis::Defined;
return new PhiAnalysis(std::move(initial_map), cfg->getStartingBlock(), false, liveness, scope_info); return std::unique_ptr<PhiAnalysis>(
new PhiAnalysis(std::move(initial_map), cfg->getStartingBlock(), false, liveness, scope_info));
} }
PhiAnalysis* computeRequiredPhis(const OSREntryDescriptor* entry_descriptor, LivenessAnalysis* liveness, std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry_descriptor, LivenessAnalysis* liveness,
ScopeInfo* scope_info) { ScopeInfo* scope_info) {
static StatCounter counter("num_phi_analysis");
counter.log();
llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map; llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map;
llvm::StringSet<> potentially_undefined; llvm::StringSet<> potentially_undefined;
...@@ -524,6 +545,7 @@ PhiAnalysis* computeRequiredPhis(const OSREntryDescriptor* entry_descriptor, Liv ...@@ -524,6 +545,7 @@ PhiAnalysis* computeRequiredPhis(const OSREntryDescriptor* entry_descriptor, Liv
initial_map[p.first] = DefinednessAnalysis::Defined; initial_map[p.first] = DefinednessAnalysis::Defined;
} }
return new PhiAnalysis(std::move(initial_map), entry_descriptor->backedge->target, true, liveness, scope_info); return std::unique_ptr<PhiAnalysis>(
new PhiAnalysis(std::move(initial_map), entry_descriptor->backedge->target, true, liveness, scope_info));
} }
} }
...@@ -45,6 +45,7 @@ private: ...@@ -45,6 +45,7 @@ private:
public: public:
LivenessAnalysis(CFG* cfg); LivenessAnalysis(CFG* cfg);
~LivenessAnalysis();
// we don't keep track of node->parent_block relationships, so you have to pass both: // we don't keep track of node->parent_block relationships, so you have to pass both:
bool isKill(AST_Name* node, CFGBlock* parent_block); bool isKill(AST_Name* node, CFGBlock* parent_block);
...@@ -105,9 +106,9 @@ public: ...@@ -105,9 +106,9 @@ public:
bool isPotentiallyUndefinedAt(InternedString name, CFGBlock* block); bool isPotentiallyUndefinedAt(InternedString name, CFGBlock* block);
}; };
LivenessAnalysis* computeLivenessInfo(CFG*); std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG*);
PhiAnalysis* computeRequiredPhis(const ParamNames&, CFG*, LivenessAnalysis*, ScopeInfo* scope_info); std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames&, CFG*, LivenessAnalysis*, ScopeInfo* scope_info);
PhiAnalysis* computeRequiredPhis(const OSREntryDescriptor*, LivenessAnalysis*, ScopeInfo* scope_info); std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor*, LivenessAnalysis*, ScopeInfo* scope_info);
} }
#endif #endif
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
namespace pyston { namespace pyston {
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) { 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]); BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
assert(self->cls == method_cls); assert(self->cls == method_cls);
......
...@@ -58,6 +58,7 @@ static int hackcheck(PyObject* self, setattrofunc func, const char* what) noexce ...@@ -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 { static PyObject* wrap_setattr(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_setattr");
setattrofunc func = (setattrofunc)wrapped; setattrofunc func = (setattrofunc)wrapped;
int res; int res;
PyObject* name, *value; PyObject* name, *value;
...@@ -74,6 +75,7 @@ static PyObject* wrap_setattr(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_delattr(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delattr");
setattrofunc func = (setattrofunc)wrapped; setattrofunc func = (setattrofunc)wrapped;
int res; int res;
PyObject* name; PyObject* name;
...@@ -91,6 +93,7 @@ static PyObject* wrap_delattr(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_hashfunc");
hashfunc func = (hashfunc)wrapped; hashfunc func = (hashfunc)wrapped;
long res; long res;
...@@ -103,12 +106,14 @@ static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) no ...@@ -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 { static PyObject* wrap_call(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_wrap_call");
ternaryfunc func = (ternaryfunc)wrapped; ternaryfunc func = (ternaryfunc)wrapped;
return (*func)(self, args, kwds); return (*func)(self, args, kwds);
} }
static PyObject* wrap_richcmpfunc(PyObject* self, PyObject* args, void* wrapped, int op) noexcept { static PyObject* wrap_richcmpfunc(PyObject* self, PyObject* args, void* wrapped, int op) noexcept {
STAT_TIMER(t0, "us_timer_wrap_richcmpfunc");
richcmpfunc func = (richcmpfunc)wrapped; richcmpfunc func = (richcmpfunc)wrapped;
PyObject* other; PyObject* other;
...@@ -132,6 +137,7 @@ RICHCMP_WRAPPER(gt, Py_GT) ...@@ -132,6 +137,7 @@ RICHCMP_WRAPPER(gt, Py_GT)
RICHCMP_WRAPPER(ge, Py_GE) RICHCMP_WRAPPER(ge, Py_GE)
static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) { static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) {
STAT_TIMER(t0, "us_timer_wrap_next");
unaryfunc func = (unaryfunc)wrapped; unaryfunc func = (unaryfunc)wrapped;
PyObject* res; PyObject* res;
...@@ -144,6 +150,7 @@ static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) { ...@@ -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 { static PyObject* wrap_descr_get(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_descr_get");
descrgetfunc func = (descrgetfunc)wrapped; descrgetfunc func = (descrgetfunc)wrapped;
PyObject* obj; PyObject* obj;
PyObject* type = NULL; PyObject* type = NULL;
...@@ -162,6 +169,7 @@ static PyObject* wrap_descr_get(PyObject* self, PyObject* args, void* wrapped) n ...@@ -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 { static PyObject* wrap_coercefunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_coercefunc");
coercion func = (coercion)wrapped; coercion func = (coercion)wrapped;
PyObject* other, *res; PyObject* other, *res;
int ok; int ok;
...@@ -188,6 +196,7 @@ static PyObject* wrap_coercefunc(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_ternaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ternaryfunc");
ternaryfunc func = (ternaryfunc)wrapped; ternaryfunc func = (ternaryfunc)wrapped;
PyObject* other; PyObject* other;
PyObject* third = Py_None; PyObject* third = Py_None;
...@@ -200,6 +209,7 @@ static PyObject* wrap_ternaryfunc(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_ternaryfunc_r(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ternaryfunc_r");
ternaryfunc func = (ternaryfunc)wrapped; ternaryfunc func = (ternaryfunc)wrapped;
PyObject* other; PyObject* other;
PyObject* third = Py_None; PyObject* third = Py_None;
...@@ -212,6 +222,7 @@ static PyObject* wrap_ternaryfunc_r(PyObject* self, PyObject* args, void* wrappe ...@@ -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 { static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_unaryfunc");
unaryfunc func = (unaryfunc)wrapped; unaryfunc func = (unaryfunc)wrapped;
if (!check_num_args(args, 0)) if (!check_num_args(args, 0))
...@@ -220,6 +231,7 @@ static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) n ...@@ -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 { static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_inquirypred");
inquiry func = (inquiry)wrapped; inquiry func = (inquiry)wrapped;
int res; int res;
...@@ -232,6 +244,7 @@ static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped) ...@@ -232,6 +244,7 @@ static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped)
} }
static PyObject* wrapInquirypred(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; inquiry func = (inquiry)wrapped;
int res; int res;
...@@ -244,6 +257,7 @@ static PyObject* wrapInquirypred(PyObject* self, PyObject* args, void* wrapped) ...@@ -244,6 +257,7 @@ static PyObject* wrapInquirypred(PyObject* self, PyObject* args, void* wrapped)
} }
static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept { static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc");
binaryfunc func = (binaryfunc)wrapped; binaryfunc func = (binaryfunc)wrapped;
PyObject* other; PyObject* other;
...@@ -254,6 +268,7 @@ static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_binaryfunc_l(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc_l");
binaryfunc func = (binaryfunc)wrapped; binaryfunc func = (binaryfunc)wrapped;
PyObject* other; PyObject* other;
...@@ -268,6 +283,7 @@ static PyObject* wrap_binaryfunc_l(PyObject* self, PyObject* args, void* wrapped ...@@ -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 { static PyObject* wrap_binaryfunc_r(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_binaryfunc_r");
binaryfunc func = (binaryfunc)wrapped; binaryfunc func = (binaryfunc)wrapped;
PyObject* other; PyObject* other;
...@@ -300,6 +316,7 @@ static Py_ssize_t getindex(PyObject* self, PyObject* arg) noexcept { ...@@ -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 { static PyObject* wrap_lenfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_lenfunc");
lenfunc func = (lenfunc)wrapped; lenfunc func = (lenfunc)wrapped;
Py_ssize_t res; Py_ssize_t res;
...@@ -312,6 +329,7 @@ static PyObject* wrap_lenfunc(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_indexargfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_indexargfunc");
ssizeargfunc func = (ssizeargfunc)wrapped; ssizeargfunc func = (ssizeargfunc)wrapped;
PyObject* o; PyObject* o;
Py_ssize_t i; Py_ssize_t i;
...@@ -325,6 +343,7 @@ static PyObject* wrap_indexargfunc(PyObject* self, PyObject* args, void* wrapped ...@@ -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 { static PyObject* wrap_sq_item(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_item");
ssizeargfunc func = (ssizeargfunc)wrapped; ssizeargfunc func = (ssizeargfunc)wrapped;
PyObject* arg; PyObject* arg;
Py_ssize_t i; Py_ssize_t i;
...@@ -342,6 +361,7 @@ static PyObject* wrap_sq_item(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_ssizessizeargfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ssizessizeargfunc");
ssizessizeargfunc func = (ssizessizeargfunc)wrapped; ssizessizeargfunc func = (ssizessizeargfunc)wrapped;
Py_ssize_t i, j; Py_ssize_t i, j;
...@@ -351,6 +371,7 @@ static PyObject* wrap_ssizessizeargfunc(PyObject* self, PyObject* args, void* wr ...@@ -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 { static PyObject* wrap_sq_setitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_setitem");
ssizeobjargproc func = (ssizeobjargproc)wrapped; ssizeobjargproc func = (ssizeobjargproc)wrapped;
Py_ssize_t i; Py_ssize_t i;
int res; int res;
...@@ -369,6 +390,7 @@ static PyObject* wrap_sq_setitem(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_sq_delitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_sq_delitem");
ssizeobjargproc func = (ssizeobjargproc)wrapped; ssizeobjargproc func = (ssizeobjargproc)wrapped;
Py_ssize_t i; Py_ssize_t i;
int res; int res;
...@@ -388,6 +410,7 @@ static PyObject* wrap_sq_delitem(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_ssizessizeobjargproc");
ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped; ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
Py_ssize_t i, j; Py_ssize_t i, j;
int res; int res;
...@@ -403,6 +426,7 @@ static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void* ...@@ -403,6 +426,7 @@ static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void*
} }
static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) noexcept { static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delslice");
ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped; ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
Py_ssize_t i, j; Py_ssize_t i, j;
int res; int res;
...@@ -418,6 +442,7 @@ static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) no ...@@ -418,6 +442,7 @@ static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) no
/* XXX objobjproc is a misnomer; should be objargpred */ /* XXX objobjproc is a misnomer; should be objargpred */
static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped) noexcept { static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_objobjproc");
objobjproc func = (objobjproc)wrapped; objobjproc func = (objobjproc)wrapped;
int res; int res;
PyObject* value; PyObject* value;
...@@ -433,6 +458,7 @@ static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped) ...@@ -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 { static PyObject* wrap_objobjargproc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_objobjargproc");
objobjargproc func = (objobjargproc)wrapped; objobjargproc func = (objobjargproc)wrapped;
int res; int res;
PyObject* key, *value; PyObject* key, *value;
...@@ -447,6 +473,7 @@ static PyObject* wrap_objobjargproc(PyObject* self, PyObject* args, void* wrappe ...@@ -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 { static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_delitem");
objobjargproc func = (objobjargproc)wrapped; objobjargproc func = (objobjargproc)wrapped;
int res; int res;
PyObject* key; PyObject* key;
...@@ -462,6 +489,7 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
STAT_TIMER(t0, "us_timer_wrap_cmpfunc");
cmpfunc func = (cmpfunc)wrapped; cmpfunc func = (cmpfunc)wrapped;
int res; int res;
PyObject* other; PyObject* other;
...@@ -482,6 +510,7 @@ static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noe ...@@ -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 { static PyObject* wrap_init(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_wrap_init");
initproc func = (initproc)wrapped; initproc func = (initproc)wrapped;
if (func(self, args, kwds) < 0) if (func(self, args, kwds) < 0)
......
...@@ -54,6 +54,7 @@ public: ...@@ -54,6 +54,7 @@ public:
} }
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs) { static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs) {
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__");
assert(self->cls == capifunc_cls); assert(self->cls == capifunc_cls);
assert(varargs->cls == tuple_cls); assert(varargs->cls == tuple_cls);
assert(kwargs->cls == dict_cls); assert(kwargs->cls == dict_cls);
...@@ -111,6 +112,8 @@ public: ...@@ -111,6 +112,8 @@ public:
DEFAULT_CLASS(wrapperobject_cls); DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) { static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) {
STAT_TIMER(t0, "us_timer_boxedwrapperobject__call__");
assert(self->cls == wrapperobject_cls); assert(self->cls == wrapperobject_cls);
assert(args->cls == tuple_cls); assert(args->cls == tuple_cls);
assert(kwds->cls == dict_cls); assert(kwds->cls == dict_cls);
......
...@@ -83,7 +83,6 @@ private: ...@@ -83,7 +83,6 @@ private:
Value doBinOp(Box* left, Box* right, int op, BinExpType exp_type); Value doBinOp(Box* left, Box* right, int op, BinExpType exp_type);
void doStore(AST_expr* node, Value value); void doStore(AST_expr* node, Value value);
void doStore(InternedString name, Value value); void doStore(InternedString name, Value value);
void eraseDeadSymbols();
Value visit_assert(AST_Assert* node); Value visit_assert(AST_Assert* node);
Value visit_assign(AST_Assign* node); Value visit_assign(AST_Assign* node);
...@@ -285,6 +284,8 @@ public: ...@@ -285,6 +284,8 @@ public:
Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block, AST_stmt* start_at) { Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block, AST_stmt* start_at) {
threading::allowGLReadPreemption(); threading::allowGLReadPreemption();
STAT_TIMER(t0, "us_timer_astinterpreter_execute");
void* frame_addr = __builtin_frame_address(0); void* frame_addr = __builtin_frame_address(0);
RegisterHelper frame_registerer(&interpreter, frame_addr); RegisterHelper frame_registerer(&interpreter, frame_addr);
...@@ -321,31 +322,6 @@ Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block ...@@ -321,31 +322,6 @@ Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block
return v; return v;
} }
void ASTInterpreter::eraseDeadSymbols() {
if (source_info->liveness == NULL)
source_info->liveness = computeLivenessInfo(source_info->cfg);
if (this->phis == NULL) {
PhiAnalysis*& phis = source_info->phis[/* entry_descriptor = */ NULL];
if (!phis)
phis = computeRequiredPhis(compiled_func->clfunc->param_names, source_info->cfg, source_info->liveness,
scope_info);
this->phis = phis;
}
std::vector<InternedString> dead_symbols;
for (auto& it : sym_table) {
if (!source_info->liveness->isLiveAtEnd(it.first, current_block)) {
dead_symbols.push_back(it.first);
} else if (phis->isRequiredAfter(it.first, current_block)) {
assert(scope_info->getScopeTypeOfName(it.first) != ScopeInfo::VarScopeType::GLOBAL);
} else {
}
}
for (auto&& dead : dead_symbols)
sym_table.erase(dead);
}
Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type) { Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type) {
if (op == AST_TYPE::Div && (source_info->parent_module->future_flags & FF_DIVISION)) { if (op == AST_TYPE::Div && (source_info->parent_module->future_flags & FF_DIVISION)) {
op = AST_TYPE::TrueDiv; op = AST_TYPE::TrueDiv;
...@@ -463,7 +439,26 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -463,7 +439,26 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
if (ENABLE_OSR && backedge && (globals->cls == module_cls)) { if (ENABLE_OSR && backedge && (globals->cls == module_cls)) {
bool can_osr = !FORCE_INTERPRETER && (globals->cls == module_cls); bool can_osr = !FORCE_INTERPRETER && (globals->cls == module_cls);
if (can_osr && edgecount++ == OSR_THRESHOLD_INTERPRETER) { if (can_osr && edgecount++ == OSR_THRESHOLD_INTERPRETER) {
eraseDeadSymbols(); static StatCounter ast_osrs("num_ast_osrs");
ast_osrs.log();
// TODO: we will immediately want the liveness info again in the jit, we should pass
// it through.
std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(source_info->cfg);
std::unique_ptr<PhiAnalysis> phis
= computeRequiredPhis(compiled_func->clfunc->param_names, source_info->cfg, liveness.get(), scope_info);
std::vector<InternedString> dead_symbols;
for (auto& it : sym_table) {
if (!liveness->isLiveAtEnd(it.first, current_block)) {
dead_symbols.push_back(it.first);
} else if (phis->isRequiredAfter(it.first, current_block)) {
assert(scope_info->getScopeTypeOfName(it.first) != ScopeInfo::VarScopeType::GLOBAL);
} else {
}
}
for (auto&& dead : dead_symbols)
sym_table.erase(dead);
const OSREntryDescriptor* found_entry = nullptr; const OSREntryDescriptor* found_entry = nullptr;
for (auto& p : compiled_func->clfunc->osr_versions) { for (auto& p : compiled_func->clfunc->osr_versions) {
...@@ -479,7 +474,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -479,7 +474,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
for (auto& name : phis->definedness.getDefinedNamesAtEnd(current_block)) { for (auto& name : phis->definedness.getDefinedNamesAtEnd(current_block)) {
auto it = sym_table.find(name); auto it = sym_table.find(name);
if (!source_info->liveness->isLiveAtEnd(name, current_block)) if (!liveness->isLiveAtEnd(name, current_block))
continue; continue;
if (phis->isPotentiallyUndefinedAfter(name, current_block)) { if (phis->isPotentiallyUndefinedAfter(name, current_block)) {
...@@ -495,10 +490,14 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -495,10 +490,14 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
} }
} }
// Manually free these here, since we might not return from this scope for a long time.
liveness.reset(nullptr);
phis.reset(nullptr);
// LLVM has a limit on the number of operands a machine instruction can have (~255), // LLVM has a limit on the number of operands a machine instruction can have (~255),
// in order to not hit the limit with the patchpoints cancel OSR when we have a high number of symbols. // in order to not hit the limit with the patchpoints cancel OSR when we have a high number of symbols.
if (sorted_symbol_table.size() > 225) { if (sorted_symbol_table.size() > 225) {
static StatCounter times_osr_cancel("num_osr_cancel_to_many_syms"); static StatCounter times_osr_cancel("num_osr_cancel_too_many_syms");
times_osr_cancel.log(); times_osr_cancel.log();
next_block = node->target; next_block = node->target;
return Value(); return Value();
...@@ -543,6 +542,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -543,6 +542,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
arg_array.push_back(it.second); arg_array.push_back(it.second);
} }
STAT_TIMER(t0, "us_timer_astinterpreter_jump_osrexit");
CompiledFunction* partial_func = compilePartialFuncInternal(&exit); CompiledFunction* partial_func = compilePartialFuncInternal(&exit);
auto arg_tuple = getTupleFromArgsArray(&arg_array[0], arg_array.size()); 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), Box* r = partial_func->call(std::get<0>(arg_tuple), std::get<1>(arg_tuple), std::get<2>(arg_tuple),
...@@ -930,6 +930,8 @@ Value ASTInterpreter::visit_print(AST_Print* node) { ...@@ -930,6 +930,8 @@ Value ASTInterpreter::visit_print(AST_Print* node) {
static const std::string newline_str("\n"); static const std::string newline_str("\n");
static const std::string space_str(" "); static const std::string space_str(" ");
STAT_TIMER(t0, "us_timer_visit_print");
Box* dest = node->dest ? visit_expr(node->dest).o : getSysStdout(); Box* dest = node->dest ? visit_expr(node->dest).o : getSysStdout();
int nvals = node->values.size(); int nvals = node->values.size();
assert(nvals <= 1 && "cfg should have lowered it to 0 or 1 values"); assert(nvals <= 1 && "cfg should have lowered it to 0 or 1 values");
......
...@@ -35,8 +35,7 @@ namespace pyston { ...@@ -35,8 +35,7 @@ namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock); DS_DEFINE_RWLOCK(codegen_rwlock);
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn) SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn)
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), fn(std::move(fn)), : parent_module(m), scoping(scoping), ast(ast), cfg(NULL), fn(std::move(fn)), body(std::move(body)) {
body(std::move(body)) {
assert(this->fn.size()); assert(this->fn.size());
switch (ast->type) { switch (ast->type) {
......
...@@ -362,7 +362,7 @@ static void handle_sigint(int signum) { ...@@ -362,7 +362,7 @@ static void handle_sigint(int signum) {
// For now, just call abort(), so that we get a traceback at least. // For now, just call abort(), so that we get a traceback at least.
fprintf(stderr, "SIGINT!\n"); fprintf(stderr, "SIGINT!\n");
joinRuntime(); joinRuntime();
Stats::dump(); Stats::dump(false);
abort(); abort();
} }
......
...@@ -342,7 +342,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -342,7 +342,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
CompiledFunction* cf = irstate->getCurFunction(); CompiledFunction* cf = irstate->getCurFunction();
ConcreteCompilerType* rtn_type = irstate->getReturnType(); ConcreteCompilerType* rtn_type = irstate->getReturnType();
// llvm::MDNode* func_info = irstate->getFuncDbgInfo(); // llvm::MDNode* func_info = irstate->getFuncDbgInfo();
PhiAnalysis* phi_analysis = source->phis[entry_descriptor]; PhiAnalysis* phi_analysis = irstate->getPhis();
assert(phi_analysis); assert(phi_analysis);
if (entry_descriptor != NULL) if (entry_descriptor != NULL)
...@@ -1055,7 +1055,15 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O ...@@ -1055,7 +1055,15 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
computeBlockSetClosure(blocks); computeBlockSetClosure(blocks);
} }
IRGenState irstate(cf, source, source->phis[entry_descriptor], param_names, getGCBuilder(), dbg_funcinfo); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(source->cfg);
std::unique_ptr<PhiAnalysis> phis;
if (entry_descriptor)
phis = computeRequiredPhis(entry_descriptor, liveness.get(), source->getScopeInfo());
else
phis = computeRequiredPhis(*param_names, source->cfg, liveness.get(), source->getScopeInfo());
IRGenState irstate(cf, source, std::move(liveness), std::move(phis), param_names, getGCBuilder(), dbg_funcinfo);
emitBBs(&irstate, types, entry_descriptor, blocks); emitBBs(&irstate, types, entry_descriptor, blocks);
......
...@@ -182,6 +182,7 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) { ...@@ -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: // The codegen_lock needs to be held in W mode before calling this function:
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel effort, CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel effort,
const OSREntryDescriptor* entry_descriptor) { const OSREntryDescriptor* entry_descriptor) {
STAT_TIMER(t0, "us_timer_compileFunction");
Timer _t("for compileFunction()", 1000); Timer _t("for compileFunction()", 1000);
assert((entry_descriptor != NULL) + (spec != NULL) == 1); assert((entry_descriptor != NULL) + (spec != NULL) == 1);
...@@ -228,19 +229,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E ...@@ -228,19 +229,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
source->cfg = computeCFG(source, source->body); source->cfg = computeCFG(source, source->body);
} }
if (effort != EffortLevel::INTERPRETED) {
if (source->liveness == NULL)
source->liveness = computeLivenessInfo(source->cfg);
PhiAnalysis*& phis = source->phis[entry_descriptor];
if (!phis) {
if (entry_descriptor)
phis = computeRequiredPhis(entry_descriptor, source->liveness, source->getScopeInfo());
else
phis = computeRequiredPhis(f->param_names, source->cfg, source->liveness, source->getScopeInfo());
}
}
CompiledFunction* cf = 0; CompiledFunction* cf = 0;
...@@ -328,10 +316,13 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -328,10 +316,13 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
assert(cf->clfunc->versions.size()); 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); astInterpretFunction(cf, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
else } else {
STAT_TIMER(t1, "us_timer_jitted_module_toplevel");
((void (*)())cf->code)(); ((void (*)())cf->code)();
}
} }
Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) { Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) {
......
...@@ -42,6 +42,19 @@ extern "C" void dumpLLVM(llvm::Value* v) { ...@@ -42,6 +42,19 @@ extern "C" void dumpLLVM(llvm::Value* v) {
v->dump(); v->dump();
} }
IRGenState::IRGenState(CompiledFunction* cf, SourceInfo* source_info, std::unique_ptr<LivenessAnalysis> liveness,
std::unique_ptr<PhiAnalysis> phis, ParamNames* param_names, GCBuilder* gc,
llvm::MDNode* func_dbg_info)
: cf(cf), source_info(source_info), liveness(std::move(liveness)), phis(std::move(phis)), param_names(param_names),
gc(gc), func_dbg_info(func_dbg_info), scratch_space(NULL), frame_info(NULL), frame_info_arg(NULL),
scratch_size(0) {
assert(cf->func);
assert(!cf->clfunc); // in this case don't need to pass in sourceinfo
}
IRGenState::~IRGenState() {
}
llvm::Value* IRGenState::getScratchSpace(int min_bytes) { llvm::Value* IRGenState::getScratchSpace(int min_bytes) {
llvm::BasicBlock& entry_block = getLLVMFunction()->getEntryBlock(); llvm::BasicBlock& entry_block = getLLVMFunction()->getEntryBlock();
...@@ -944,7 +957,7 @@ private: ...@@ -944,7 +957,7 @@ private:
CompilerVariable* evalName(AST_Name* node, UnwindInfo unw_info) { CompilerVariable* evalName(AST_Name* node, UnwindInfo unw_info) {
auto scope_info = irstate->getScopeInfo(); auto scope_info = irstate->getScopeInfo();
bool is_kill = irstate->getSourceInfo()->liveness->isKill(node, myblock); bool is_kill = irstate->getLiveness()->isKill(node, myblock);
assert(!is_kill || node->id.str()[0] == '#'); assert(!is_kill || node->id.str()[0] == '#');
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(node->id); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(node->id);
...@@ -2271,7 +2284,7 @@ private: ...@@ -2271,7 +2284,7 @@ private:
// ASSERT(p.first[0] != '!' || isIsDefinedName(p.first), "left a fake variable in the real // ASSERT(p.first[0] != '!' || isIsDefinedName(p.first), "left a fake variable in the real
// symbol table? '%s'", p.first.c_str()); // symbol table? '%s'", p.first.c_str());
if (!source->liveness->isLiveAtEnd(p.first, myblock)) { if (!irstate->getLiveness()->isLiveAtEnd(p.first, myblock)) {
// printf("%s dead at end of %d; grabbed = %d, %d vrefs\n", p.first.c_str(), myblock->idx, // printf("%s dead at end of %d; grabbed = %d, %d vrefs\n", p.first.c_str(), myblock->idx,
// p.second->isGrabbed(), p.second->getVrefs()); // p.second->isGrabbed(), p.second->getVrefs());
......
...@@ -56,7 +56,8 @@ class IRGenState { ...@@ -56,7 +56,8 @@ class IRGenState {
private: private:
CompiledFunction* cf; CompiledFunction* cf;
SourceInfo* source_info; SourceInfo* source_info;
PhiAnalysis* phis; std::unique_ptr<LivenessAnalysis> liveness;
std::unique_ptr<PhiAnalysis> phis;
ParamNames* param_names; ParamNames* param_names;
GCBuilder* gc; GCBuilder* gc;
llvm::MDNode* func_dbg_info; llvm::MDNode* func_dbg_info;
...@@ -69,13 +70,9 @@ private: ...@@ -69,13 +70,9 @@ private:
public: public:
IRGenState(CompiledFunction* cf, SourceInfo* source_info, PhiAnalysis* phis, ParamNames* param_names, GCBuilder* gc, IRGenState(CompiledFunction* cf, SourceInfo* source_info, std::unique_ptr<LivenessAnalysis> liveness,
llvm::MDNode* func_dbg_info) std::unique_ptr<PhiAnalysis> phis, ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info);
: cf(cf), source_info(source_info), phis(phis), param_names(param_names), gc(gc), func_dbg_info(func_dbg_info), ~IRGenState();
scratch_space(NULL), frame_info(NULL), frame_info_arg(NULL), scratch_size(0) {
assert(cf->func);
assert(!cf->clfunc); // in this case don't need to pass in sourceinfo
}
CompiledFunction* getCurFunction() { return cf; } CompiledFunction* getCurFunction() { return cf; }
...@@ -93,7 +90,8 @@ public: ...@@ -93,7 +90,8 @@ public:
SourceInfo* getSourceInfo() { return source_info; } SourceInfo* getSourceInfo() { return source_info; }
PhiAnalysis* getPhis() { return phis; } LivenessAnalysis* getLiveness() { return liveness.get(); }
PhiAnalysis* getPhis() { return phis.get(); }
ScopeInfo* getScopeInfo(); ScopeInfo* getScopeInfo();
ScopeInfo* getScopeInfoForNode(AST* node); ScopeInfo* getScopeInfoForNode(AST* node);
......
...@@ -982,6 +982,7 @@ AST_Module* parse_string(const char* code) { ...@@ -982,6 +982,7 @@ AST_Module* parse_string(const char* code) {
} }
AST_Module* parse_file(const char* fn) { AST_Module* parse_file(const char* fn) {
STAT_TIMER(t0, "us_timer_cpyton_parsing");
Timer _t("parsing"); Timer _t("parsing");
if (ENABLE_PYPA_PARSER) { if (ENABLE_PYPA_PARSER) {
...@@ -1071,9 +1072,10 @@ static ParseResult _reparse(const char* fn, const std::string& cache_fn, AST_Mod ...@@ -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 // it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms). // on the startup time (40ms -> 10ms).
AST_Module* caching_parse_file(const char* fn) { AST_Module* caching_parse_file(const char* fn) {
STAT_TIMER(t0, "us_timer_caching_parse_file");
static StatCounter us_parsing("us_parsing"); static StatCounter us_parsing("us_parsing");
Timer _t("parsing"); Timer _t("parsing");
_t.setExitCallback([](long t) { us_parsing.log(t); }); _t.setExitCallback([](uint64_t t) { us_parsing.log(t); });
int code; int code;
std::string cache_fn = std::string(fn) + "c"; std::string cache_fn = std::string(fn) + "c";
......
...@@ -494,6 +494,7 @@ void unwindPythonStack(std::function<bool(std::unique_ptr<PythonFrameIteratorImp ...@@ -494,6 +494,7 @@ void unwindPythonStack(std::function<bool(std::unique_ptr<PythonFrameIteratorImp
} }
static std::unique_ptr<PythonFrameIteratorImpl> getTopPythonFrame() { static std::unique_ptr<PythonFrameIteratorImpl> getTopPythonFrame() {
STAT_TIMER(t0, "us_timer_getTopPythonFrame");
std::unique_ptr<PythonFrameIteratorImpl> rtn(nullptr); std::unique_ptr<PythonFrameIteratorImpl> rtn(nullptr);
unwindPythonStack([&](std::unique_ptr<PythonFrameIteratorImpl> iter) { unwindPythonStack([&](std::unique_ptr<PythonFrameIteratorImpl> iter) {
rtn = std::move(iter); rtn = std::move(iter);
...@@ -514,6 +515,7 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) { ...@@ -514,6 +515,7 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) {
static StatCounter us_gettraceback("us_gettraceback"); static StatCounter us_gettraceback("us_gettraceback");
BoxedTraceback* getTraceback() { BoxedTraceback* getTraceback() {
STAT_TIMER(t0, "us_timer_gettraceback");
if (!ENABLE_FRAME_INTROSPECTION) { if (!ENABLE_FRAME_INTROSPECTION) {
static bool printed_warning = false; static bool printed_warning = false;
if (!printed_warning) { if (!printed_warning) {
......
...@@ -17,13 +17,115 @@ ...@@ -17,13 +17,115 @@
#include <algorithm> #include <algorithm>
#include "core/thread_utils.h" #include "core/thread_utils.h"
#include "gc/heap.h"
namespace pyston { namespace pyston {
#if !DISABLE_STATS #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();
_duration = 0;
_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) {
_duration = 0;
_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);
auto cur_duration = _duration;
_duration = at_time - _start_time;
assert(_duration > cur_duration);
Stats::log(_statid, _duration);
_duration = 0;
_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; std::unordered_map<int, std::string>* Stats::names;
bool Stats::enabled; bool Stats::enabled;
timespec Stats::start_ts;
uint64_t Stats::start_tick;
StatCounter::StatCounter(const std::string& name) : id(Stats::getStatId(name)) { StatCounter::StatCounter(const std::string& name) : id(Stats::getStatId(name)) {
} }
...@@ -37,7 +139,7 @@ int Stats::getStatId(const std::string& name) { ...@@ -37,7 +139,7 @@ int Stats::getStatId(const std::string& name) {
// hacky but easy way of getting around static constructor ordering issues for now: // hacky but easy way of getting around static constructor ordering issues for now:
static std::unordered_map<int, std::string> names; static std::unordered_map<int, std::string> names;
Stats::names = &names; Stats::names = &names;
static std::vector<long> counts; static std::vector<uint64_t> counts;
Stats::counts = &counts; Stats::counts = &counts;
static std::unordered_map<std::string, int> made; static std::unordered_map<std::string, int> made;
...@@ -51,11 +153,40 @@ int Stats::getStatId(const std::string& name) { ...@@ -51,11 +153,40 @@ int Stats::getStatId(const std::string& name) {
return rtn; 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) { void Stats::dump(bool includeZeros) {
if (!Stats::enabled) if (!Stats::enabled)
return; return;
printf("Stats:\n"); double cycles_per_us = Stats::estimateCPUFreq();
fprintf(stderr, "Stats:\n");
fprintf(stderr, "estimated_cpu_mhz: %5.5f\n", cycles_per_us);
gc::dumpHeapStatistics(0);
fprintf(stderr, "Counters:\n");
std::vector<std::pair<std::string, int>> pairs; std::vector<std::pair<std::string, int>> pairs;
for (const auto& p : *names) { for (const auto& p : *names) {
...@@ -64,10 +195,42 @@ void Stats::dump(bool includeZeros) { ...@@ -64,10 +195,42 @@ void Stats::dump(bool includeZeros) {
std::sort(pairs.begin(), pairs.end()); 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++) { for (int i = 0; i < pairs.size(); i++) {
if (includeZeros || (*counts)[pairs[i].second] > 0) if (includeZeros || (*counts)[pairs[i].second] > 0) {
printf("%s: %ld\n", pairs[i].first.c_str(), (*counts)[pairs[i].second]); 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");
} }
void Stats::endOfInit() { void Stats::endOfInit() {
......
...@@ -22,23 +22,48 @@ ...@@ -22,23 +22,48 @@
#include <vector> #include <vector>
#include "core/options.h" #include "core/options.h"
#include "core/util.h"
namespace pyston { namespace pyston {
#define DISABLE_STATS 0 #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 #if !DISABLE_STATS
struct Stats { struct Stats {
private: private:
static std::vector<long>* counts; static std::vector<uint64_t>* counts;
static std::unordered_map<int, std::string>* names; static std::unordered_map<int, std::string>* names;
static bool enabled; static bool enabled;
static timespec start_ts;
static uint64_t start_tick;
public: public:
static void startEstimatingCPUFreq();
static double estimateCPUFreq();
static int getStatId(const std::string& name); static int getStatId(const std::string& name);
static std::string getStatName(int id);
static void setEnabled(bool enabled) { Stats::enabled = enabled; } 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 clear() { std::fill(counts->begin(), counts->end(), 0); }
static void dump(bool includeZeros = true); static void dump(bool includeZeros = true);
...@@ -52,7 +77,7 @@ private: ...@@ -52,7 +77,7 @@ private:
public: public:
StatCounter(const std::string& name); 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 { struct StatPerThreadCounter {
...@@ -62,24 +87,77 @@ private: ...@@ -62,24 +87,77 @@ private:
public: public:
StatPerThreadCounter(const std::string& name); 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 #else
struct Stats { struct Stats {
static void startEstimatingCPUFreq() {}
static double estimateCPUFreq() { return 0; }
static void setEnabled(bool enabled) {} 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 void log(int id, int count = 1) {}
static int getStatId(const std::string& name) { return 0; } static int getStatId(const std::string& name) { return 0; }
static void endOfInit() {} static void endOfInit() {}
}; };
struct StatCounter { struct StatCounter {
StatCounter(const char* name) {} StatCounter(const char* name) {}
void log(int count = 1){}; void log(uint64_t count = 1){};
}; };
struct StatPerThreadCounter { struct StatPerThreadCounter {
StatPerThreadCounter(const char* name) {} 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 accumulated active duration of this timer
uint64_t _duration;
// 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 #endif
} }
......
...@@ -243,8 +243,6 @@ public: ...@@ -243,8 +243,6 @@ public:
ScopingAnalysis* scoping; ScopingAnalysis* scoping;
AST* ast; AST* ast;
CFG* cfg; CFG* cfg;
LivenessAnalysis* liveness;
std::unordered_map<const OSREntryDescriptor*, PhiAnalysis*> phis;
bool is_generator; bool is_generator;
std::string fn; // equivalent of code.co_filename std::string fn; // equivalent of code.co_filename
...@@ -487,13 +485,26 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) ...@@ -487,13 +485,26 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
return Box::operator new(size, default_cls); \ 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 // The restrictions on when you can use the SIMPLE (ie fast) variant are encoded as
// asserts in the 1-arg operator new function: // asserts in the 1-arg operator new function:
#define DEFAULT_CLASS_SIMPLE(default_cls) \ #define DEFAULT_CLASS_SIMPLE(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \ void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
ALLOC_STATS(cls); \
return Box::operator new(size, cls); \ return Box::operator new(size, cls); \
} \ } \
void* operator new(size_t size) __attribute__((visibility("default"))) { \ 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: \ /* In the simple cases, we can inline the following methods and simplify things a lot: \
* - Box::operator new \ * - Box::operator new \
* - cls->tp_alloc \ * - cls->tp_alloc \
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
...@@ -26,6 +29,18 @@ ...@@ -26,6 +29,18 @@
namespace pyston { 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; int Timer::level = 0;
Timer::Timer(const char* desc, long min_usec) : min_usec(min_usec), ended(true) { Timer::Timer(const char* desc, long min_usec) : min_usec(min_usec), ended(true) {
...@@ -36,7 +51,7 @@ void Timer::restart(const char* newdesc) { ...@@ -36,7 +51,7 @@ void Timer::restart(const char* newdesc) {
assert(ended); assert(ended);
desc = newdesc; desc = newdesc;
gettimeofday(&start_time, NULL); start_time = getCPUTicks();
Timer::level++; Timer::level++;
ended = false; ended = false;
} }
...@@ -46,14 +61,14 @@ void Timer::restart(const char* newdesc, long new_min_usec) { ...@@ -46,14 +61,14 @@ void Timer::restart(const char* newdesc, long new_min_usec) {
restart(newdesc); restart(newdesc);
} }
long Timer::end() { uint64_t Timer::end(uint64_t* ended_at) {
if (!ended) { if (!ended) {
timeval end; uint64_t end = getCPUTicks();
gettimeofday(&end, NULL); uint64_t duration = end - start_time;
long us = 1000000L * (end.tv_sec - start_time.tv_sec) + (end.tv_usec - start_time.tv_usec);
Timer::level--; Timer::level--;
if (VERBOSITY("time") >= 2 && desc) { if (VERBOSITY("time") >= 2 && desc) {
uint64_t us = (uint64_t)(duration / Stats::estimateCPUFreq());
if (us > min_usec) { if (us > min_usec) {
for (int i = 0; i < Timer::level; i++) { for (int i = 0; i < Timer::level; i++) {
putchar(' '); putchar(' ');
...@@ -70,15 +85,17 @@ long Timer::end() { ...@@ -70,15 +85,17 @@ long Timer::end() {
fflush(stdout); fflush(stdout);
} }
} }
if (ended_at)
*ended_at = end;
ended = true; ended = true;
return us; return duration;
} }
return -1; return -1;
} }
Timer::~Timer() { Timer::~Timer() {
if (!ended) { if (!ended) {
long t = end(); uint64_t t = end();
if (exit_callback) if (exit_callback)
exit_callback(t); exit_callback(t);
} }
......
...@@ -24,30 +24,36 @@ ...@@ -24,30 +24,36 @@
namespace pyston { namespace pyston {
uint64_t getCPUTicks();
class Timer { class Timer {
private: private:
static int level; static int level;
timeval start_time; uint64_t start_time;
const char* desc; const char* desc;
long min_usec; long min_usec;
bool ended; bool ended;
std::function<void(long)> exit_callback; std::function<void(uint64_t)> exit_callback;
public: public:
Timer(const char* desc = NULL, long min_usec = -1); Timer(const char* desc = NULL, long min_usec = -1);
~Timer(); ~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, long new_min_usec);
void restart(const char* newdesc = NULL); void restart(const char* newdesc = NULL);
long end(); // returns the duration. if @ended_at is non-null, it's filled in
long split(const char* newdesc = NULL) { // with the tick the timer stopped at.
long rtn = end(); uint64_t end(uint64_t* ended_at = NULL);
uint64_t split(const char* newdesc = NULL) {
uint64_t rtn = end();
restart(newdesc); restart(newdesc);
return rtn; return rtn;
} }
uint64_t getStartTime() const { return start_time; }
}; };
bool startswith(const std::string& s, const std::string& pattern); bool startswith(const std::string& s, const std::string& pattern);
......
...@@ -339,6 +339,8 @@ void runCollection() { ...@@ -339,6 +339,8 @@ void runCollection() {
static StatCounter sc("gc_collections"); static StatCounter sc("gc_collections");
sc.log(); sc.log();
STAT_TIMER(t0, "us_timer_gc_collection");
ncollections++; ncollections++;
if (VERBOSITY("gc") >= 2) if (VERBOSITY("gc") >= 2)
......
...@@ -28,7 +28,9 @@ namespace pyston { ...@@ -28,7 +28,9 @@ namespace pyston {
namespace gc { namespace gc {
static StatCounter gc_alloc_bytes("zzz_gc_alloc_bytes");
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) { 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); size_t alloc_bytes = bytes + sizeof(GCAllocation);
#ifndef NVALGRIND #ifndef NVALGRIND
...@@ -89,8 +91,10 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) { ...@@ -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); // if (VERBOSITY()) printf("Allocated %ld bytes at [%p, %p)\n", bytes, r, (char*)r + bytes);
#endif #endif
// printf("Allocated %p\n", r);
#if STAT_ALLOCATIONS
gc_alloc_bytes.log(bytes);
#endif
return r; return r;
} }
...@@ -128,6 +132,10 @@ extern "C" inline void* gc_realloc(void* ptr, size_t bytes) { ...@@ -128,6 +132,10 @@ extern "C" inline void* gc_realloc(void* ptr, size_t bytes) {
alloc->kind_data = bytes; alloc->kind_data = bytes;
} }
#if STAT_ALLOCATIONS
gc_alloc_bytes.log(bytes);
#endif
return rtn; return rtn;
} }
......
...@@ -185,16 +185,32 @@ struct HeapStatistics { ...@@ -185,16 +185,32 @@ struct HeapStatistics {
void print(const char* name) const { void print(const char* name) const {
if (nbytes > (1 << 20)) if (nbytes > (1 << 20))
printf("%s: %ld allocations for %.1f MB\n", name, nallocs, nbytes * 1.0 / (1 << 20)); fprintf(stderr, "%s: %ld allocations for %.1f MB\n", name, nallocs, nbytes * 1.0 / (1 << 20));
else if (nbytes > (1 << 10)) else if (nbytes > (1 << 10))
printf("%s: %ld allocations for %.1f KB\n", name, nallocs, nbytes * 1.0 / (1 << 10)); fprintf(stderr, "%s: %ld allocations for %.1f KB\n", name, nallocs, nbytes * 1.0 / (1 << 10));
else else
printf("%s: %ld allocations for %ld bytes\n", name, nallocs, nbytes); fprintf(stderr, "%s: %ld allocations for %ld bytes\n", name, nallocs, nbytes);
} }
}; };
bool collect_cls_stats, collect_hcls_stats;
// For use if collect_cls_stats == true:
std::unordered_map<BoxedClass*, TypeStats> by_cls; std::unordered_map<BoxedClass*, TypeStats> by_cls;
TypeStats conservative, untracked, hcls;
// For use if collect_hcls_stats == true:
std::unordered_map<HiddenClass*, int> hcls_uses;
#define HCLS_ATTRS_STAT_MAX 20
int num_hcls_by_attrs[HCLS_ATTRS_STAT_MAX + 1];
int num_hcls_by_attrs_exceed;
TypeStats python, conservative, untracked, hcls, precise;
TypeStats total; TypeStats total;
HeapStatistics(bool collect_cls_stats, bool collect_hcls_stats)
: collect_cls_stats(collect_cls_stats), collect_hcls_stats(collect_hcls_stats) {
memset(num_hcls_by_attrs, 0, sizeof(num_hcls_by_attrs));
}
}; };
void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) { void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
...@@ -202,11 +218,24 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) { ...@@ -202,11 +218,24 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
stats->total.nbytes += nbytes; stats->total.nbytes += nbytes;
if (al->kind_id == GCKind::PYTHON) { if (al->kind_id == GCKind::PYTHON) {
Box* b = (Box*)al->user_data; stats->python.nallocs++;
auto& t = stats->by_cls[b->cls]; stats->python.nbytes += nbytes;
t.nallocs++; if (stats->collect_cls_stats) {
t.nbytes += nbytes; Box* b = (Box*)al->user_data;
auto& t = stats->by_cls[b->cls];
t.nallocs++;
t.nbytes += nbytes;
}
if (stats->collect_hcls_stats) {
Box* b = (Box*)al->user_data;
if (b->cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = b->getHCAttrsPtr();
stats->hcls_uses[attrs->hcls]++;
}
}
} else if (al->kind_id == GCKind::CONSERVATIVE) { } else if (al->kind_id == GCKind::CONSERVATIVE) {
stats->conservative.nallocs++; stats->conservative.nallocs++;
stats->conservative.nbytes += nbytes; stats->conservative.nbytes += nbytes;
...@@ -216,6 +245,18 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) { ...@@ -216,6 +245,18 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
} else if (al->kind_id == GCKind::HIDDEN_CLASS) { } else if (al->kind_id == GCKind::HIDDEN_CLASS) {
stats->hcls.nallocs++; stats->hcls.nallocs++;
stats->hcls.nbytes += nbytes; stats->hcls.nbytes += nbytes;
if (stats->collect_hcls_stats) {
HiddenClass* hcls = (HiddenClass*)al->user_data;
int numattrs = hcls->attributeArraySize();
if (numattrs <= HCLS_ATTRS_STAT_MAX)
stats->num_hcls_by_attrs[numattrs]++;
else
stats->num_hcls_by_attrs_exceed++;
}
} else if (al->kind_id == GCKind::PRECISE) {
stats->precise.nallocs++;
stats->precise.nbytes += nbytes;
} else { } else {
RELEASE_ASSERT(0, "%d", (int)al->kind_id); RELEASE_ASSERT(0, "%d", (int)al->kind_id);
} }
...@@ -223,27 +264,49 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) { ...@@ -223,27 +264,49 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
void Heap::dumpHeapStatistics() { void Heap::dumpHeapStatistics(int level) {
bool collect_cls_stats = (level >= 1);
bool collect_hcls_stats = (level >= 1);
threading::GLPromoteRegion _lock; threading::GLPromoteRegion _lock;
HeapStatistics stats; fprintf(stderr, "\nCollecting heap stats for pid %d...\n", getpid());
HeapStatistics stats(collect_cls_stats, collect_hcls_stats);
small_arena.getStatistics(&stats); small_arena.getStatistics(&stats);
large_arena.getStatistics(&stats); large_arena.getStatistics(&stats);
huge_arena.getStatistics(&stats); huge_arena.getStatistics(&stats);
stats.python.print("python");
stats.conservative.print("conservative"); stats.conservative.print("conservative");
stats.untracked.print("untracked"); stats.untracked.print("untracked");
stats.hcls.print("hcls"); stats.hcls.print("hcls");
for (const auto& p : stats.by_cls) { stats.precise.print("precise");
p.second.print(getFullNameOfClass(p.first).c_str());
if (collect_cls_stats) {
for (const auto& p : stats.by_cls) {
p.second.print(getFullNameOfClass(p.first).c_str());
}
} }
stats.total.print("Total"); stats.total.print("Total");
printf("\n");
if (collect_hcls_stats) {
fprintf(stderr, "%ld hidden classes currently alive\n", stats.hcls.nallocs);
fprintf(stderr, "%ld have at least one Box that uses them\n", stats.hcls_uses.size());
for (int i = 0; i <= HCLS_ATTRS_STAT_MAX; i++) {
fprintf(stderr, "With % 3d attributes: %d\n", i, stats.num_hcls_by_attrs[i]);
}
fprintf(stderr, "With >% 2d attributes: %d\n", HCLS_ATTRS_STAT_MAX, stats.num_hcls_by_attrs_exceed);
}
fprintf(stderr, "\n");
} }
void dumpHeapStatistics() { void dumpHeapStatistics(int level) {
global_heap.dumpHeapStatistics(); global_heap.dumpHeapStatistics(level);
} }
////// //////
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "core/common.h" #include "core/common.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h"
namespace pyston { namespace pyston {
...@@ -535,13 +536,13 @@ public: ...@@ -535,13 +536,13 @@ public:
huge_arena.freeUnmarked(weakly_referenced); huge_arena.freeUnmarked(weakly_referenced);
} }
void dumpHeapStatistics(); void dumpHeapStatistics(int level);
friend void markPhase(); friend void markPhase();
}; };
extern Heap global_heap; extern Heap global_heap;
void dumpHeapStatistics(); void dumpHeapStatistics(int level);
} // namespace gc } // namespace gc
} // namespace pyston } // namespace pyston
......
This diff is collapsed.
...@@ -304,6 +304,7 @@ extern "C" Box* ord(Box* obj) { ...@@ -304,6 +304,7 @@ extern "C" Box* ord(Box* obj) {
} }
Box* range(Box* start, Box* stop, Box* step) { Box* range(Box* start, Box* stop, Box* step) {
STAT_TIMER(t0, "us_timer_builtin_range");
i64 istart, istop, istep; i64 istart, istop, istep;
if (stop == NULL) { if (stop == NULL) {
istart = 0; istart = 0;
...@@ -347,6 +348,7 @@ Box* notimplementedRepr(Box* self) { ...@@ -347,6 +348,7 @@ Box* notimplementedRepr(Box* self) {
} }
Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) { Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) {
STAT_TIMER(t0, "us_timer_builtin_sorted");
Box* reverse = args[0]; Box* reverse = args[0];
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
...@@ -359,6 +361,7 @@ Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) { ...@@ -359,6 +361,7 @@ Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) {
} }
Box* isinstance_func(Box* obj, Box* cls) { Box* isinstance_func(Box* obj, Box* cls) {
STAT_TIMER(t0, "us_timer_builtin_isinstance");
int rtn = PyObject_IsInstance(obj, cls); int rtn = PyObject_IsInstance(obj, cls);
if (rtn < 0) if (rtn < 0)
checkAndThrowCAPIException(); checkAndThrowCAPIException();
...@@ -366,6 +369,7 @@ Box* isinstance_func(Box* obj, Box* cls) { ...@@ -366,6 +369,7 @@ Box* isinstance_func(Box* obj, Box* cls) {
} }
Box* issubclass_func(Box* child, Box* parent) { Box* issubclass_func(Box* child, Box* parent) {
STAT_TIMER(t0, "us_timer_builtin_issubclass");
int rtn = PyObject_IsSubclass(child, parent); int rtn = PyObject_IsSubclass(child, parent);
if (rtn < 0) if (rtn < 0)
checkAndThrowCAPIException(); checkAndThrowCAPIException();
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace pyston { namespace pyston {
static Box* memberGet(BoxedMemberDescriptor* self, Box* inst, Box* owner) { static Box* memberGet(BoxedMemberDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == member_cls, ""); RELEASE_ASSERT(self->cls == member_descriptor_cls, "");
if (inst == None) if (inst == None)
return self; return self;
...@@ -169,8 +169,8 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) { ...@@ -169,8 +169,8 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
} }
void setupDescr() { void setupDescr() {
member_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)memberGet, UNKNOWN, 3))); member_descriptor_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)memberGet, UNKNOWN, 3)));
member_cls->freeze(); member_descriptor_cls->freeze();
property_cls->giveAttr("__init__", property_cls->giveAttr("__init__",
new BoxedFunction(boxRTFunction((void*)propertyInit, UNKNOWN, 5, 4, false, false, new BoxedFunction(boxRTFunction((void*)propertyInit, UNKNOWN, 5, 4, false, false,
......
...@@ -48,6 +48,7 @@ Box* dictRepr(BoxedDict* self) { ...@@ -48,6 +48,7 @@ Box* dictRepr(BoxedDict* self) {
} }
Box* dictClear(BoxedDict* self) { Box* dictClear(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictClear");
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'clear' requires a 'dict' object but received a '%s'", getTypeName(self)); raiseExcHelper(TypeError, "descriptor 'clear' requires a 'dict' object but received a '%s'", getTypeName(self));
...@@ -56,6 +57,7 @@ Box* dictClear(BoxedDict* self) { ...@@ -56,6 +57,7 @@ Box* dictClear(BoxedDict* self) {
} }
Box* dictCopy(BoxedDict* self) { Box* dictCopy(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictCopy");
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'copy' requires a 'dict' object but received a '%s'", getTypeName(self)); raiseExcHelper(TypeError, "descriptor 'copy' requires a 'dict' object but received a '%s'", getTypeName(self));
...@@ -65,6 +67,7 @@ Box* dictCopy(BoxedDict* self) { ...@@ -65,6 +67,7 @@ Box* dictCopy(BoxedDict* self) {
} }
Box* dictItems(BoxedDict* self) { Box* dictItems(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictItems");
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
rtn->ensure(self->d.size()); rtn->ensure(self->d.size());
...@@ -77,6 +80,7 @@ Box* dictItems(BoxedDict* self) { ...@@ -77,6 +80,7 @@ Box* dictItems(BoxedDict* self) {
} }
Box* dictValues(BoxedDict* self) { Box* dictValues(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictValues");
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
rtn->ensure(self->d.size()); rtn->ensure(self->d.size());
for (const auto& p : self->d) { for (const auto& p : self->d) {
...@@ -86,6 +90,7 @@ Box* dictValues(BoxedDict* self) { ...@@ -86,6 +90,7 @@ Box* dictValues(BoxedDict* self) {
} }
Box* dictKeys(BoxedDict* self) { Box* dictKeys(BoxedDict* self) {
STAT_TIMER(t0, "us_timer_dictKeys");
RELEASE_ASSERT(isSubclass(self->cls, dict_cls), ""); RELEASE_ASSERT(isSubclass(self->cls, dict_cls), "");
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
...@@ -182,6 +187,7 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept { ...@@ -182,6 +187,7 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept {
} }
Box* dictGetitem(BoxedDict* self, Box* k) { Box* dictGetitem(BoxedDict* self, Box* k) {
STAT_TIMER(t0, "us_timer_dictGetitem");
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'",
getTypeName(self)); getTypeName(self));
...@@ -306,6 +312,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc ...@@ -306,6 +312,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
} }
Box* dictSetitem(BoxedDict* self, Box* k, Box* v) { Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
STAT_TIMER(t0, "us_timer_dictSetitem");
// printf("Starting setitem\n"); // printf("Starting setitem\n");
Box*& pos = self->d[k]; Box*& pos = self->d[k];
// printf("Got the pos\n"); // printf("Got the pos\n");
...@@ -320,6 +327,7 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) { ...@@ -320,6 +327,7 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
} }
Box* dictDelitem(BoxedDict* self, Box* k) { Box* dictDelitem(BoxedDict* self, Box* k) {
STAT_TIMER(t0, "us_timer_dictDelitem");
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__delitem__' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__delitem__' requires a 'dict' object but received a '%s'",
getTypeName(self)); getTypeName(self));
......
...@@ -741,6 +741,98 @@ static Box* float0(Box*, void*) { ...@@ -741,6 +741,98 @@ static Box* float0(Box*, void*) {
return boxFloat(0.0); return boxFloat(0.0);
} }
// __getformat__
// ported pretty directly from cpython Objects/floatobject.c
typedef enum { unknown_format, ieee_big_endian_format, ieee_little_endian_format } float_format_type;
static float_format_type double_format, float_format;
static float_format_type detected_double_format, detected_float_format;
static void floatFormatInit() {
/* We attempt to determine if this machine is using IEEE
floating point formats by peering at the bits of some
carefully chosen values. If it looks like we are on an
IEEE platform, the float packing/unpacking routines can
just copy bits, if not they resort to arithmetic & shifts
and masks. The shifts & masks approach works on all finite
values, but what happens to infinities, NaNs and signed
zeroes on packing is an accident, and attempting to unpack
a NaN or an infinity will raise an exception.
Note that if we're on some whacked-out platform which uses
IEEE formats but isn't strictly little-endian or big-
endian, we will fall back to the portable shifts & masks
method. */
if (sizeof(double) == 8) {
double x = 9006104071832581.0;
if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
detected_double_format = ieee_big_endian_format;
else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
detected_double_format = ieee_little_endian_format;
else
detected_double_format = unknown_format;
} else {
detected_double_format = unknown_format;
}
if (sizeof(float) == 4) {
float y = 16711938.0;
if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
detected_float_format = ieee_big_endian_format;
else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
detected_float_format = ieee_little_endian_format;
else
detected_float_format = unknown_format;
} else {
detected_float_format = unknown_format;
}
double_format = detected_double_format;
float_format = detected_float_format;
}
// ported pretty directly from cpython
Box* floatGetFormat(BoxedClass* v, Box* arg) {
char* s;
float_format_type r;
if (!PyString_Check(arg)) {
raiseExcHelper(TypeError, "__getformat__() argument must be string, not %s", arg->cls->tp_name);
}
s = PyString_AS_STRING(arg);
if (strcmp(s, "double") == 0) {
r = double_format;
} else if (strcmp(s, "float") == 0) {
r = float_format;
} else {
raiseExcHelper(ValueError, "__getformat__() argument 1 must be "
"'double' or 'float'");
}
switch (r) {
case unknown_format:
return boxString("unknown");
case ieee_little_endian_format:
return boxString("IEEE, little-endian");
case ieee_big_endian_format:
return boxString("IEEE, big-endian");
default:
RELEASE_ASSERT(false, "insane float_format or double_format");
return NULL;
}
}
const char* floatGetFormatDoc = "float.__getformat__(typestr) -> string\n"
"\n"
"You probably don't want to use this function. It exists mainly to be\n"
"used in Python's test suite.\n"
"\n"
"typestr must be 'double' or 'float'. This function returns whichever of\n"
"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n"
"format of floating point numbers used by the C type named by typestr.";
void setupFloat() { void setupFloat() {
_addFunc("__add__", BOXED_FLOAT, (void*)floatAddFloat, (void*)floatAddInt, (void*)floatAdd); _addFunc("__add__", BOXED_FLOAT, (void*)floatAddFloat, (void*)floatAddInt, (void*)floatAdd);
float_cls->giveAttr("__radd__", float_cls->getattr("__add__")); float_cls->giveAttr("__radd__", float_cls->getattr("__add__"));
...@@ -785,7 +877,13 @@ void setupFloat() { ...@@ -785,7 +877,13 @@ void setupFloat() {
float_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(float0, NULL, NULL)); float_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(float0, NULL, NULL));
float_cls->giveAttr("conjugate", new BoxedFunction(boxRTFunction((void*)floatFloat, BOXED_FLOAT, 1))); float_cls->giveAttr("conjugate", new BoxedFunction(boxRTFunction((void*)floatFloat, BOXED_FLOAT, 1)));
float_cls->giveAttr("__getformat__",
new BoxedClassmethod(new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)floatGetFormat, STR, 2), "__getformat__", floatGetFormatDoc)));
float_cls->freeze(); float_cls->freeze();
floatFormatInit();
} }
void teardownFloat() { void teardownFloat() {
......
...@@ -86,28 +86,36 @@ Context* getReturnContextForGeneratorFrame(void* frame_addr) { ...@@ -86,28 +86,36 @@ Context* getReturnContextForGeneratorFrame(void* frame_addr) {
} }
void generatorEntry(BoxedGenerator* g) { 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 { threading::pushGenerator(g, g->stack_begin, g->returnContext);
RegisterHelper context_registerer(g, __builtin_frame_address(0)); try {
RegisterHelper context_registerer(g, __builtin_frame_address(0));
// call body of the generator // call body of the generator
BoxedFunctionBase* func = g->function; BoxedFunctionBase* func = g->function;
Box** args = g->args ? &g->args->elts[0] : nullptr; 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, callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2,
g->arg3, args); g->arg3, args);
} catch (ExcInfo e) { } catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller // unhandled exception: propagate the exception to the caller
g->exception = e; g->exception = e;
} }
// we returned from the body of the generator. next/send/throw will notify the caller // we returned from the body of the generator. next/send/throw will notify the caller
g->entryExited = true; g->entryExited = true;
threading::popGenerator(); 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); swapContext(&g->context, g->returnContext, 0);
} }
...@@ -130,7 +138,21 @@ Box* generatorSend(Box* s, Box* v) { ...@@ -130,7 +138,21 @@ Box* generatorSend(Box* s, Box* v) {
self->returnValue = v; self->returnValue = v;
self->running = true; 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); 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; self->running = false;
// propagate exception to the caller // propagate exception to the caller
......
...@@ -541,6 +541,8 @@ extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) { ...@@ -541,6 +541,8 @@ extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) {
} }
Box* listMul(BoxedList* self, Box* rhs) { Box* listMul(BoxedList* self, Box* rhs) {
STAT_TIMER(t0, "us_timer_listMul");
if (rhs->cls != int_cls) { if (rhs->cls != int_cls) {
raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs)); raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs));
} }
...@@ -940,7 +942,7 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) { ...@@ -940,7 +942,7 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
} }
Box* listEq(BoxedList* self, Box* rhs) { Box* listEq(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
...@@ -950,7 +952,7 @@ Box* listEq(BoxedList* self, Box* rhs) { ...@@ -950,7 +952,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
} }
Box* listNe(BoxedList* self, Box* rhs) { Box* listNe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
...@@ -960,7 +962,7 @@ Box* listNe(BoxedList* self, Box* rhs) { ...@@ -960,7 +962,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
} }
Box* listLt(BoxedList* self, Box* rhs) { Box* listLt(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
...@@ -970,7 +972,7 @@ Box* listLt(BoxedList* self, Box* rhs) { ...@@ -970,7 +972,7 @@ Box* listLt(BoxedList* self, Box* rhs) {
} }
Box* listLe(BoxedList* self, Box* rhs) { Box* listLe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
...@@ -980,7 +982,7 @@ Box* listLe(BoxedList* self, Box* rhs) { ...@@ -980,7 +982,7 @@ Box* listLe(BoxedList* self, Box* rhs) {
} }
Box* listGt(BoxedList* self, Box* rhs) { Box* listGt(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
...@@ -990,7 +992,7 @@ Box* listGt(BoxedList* self, Box* rhs) { ...@@ -990,7 +992,7 @@ Box* listGt(BoxedList* self, Box* rhs) {
} }
Box* listGe(BoxedList* self, Box* rhs) { Box* listGe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) { if (!isSubclass(rhs->cls, list_cls)) {
return NotImplemented; return NotImplemented;
} }
......
This diff is collapsed.
...@@ -96,6 +96,7 @@ void unwindExc(Box* exc_obj) { ...@@ -96,6 +96,7 @@ void unwindExc(Box* exc_obj) {
void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__)); void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__));
void raiseRaw(const ExcInfo& e) { void raiseRaw(const ExcInfo& e) {
STAT_TIMER(t0, "us_timer_raiseraw");
// Should set these to None before getting here: // Should set these to None before getting here:
assert(e.type); assert(e.type);
assert(e.value); assert(e.value);
...@@ -160,28 +161,31 @@ extern "C" void abort() { ...@@ -160,28 +161,31 @@ extern "C" void abort() {
// In case displaying the traceback recursively calls abort: // In case displaying the traceback recursively calls abort:
static bool recursive = false; static bool recursive = false;
// If traceback_cls is NULL, then we somehow died early on, and won't be able to display a traceback. if (!recursive) {
if (!recursive && traceback_cls) {
recursive = true; recursive = true;
Stats::dump();
fprintf(stderr, "Someone called abort!\n"); fprintf(stderr, "Someone called abort!\n");
// If we call abort(), things may be seriously wrong. Set an alarm() to // If traceback_cls is NULL, then we somehow died early on, and won't be able to display a traceback.
// try to handle cases that we would just hang. if (traceback_cls) {
// (Ex if we abort() from a static constructor, and _printStackTrace uses
// that object, _printStackTrace will hang waiting for the first construction // If we call abort(), things may be seriously wrong. Set an alarm() to
// to finish.) // try to handle cases that we would just hang.
alarm(1); // (Ex if we abort() from a static constructor, and _printStackTrace uses
try { // that object, _printStackTrace will hang waiting for the first construction
_printStacktrace(); // to finish.)
} catch (ExcInfo) { alarm(1);
fprintf(stderr, "error printing stack trace during abort()"); try {
} _printStacktrace();
} catch (ExcInfo) {
fprintf(stderr, "error printing stack trace during abort()");
}
// Cancel the alarm. // Cancel the alarm.
// This is helpful for when running in a debugger, since otherwise the debugger will catch the // This is helpful for when running in a debugger, since otherwise the debugger will catch the
// abort and let you investigate, but the alarm will still come back to kill the program. // abort and let you investigate, but the alarm will still come back to kill the program.
alarm(0); alarm(0);
}
} }
if (PAUSE_AT_ABORT) { if (PAUSE_AT_ABORT) {
......
...@@ -1112,6 +1112,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) { ...@@ -1112,6 +1112,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
} }
extern "C" Box* strMul(BoxedString* lhs, Box* rhs) { extern "C" Box* strMul(BoxedString* lhs, Box* rhs) {
STAT_TIMER(t0, "us_timer_strMul");
assert(isSubclass(lhs->cls, str_cls)); assert(isSubclass(lhs->cls, str_cls));
int n; int n;
...@@ -1514,6 +1515,7 @@ failed: ...@@ -1514,6 +1515,7 @@ failed:
} }
extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) { extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
STAT_TIMER(t0, "us_timer_unicodeHashUnboxed");
if (self->hash != -1) if (self->hash != -1)
return self->hash; return self->hash;
...@@ -1524,6 +1526,7 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) { ...@@ -1524,6 +1526,7 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
} }
extern "C" Box* strHash(BoxedString* self) { extern "C" Box* strHash(BoxedString* self) {
STAT_TIMER(t0, "us_timer_strHash");
assert(isSubclass(self->cls, str_cls)); assert(isSubclass(self->cls, str_cls));
StringHash<char> H; StringHash<char> H;
......
...@@ -168,6 +168,7 @@ Box* tupleAdd(BoxedTuple* self, Box* rhs) { ...@@ -168,6 +168,7 @@ Box* tupleAdd(BoxedTuple* self, Box* rhs) {
} }
Box* tupleMul(BoxedTuple* self, Box* rhs) { Box* tupleMul(BoxedTuple* self, Box* rhs) {
STAT_TIMER(t0, "us_timer_tupleMul");
if (rhs->cls != int_cls) { if (rhs->cls != int_cls) {
raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs)); raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs));
} }
...@@ -337,6 +338,7 @@ Box* tupleIndex(BoxedTuple* self, Box* elt) { ...@@ -337,6 +338,7 @@ Box* tupleIndex(BoxedTuple* self, Box* elt) {
} }
Box* tupleHash(BoxedTuple* self) { Box* tupleHash(BoxedTuple* self) {
STAT_TIMER(t0, "us_timer_tupleHash");
assert(isSubclass(self->cls, tuple_cls)); assert(isSubclass(self->cls, tuple_cls));
int64_t rtn = 3527539; int64_t rtn = 3527539;
......
...@@ -655,7 +655,7 @@ extern "C" void closureGCHandler(GCVisitor* v, Box* b) { ...@@ -655,7 +655,7 @@ extern "C" void closureGCHandler(GCVisitor* v, Box* b) {
extern "C" { extern "C" {
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
* str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, * str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls,
*file_cls, *member_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *property_cls, *file_cls, *member_descriptor_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *property_cls,
*staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls,
*builtin_function_or_method_cls, *attrwrapperiter_cls, *set_cls, *frozenset_cls; *builtin_function_or_method_cls, *attrwrapperiter_cls, *set_cls, *frozenset_cls;
...@@ -1270,6 +1270,8 @@ public: ...@@ -1270,6 +1270,8 @@ public:
} }
static Box* setitem(Box* _self, Box* _key, Box* value) { static Box* setitem(Box* _self, Box* _key, Box* value) {
STAT_TIMER(t0, "us_timer_AttrWrapper_setitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1282,6 +1284,7 @@ public: ...@@ -1282,6 +1284,7 @@ public:
} }
static Box* setdefault(Box* _self, Box* _key, Box* value) { static Box* setdefault(Box* _self, Box* _key, Box* value) {
STAT_TIMER(t0, "us_timer_AttrWrapper_setdefault");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1297,6 +1300,7 @@ public: ...@@ -1297,6 +1300,7 @@ public:
} }
static Box* get(Box* _self, Box* _key, Box* def) { static Box* get(Box* _self, Box* _key, Box* def) {
STAT_TIMER(t0, "us_timer_AttrWrapper_get");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1311,6 +1315,7 @@ public: ...@@ -1311,6 +1315,7 @@ public:
} }
static Box* getitem(Box* _self, Box* _key) { static Box* getitem(Box* _self, Box* _key) {
STAT_TIMER(t0, "us_timer_AttrWrapper_getitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1344,6 +1349,7 @@ public: ...@@ -1344,6 +1349,7 @@ public:
} }
static Box* delitem(Box* _self, Box* _key) { static Box* delitem(Box* _self, Box* _key) {
STAT_TIMER(t0, "us_timer_AttrWrapper_delitem");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1409,6 +1415,7 @@ public: ...@@ -1409,6 +1415,7 @@ public:
} }
static Box* values(Box* _self) { static Box* values(Box* _self) {
STAT_TIMER(t0, "us_timer_AttrWrapper_values");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1423,6 +1430,7 @@ public: ...@@ -1423,6 +1430,7 @@ public:
} }
static Box* items(Box* _self) { static Box* items(Box* _self) {
STAT_TIMER(t0, "us_timer_AttrWrapper_items");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1461,6 +1469,7 @@ public: ...@@ -1461,6 +1469,7 @@ public:
} }
static Box* update(Box* _self, Box* _container) { static Box* update(Box* _self, Box* _container) {
STAT_TIMER(t0, "us_timer_AttrWrapper_update");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -2101,8 +2110,8 @@ void setupRuntime() { ...@@ -2101,8 +2110,8 @@ void setupRuntime() {
module_cls = new BoxedHeapClass(object_cls, &moduleGCHandler, offsetof(BoxedModule, attrs), 0, sizeof(BoxedModule), module_cls = new BoxedHeapClass(object_cls, &moduleGCHandler, offsetof(BoxedModule, attrs), 0, sizeof(BoxedModule),
false, static_cast<BoxedString*>(boxStrConstant("module"))); false, static_cast<BoxedString*>(boxStrConstant("module")));
member_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false, member_descriptor_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("member"))); static_cast<BoxedString*>(boxStrConstant("member_descriptor")));
capifunc_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false, capifunc_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false,
static_cast<BoxedString*>(boxStrConstant("capifunc"))); static_cast<BoxedString*>(boxStrConstant("capifunc")));
method_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false, method_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false,
...@@ -2132,7 +2141,7 @@ void setupRuntime() { ...@@ -2132,7 +2141,7 @@ void setupRuntime() {
float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls }); float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls });
function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls }); function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls });
builtin_function_or_method_cls->tp_mro = BoxedTuple::create({ builtin_function_or_method_cls, object_cls }); builtin_function_or_method_cls->tp_mro = BoxedTuple::create({ builtin_function_or_method_cls, object_cls });
member_cls->tp_mro = BoxedTuple::create({ member_cls, object_cls }); member_descriptor_cls->tp_mro = BoxedTuple::create({ member_descriptor_cls, object_cls });
capifunc_cls->tp_mro = BoxedTuple::create({ capifunc_cls, object_cls }); capifunc_cls->tp_mro = BoxedTuple::create({ capifunc_cls, object_cls });
module_cls->tp_mro = BoxedTuple::create({ module_cls, object_cls }); module_cls->tp_mro = BoxedTuple::create({ module_cls, object_cls });
method_cls->tp_mro = BoxedTuple::create({ method_cls, object_cls }); method_cls->tp_mro = BoxedTuple::create({ method_cls, object_cls });
...@@ -2187,7 +2196,7 @@ void setupRuntime() { ...@@ -2187,7 +2196,7 @@ void setupRuntime() {
float_cls->finishInitialization(); float_cls->finishInitialization();
function_cls->finishInitialization(); function_cls->finishInitialization();
builtin_function_or_method_cls->finishInitialization(); builtin_function_or_method_cls->finishInitialization();
member_cls->finishInitialization(); member_descriptor_cls->finishInitialization();
module_cls->finishInitialization(); module_cls->finishInitialization();
capifunc_cls->finishInitialization(); capifunc_cls->finishInitialization();
method_cls->finishInitialization(); method_cls->finishInitialization();
......
...@@ -85,9 +85,9 @@ extern "C" Box* getSysStdout(); ...@@ -85,9 +85,9 @@ extern "C" Box* getSysStdout();
extern "C" { extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls, extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls,
*enumerate_cls, *xrange_cls, *member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *enumerate_cls, *xrange_cls, *member_descriptor_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls,
*property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls, *basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls,
*builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls; *capi_getset_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls;
} }
#define unicode_cls (&PyUnicode_Type) #define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type) #define memoryview_cls (&PyMemoryView_Type)
...@@ -410,12 +410,37 @@ public: ...@@ -410,12 +410,37 @@ public:
size_t size() { return s.size(); } size_t size() { return s.size(); }
void* operator new(size_t size, size_t ssize) __attribute__((visibility("default"))) { 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)); Box* rtn = static_cast<Box*>(gc_alloc(str_cls->tp_basicsize + ssize + 1, gc::GCKind::PYTHON));
rtn->cls = str_cls; rtn->cls = str_cls;
return rtn; return rtn;
} }
void* operator new(size_t size, BoxedClass* cls, size_t ssize) __attribute__((visibility("default"))) { 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)); Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, ssize + 1));
rtn->cls = cls; rtn->cls = cls;
return rtn; return rtn;
...@@ -517,12 +542,43 @@ public: ...@@ -517,12 +542,43 @@ public:
Box** elts; Box** elts;
void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) { 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)); Box* rtn = static_cast<Box*>(gc_alloc(_PyObject_VAR_SIZE(tuple_cls, nelts + 1), gc::GCKind::PYTHON));
rtn->cls = tuple_cls; rtn->cls = tuple_cls;
return rtn; return rtn;
} }
void* operator new(size_t size, BoxedClass* cls, size_t nelts) __attribute__((visibility("default"))) { 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)); Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, nelts));
rtn->cls = cls; rtn->cls = cls;
return rtn; return rtn;
...@@ -732,7 +788,7 @@ public: ...@@ -732,7 +788,7 @@ public:
BoxedMemberDescriptor(PyMemberDef* member) BoxedMemberDescriptor(PyMemberDef* member)
: type((MemberType)member->type), offset(member->offset), readonly(member->flags & READONLY) {} : type((MemberType)member->type), offset(member->offset), readonly(member->flags & READONLY) {}
DEFAULT_CLASS_SIMPLE(member_cls); DEFAULT_CLASS_SIMPLE(member_descriptor_cls);
}; };
class BoxedGetsetDescriptor : public Box { class BoxedGetsetDescriptor : public Box {
...@@ -817,6 +873,11 @@ public: ...@@ -817,6 +873,11 @@ public:
struct Context* context, *returnContext; struct Context* context, *returnContext;
void* stack_begin; void* stack_begin;
#if STAT_TIMERS
StatTimer* statTimers;
uint64_t timer_time;
#endif
BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args); BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
DEFAULT_CLASS(generator_cls); DEFAULT_CLASS(generator_cls);
......
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
s = """ s = """
def f(): def f():
a = 1 a = 1
...@@ -11,7 +10,8 @@ f() ...@@ -11,7 +10,8 @@ f()
try: try:
exec s exec s
except Exception as e: except Exception as e:
print repr(e) # avoid microrevision changes to Python error messages
print repr(e).replace("because ", "")
s = """ s = """
def f(): def f():
...@@ -27,4 +27,5 @@ f() ...@@ -27,4 +27,5 @@ f()
try: try:
exec s exec s
except Exception as e: except Exception as e:
print repr(e) # avoid microrevision changes to Python error messages
print repr(e).replace("because ", "")
...@@ -50,3 +50,11 @@ except ValueError as e: ...@@ -50,3 +50,11 @@ except ValueError as e:
pass pass
# We don't print the right thing yet: # We don't print the right thing yet:
# print e # print e
print '__getformat__ test'
print float.__getformat__('double')
print float.__getformat__('float')
try:
float.__getformat__('oooga booga boooga')
except Exception as e:
print e.message
...@@ -12,3 +12,27 @@ print l ...@@ -12,3 +12,27 @@ print l
print len(MyList.__new__(MyList)) print len(MyList.__new__(MyList))
l[:] = l[:] l[:] = l[:]
print l print l
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))
...@@ -208,6 +208,6 @@ for case in cases: ...@@ -208,6 +208,6 @@ for case in cases:
try: try:
exec case exec case
except SyntaxError as se: except SyntaxError as se:
print se.message print se.message.replace("because ", "")
# TODO uncomment this # TODO uncomment this
# traceback.print_exc() # traceback.print_exc()
import os import os
import test_package import test_package
print 1, test_package.__name__, os.path.normpath(test_package.__file__) print 1, test_package.__name__, os.path.normpath(test_package.__file__).replace(".pyc", ".py")
import test_package.intrapackage_import import test_package.intrapackage_import
import test_package.absolute_import import test_package.absolute_import
......
import os import os
import import_target import import_target
print 3, import_target.__name__, os.path.normpath(import_target.__file__) print 3, import_target.__name__, os.path.normpath(import_target.__file__).replace(".pyc", ".py")
...@@ -2,4 +2,4 @@ from __future__ import absolute_import ...@@ -2,4 +2,4 @@ from __future__ import absolute_import
import os import os
import import_target import import_target
print 4, import_target.__name__, os.path.normpath(import_target.__file__) print 4, import_target.__name__, os.path.normpath(import_target.__file__).replace(".pyc", ".py")
import os import os
from . import import_target from . import import_target
print 2, import_target.__name__, os.path.normpath(import_target.__file__) print 2, import_target.__name__, os.path.normpath(import_target.__file__).replace(".pyc", ".py")
...@@ -39,7 +39,7 @@ TEST_F(AnalysisTest, augassign) { ...@@ -39,7 +39,7 @@ TEST_F(AnalysisTest, augassign) {
SourceInfo* si = new SourceInfo(createModule("augassign", fn), scoping, func, func->body, fn); SourceInfo* si = new SourceInfo(createModule("augassign", fn), scoping, func, func->body, fn);
CFG* cfg = computeCFG(si, func->body); CFG* cfg = computeCFG(si, func->body);
LivenessAnalysis* liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
//cfg->print(); //cfg->print();
...@@ -49,7 +49,7 @@ TEST_F(AnalysisTest, augassign) { ...@@ -49,7 +49,7 @@ TEST_F(AnalysisTest, augassign) {
ASSERT_TRUE(liveness->isLiveAtEnd(module->interned_strings->get("a"), block)); ASSERT_TRUE(liveness->isLiveAtEnd(module->interned_strings->get("a"), block));
} }
PhiAnalysis* phis = computeRequiredPhis(ParamNames(func), cfg, liveness, scope_info); std::unique_ptr<PhiAnalysis> phis = computeRequiredPhis(ParamNames(func), cfg, liveness.get(), scope_info);
} }
void doOsrTest(bool is_osr, bool i_maybe_undefined) { void doOsrTest(bool is_osr, bool i_maybe_undefined) {
...@@ -67,7 +67,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -67,7 +67,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
scoping, func, func->body, fn); scoping, func, func->body, fn);
CFG* cfg = computeCFG(si, func->body); CFG* cfg = computeCFG(si, func->body);
LivenessAnalysis* liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
// cfg->print(); // cfg->print();
...@@ -83,7 +83,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -83,7 +83,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
AST_Jump* backedge = ast_cast<AST_Jump>(loop_backedge->body[0]); AST_Jump* backedge = ast_cast<AST_Jump>(loop_backedge->body[0]);
ASSERT_LE(backedge->target->idx, loop_backedge->idx); ASSERT_LE(backedge->target->idx, loop_backedge->idx);
PhiAnalysis* phis; std::unique_ptr<PhiAnalysis> phis;
if (is_osr) { if (is_osr) {
OSREntryDescriptor* entry_descriptor = OSREntryDescriptor::create(NULL, backedge); OSREntryDescriptor* entry_descriptor = OSREntryDescriptor::create(NULL, backedge);
...@@ -91,9 +91,9 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -91,9 +91,9 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
if (i_maybe_undefined) if (i_maybe_undefined)
entry_descriptor->args[idi_str] = NULL; entry_descriptor->args[idi_str] = NULL;
entry_descriptor->args[iter_str] = NULL; entry_descriptor->args[iter_str] = NULL;
phis = computeRequiredPhis(entry_descriptor, liveness, scope_info); phis = computeRequiredPhis(entry_descriptor, liveness.get(), scope_info);
} else { } else {
phis = computeRequiredPhis(ParamNames(func), cfg, liveness, scope_info); phis = computeRequiredPhis(ParamNames(func), cfg, liveness.get(), scope_info);
} }
// First, verify that we require phi nodes for the block we enter into. // First, verify that we require phi nodes for the block we enter into.
......
...@@ -125,6 +125,8 @@ def canonicalize_stderr(stderr): ...@@ -125,6 +125,8 @@ def canonicalize_stderr(stderr):
("AttributeError: '(\w+)' object attribute '(\w+)' is read-only", "AttributeError: \\2"), ("AttributeError: '(\w+)' object attribute '(\w+)' is read-only", "AttributeError: \\2"),
(r"TypeError: object.__new__\(\) takes no parameters", "TypeError: object() takes no parameters"), (r"TypeError: object.__new__\(\) takes no parameters", "TypeError: object() takes no parameters"),
("IndexError: list assignment index out of range", "IndexError: list index out of range"), ("IndexError: list assignment index out of range", "IndexError: list index out of range"),
(r"unqualified exec is not allowed in function '(\w+)' it (.*)",
r"unqualified exec is not allowed in function '\1' because it \2"),
] ]
for pattern, subst_with in substitutions: for pattern, subst_with in substitutions:
...@@ -206,9 +208,6 @@ def get_test_options(fn, check_stats, run_memcheck): ...@@ -206,9 +208,6 @@ def get_test_options(fn, check_stats, run_memcheck):
elif os.path.basename(fn).split('.')[0] in TESTS_TO_SKIP: elif os.path.basename(fn).split('.')[0] in TESTS_TO_SKIP:
opts.skip = 'command line option' opts.skip = 'command line option'
if opts.collect_stats:
opts.jit_args = ['-s'] + opts.jit_args
assert opts.expected in ("success", "fail", "statfail"), opts.expected assert opts.expected in ("success", "fail", "statfail"), opts.expected
if TEST_PYPY: if TEST_PYPY:
...@@ -217,11 +216,12 @@ def get_test_options(fn, check_stats, run_memcheck): ...@@ -217,11 +216,12 @@ def get_test_options(fn, check_stats, run_memcheck):
opts.check_stats = False opts.check_stats = False
opts.expected = "success" opts.expected = "success"
if opts.collect_stats:
opts.jit_args = ['-s'] + opts.jit_args
return opts return opts
def determine_test_result(fn, opts, code, out, stderr, elapsed): def determine_test_result(fn, opts, code, out, stderr, elapsed):
last_stderr_line = stderr.strip().split('\n')[-1]
if opts.allow_warnings: if opts.allow_warnings:
out_lines = [] out_lines = []
for l in out.split('\n'): for l in out.split('\n'):
...@@ -233,13 +233,26 @@ def determine_test_result(fn, opts, code, out, stderr, elapsed): ...@@ -233,13 +233,26 @@ def determine_test_result(fn, opts, code, out, stderr, elapsed):
out = "\n".join(out_lines) out = "\n".join(out_lines)
stats = None stats = None
if code >= 0 and opts.collect_stats: if opts.collect_stats:
stats = {} stats = {}
assert out.count("Stats:") == 1 have_stats = (stderr.count("Stats:") == 1 and stderr.count("(End of stats)") == 1)
out, stats_str = out.split("Stats:")
for l in stats_str.strip().split('\n'): if code >= 0:
k, v = l.split(':') assert have_stats
stats[k.strip()] = int(v)
if have_stats:
assert stderr.count("Stats:") == 1
stderr, stats_str = stderr.split("Stats:")
stats_str, stderr_tail = stats_str.split("(End of stats)\n")
stderr += stderr_tail
other_stats_str, counter_str = stats_str.split("Counters:")
for l in counter_str.strip().split('\n'):
assert l.count(':') == 1, l
k, v = l.split(':')
stats[k.strip()] = int(v)
last_stderr_line = stderr.strip().split('\n')[-1]
if EXIT_CODE_ONLY: if EXIT_CODE_ONLY:
# fools the rest of this function into thinking the output is OK & just checking the exit code. # fools the rest of this function into thinking the output is OK & just checking the exit code.
......
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