Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
fb62db02
Commit
fb62db02
authored
May 07, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into HEAD
parents
f2632e45
0defcec2
Changes
50
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
1366 additions
and
402 deletions
+1366
-402
Makefile
Makefile
+18
-0
from_cpython/Include/pyconfig.h
from_cpython/Include/pyconfig.h
+3
-0
minibenchmarks/django-template.py
minibenchmarks/django-template.py
+115
-0
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+32
-10
src/analysis/function_analysis.h
src/analysis/function_analysis.h
+4
-3
src/capi/descrobject.cpp
src/capi/descrobject.cpp
+1
-0
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+29
-0
src/capi/types.h
src/capi/types.h
+3
-0
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+31
-29
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+1
-2
src/codegen/entry.cpp
src/codegen/entry.cpp
+1
-1
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+10
-2
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+6
-15
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+15
-2
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+7
-9
src/codegen/parser.cpp
src/codegen/parser.cpp
+3
-1
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+2
-0
src/core/stats.cpp
src/core/stats.cpp
+168
-5
src/core/stats.h
src/core/stats.h
+85
-7
src/core/types.h
src/core/types.h
+13
-2
src/core/util.cpp
src/core/util.cpp
+25
-8
src/core/util.h
src/core/util.h
+12
-6
src/gc/collector.cpp
src/gc/collector.cpp
+2
-0
src/gc/gc_alloc.h
src/gc/gc_alloc.h
+9
-1
src/gc/heap.cpp
src/gc/heap.cpp
+78
-15
src/gc/heap.h
src/gc/heap.h
+3
-2
src/jit.cpp
src/jit.cpp
+191
-174
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+4
-0
src/runtime/descr.cpp
src/runtime/descr.cpp
+3
-3
src/runtime/dict.cpp
src/runtime/dict.cpp
+8
-0
src/runtime/float.cpp
src/runtime/float.cpp
+98
-0
src/runtime/generator.cpp
src/runtime/generator.cpp
+39
-17
src/runtime/list.cpp
src/runtime/list.cpp
+8
-6
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+112
-30
src/runtime/stacktrace.cpp
src/runtime/stacktrace.cpp
+22
-18
src/runtime/str.cpp
src/runtime/str.cpp
+3
-0
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+2
-0
src/runtime/types.cpp
src/runtime/types.cpp
+14
-5
src/runtime/types.h
src/runtime/types.h
+65
-4
test/cpython/exception_hierarchy.txt
test/cpython/exception_hierarchy.txt
+50
-0
test/tests/exec_syntax_error.py
test/tests/exec_syntax_error.py
+4
-3
test/tests/float.py
test/tests/float.py
+8
-0
test/tests/list_subclassing.py
test/tests/list_subclassing.py
+24
-0
test/tests/name_forcing_syntax_error.py
test/tests/name_forcing_syntax_error.py
+1
-1
test/tests/package_test.py
test/tests/package_test.py
+1
-1
test/tests/test_package/absolute_import.py
test/tests/test_package/absolute_import.py
+1
-1
test/tests/test_package/absolute_import_with_future.py
test/tests/test_package/absolute_import_with_future.py
+1
-1
test/tests/test_package/intrapackage_import.py
test/tests/test_package/intrapackage_import.py
+1
-1
test/unittests/analysis.cpp
test/unittests/analysis.cpp
+6
-6
tools/tester.py
tools/tester.py
+24
-11
No files found.
Makefile
View file @
fb62db02
...
...
@@ -112,12 +112,25 @@ ifeq ($(NEED_OLD_JIT),1)
LLVM_LINK_LIBS
+=
jit
endif
LLVM_CONFIG_DBG
:=
$(LLVM_BUILD)
/Release+Asserts/bin/llvm-config
ifneq
($(wildcard $(LLVM_CONFIG_DBG)),)
LLVM_CXXFLAGS
:=
$(
shell
$(LLVM_BUILD)
/Release+Asserts/bin/llvm-config
--cxxflags
)
LLVM_LDFLAGS
:=
$(
shell
$(LLVM_BUILD)
/Release+Asserts/bin/llvm-config
--ldflags
--system-libs
--libs
$(LLVM_LINK_LIBS)
)
LLVM_LIB_DEPS
:=
$(
wildcard
$(LLVM_BUILD)
/Release+Asserts/lib/
*
)
else
LLVM_CXXFLAGS
:=
DBG_NOT_BUILT
LLVM_LDFLAGS
:=
DBG_NOT_BUILT
LLVM_LIB_DEPS
:=
DBG_NOT_BUILT
endif
LLVM_CONFIG_DEBUG
:=
$(LLVM_BUILD)
/Debug+Asserts/bin/llvm-config
ifneq
($(wildcard $(LLVM_CONFIG_DBG)),)
LLVM_DEBUG_LDFLAGS
:=
$(
shell
$(LLVM_BUILD)
/Debug+Asserts/bin/llvm-config
--ldflags
--system-libs
--libs
$(LLVM_LINK_LIBS)
)
LLVM_DEBUG_LIB_DEPS
:=
$(
wildcard
$(LLVM_BUILD)
/Debug+Asserts/lib/
*
)
else
LLVM_DEBUG_LDFLAGS
:=
DEBUG_NOT_BUILT
LLVM_DEBUG_LIB_DEPS
:=
DEBUG_NOT_BUILT
endif
LLVM_CONFIG_RELEASE
:=
$(LLVM_BUILD)
/Release/bin/llvm-config
ifneq
($(wildcard $(LLVM_CONFIG_RELEASE)),)
...
...
@@ -779,11 +792,16 @@ endef
PASS_SRCS
:=
codegen/opt/aa.cpp
PASS_OBJS
:=
$(PASS_SRCS:.cpp=.standalone.o)
ifneq
($(USE_CMAKE),1)
$(call
make_compile_config,,$(CXXFLAGS_DBG))
$(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_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
)
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
...
...
from_cpython/Include/pyconfig.h
View file @
fb62db02
...
...
@@ -61,6 +61,9 @@
#define HAVE_STRUCT_TM_TM_ZONE 1
#define HAVE_MKTIME 1
#define TIME_WITH_SYS_TIME
#define HAVE_GETTIMEOFDAY 1
#define PY_FORMAT_LONG_LONG "ll"
#define PY_FORMAT_SIZE_T "z"
...
...
minibenchmarks/django-template.py
0 → 100644
View file @
fb62db02
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> </td>
{% endif %}
{% if model.admin_url %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td> </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
,)
src/analysis/function_analysis.cpp
View file @
fb62db02
...
...
@@ -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:
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
))
return
true
;
...
...
@@ -163,6 +170,9 @@ LivenessAnalysis::LivenessAnalysis(CFG* cfg) : cfg(cfg) {
us_liveness
.
log
(
_t
.
end
());
}
LivenessAnalysis
::~
LivenessAnalysis
()
{
}
bool
LivenessAnalysis
::
isKill
(
AST_Name
*
node
,
CFGBlock
*
parent_block
)
{
if
(
node
->
id
.
str
()[
0
]
!=
'#'
)
return
false
;
...
...
@@ -487,11 +497,18 @@ bool PhiAnalysis::isPotentiallyUndefinedAt(InternedString name, CFGBlock* block)
return
definedness
.
defined_at_beginning
[
block
][
name
]
!=
DefinednessAnalysis
::
Defined
;
}
LivenessAnalysis
*
computeLivenessInfo
(
CFG
*
cfg
)
{
return
new
LivenessAnalysis
(
cfg
);
std
::
unique_ptr
<
LivenessAnalysis
>
computeLivenessInfo
(
CFG
*
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
;
for
(
auto
e
:
args
.
args
)
...
...
@@ -501,11 +518,15 @@ PhiAnalysis* computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnaly
if
(
args
.
kwarg
.
size
())
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
,
ScopeInfo
*
scope_info
)
{
std
::
unique_ptr
<
PhiAnalysis
>
computeRequiredPhis
(
const
OSREntryDescriptor
*
entry_descriptor
,
LivenessAnalysis
*
liveness
,
ScopeInfo
*
scope_info
)
{
static
StatCounter
counter
(
"num_phi_analysis"
);
counter
.
log
();
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
;
llvm
::
StringSet
<>
potentially_undefined
;
...
...
@@ -524,6 +545,7 @@ PhiAnalysis* computeRequiredPhis(const OSREntryDescriptor* entry_descriptor, Liv
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
));
}
}
src/analysis/function_analysis.h
View file @
fb62db02
...
...
@@ -45,6 +45,7 @@ private:
public:
LivenessAnalysis
(
CFG
*
cfg
);
~
LivenessAnalysis
();
// we don't keep track of node->parent_block relationships, so you have to pass both:
bool
isKill
(
AST_Name
*
node
,
CFGBlock
*
parent_block
);
...
...
@@ -105,9 +106,9 @@ public:
bool
isPotentiallyUndefinedAt
(
InternedString
name
,
CFGBlock
*
block
);
};
LivenessAnalysis
*
computeLivenessInfo
(
CFG
*
);
PhiAnalysis
*
computeRequiredPhis
(
const
ParamNames
&
,
CFG
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_info
);
PhiAnalysis
*
computeRequiredPhis
(
const
OSREntryDescriptor
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_info
);
std
::
unique_ptr
<
LivenessAnalysis
>
computeLivenessInfo
(
CFG
*
);
std
::
unique_ptr
<
PhiAnalysis
>
computeRequiredPhis
(
const
ParamNames
&
,
CFG
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_info
);
std
::
unique_ptr
<
PhiAnalysis
>
computeRequiredPhis
(
const
OSREntryDescriptor
*
,
LivenessAnalysis
*
,
ScopeInfo
*
scope_info
);
}
#endif
src/capi/descrobject.cpp
View file @
fb62db02
...
...
@@ -18,6 +18,7 @@
namespace
pyston
{
Box
*
BoxedMethodDescriptor
::
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedmethoddescriptor__call__"
);
BoxedDict
*
kwargs
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
assert
(
self
->
cls
==
method_cls
);
...
...
src/capi/typeobject.cpp
View file @
fb62db02
...
...
@@ -58,6 +58,7 @@ static int hackcheck(PyObject* self, setattrofunc func, const char* what) noexce
}
static
PyObject
*
wrap_setattr
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_setattr"
);
setattrofunc
func
=
(
setattrofunc
)
wrapped
;
int
res
;
PyObject
*
name
,
*
value
;
...
...
@@ -74,6 +75,7 @@ static PyObject* wrap_setattr(PyObject* self, PyObject* args, void* wrapped) noe
}
static
PyObject
*
wrap_delattr
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_delattr"
);
setattrofunc
func
=
(
setattrofunc
)
wrapped
;
int
res
;
PyObject
*
name
;
...
...
@@ -91,6 +93,7 @@ static PyObject* wrap_delattr(PyObject* self, PyObject* args, void* wrapped) noe
}
static
PyObject
*
wrap_hashfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_hashfunc"
);
hashfunc
func
=
(
hashfunc
)
wrapped
;
long
res
;
...
...
@@ -103,12 +106,14 @@ static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) no
}
static
PyObject
*
wrap_call
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
,
PyObject
*
kwds
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_call"
);
ternaryfunc
func
=
(
ternaryfunc
)
wrapped
;
return
(
*
func
)(
self
,
args
,
kwds
);
}
static
PyObject
*
wrap_richcmpfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
,
int
op
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_richcmpfunc"
);
richcmpfunc
func
=
(
richcmpfunc
)
wrapped
;
PyObject
*
other
;
...
...
@@ -132,6 +137,7 @@ RICHCMP_WRAPPER(gt, Py_GT)
RICHCMP_WRAPPER
(
ge
,
Py_GE
)
static
PyObject
*
wrap_next
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
STAT_TIMER
(
t0
,
"us_timer_wrap_next"
);
unaryfunc
func
=
(
unaryfunc
)
wrapped
;
PyObject
*
res
;
...
...
@@ -144,6 +150,7 @@ static PyObject* wrap_next(PyObject* self, PyObject* args, void* wrapped) {
}
static
PyObject
*
wrap_descr_get
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_descr_get"
);
descrgetfunc
func
=
(
descrgetfunc
)
wrapped
;
PyObject
*
obj
;
PyObject
*
type
=
NULL
;
...
...
@@ -162,6 +169,7 @@ static PyObject* wrap_descr_get(PyObject* self, PyObject* args, void* wrapped) n
}
static
PyObject
*
wrap_coercefunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_coercefunc"
);
coercion
func
=
(
coercion
)
wrapped
;
PyObject
*
other
,
*
res
;
int
ok
;
...
...
@@ -188,6 +196,7 @@ static PyObject* wrap_coercefunc(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_ternaryfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_ternaryfunc"
);
ternaryfunc
func
=
(
ternaryfunc
)
wrapped
;
PyObject
*
other
;
PyObject
*
third
=
Py_None
;
...
...
@@ -200,6 +209,7 @@ static PyObject* wrap_ternaryfunc(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_ternaryfunc_r
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_ternaryfunc_r"
);
ternaryfunc
func
=
(
ternaryfunc
)
wrapped
;
PyObject
*
other
;
PyObject
*
third
=
Py_None
;
...
...
@@ -212,6 +222,7 @@ static PyObject* wrap_ternaryfunc_r(PyObject* self, PyObject* args, void* wrappe
}
static
PyObject
*
wrap_unaryfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_unaryfunc"
);
unaryfunc
func
=
(
unaryfunc
)
wrapped
;
if
(
!
check_num_args
(
args
,
0
))
...
...
@@ -220,6 +231,7 @@ static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) n
}
static
PyObject
*
wrap_inquirypred
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_inquirypred"
);
inquiry
func
=
(
inquiry
)
wrapped
;
int
res
;
...
...
@@ -232,6 +244,7 @@ static PyObject* wrap_inquirypred(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrapInquirypred
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
{
STAT_TIMER
(
t0
,
"us_timer_wrapInquirypred"
);
inquiry
func
=
(
inquiry
)
wrapped
;
int
res
;
...
...
@@ -244,6 +257,7 @@ static PyObject* wrapInquirypred(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_binaryfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_binaryfunc"
);
binaryfunc
func
=
(
binaryfunc
)
wrapped
;
PyObject
*
other
;
...
...
@@ -254,6 +268,7 @@ static PyObject* wrap_binaryfunc(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_binaryfunc_l
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_binaryfunc_l"
);
binaryfunc
func
=
(
binaryfunc
)
wrapped
;
PyObject
*
other
;
...
...
@@ -268,6 +283,7 @@ static PyObject* wrap_binaryfunc_l(PyObject* self, PyObject* args, void* wrapped
}
static
PyObject
*
wrap_binaryfunc_r
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_binaryfunc_r"
);
binaryfunc
func
=
(
binaryfunc
)
wrapped
;
PyObject
*
other
;
...
...
@@ -300,6 +316,7 @@ static Py_ssize_t getindex(PyObject* self, PyObject* arg) noexcept {
}
static
PyObject
*
wrap_lenfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_lenfunc"
);
lenfunc
func
=
(
lenfunc
)
wrapped
;
Py_ssize_t
res
;
...
...
@@ -312,6 +329,7 @@ static PyObject* wrap_lenfunc(PyObject* self, PyObject* args, void* wrapped) noe
}
static
PyObject
*
wrap_indexargfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_indexargfunc"
);
ssizeargfunc
func
=
(
ssizeargfunc
)
wrapped
;
PyObject
*
o
;
Py_ssize_t
i
;
...
...
@@ -325,6 +343,7 @@ static PyObject* wrap_indexargfunc(PyObject* self, PyObject* args, void* wrapped
}
static
PyObject
*
wrap_sq_item
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_sq_item"
);
ssizeargfunc
func
=
(
ssizeargfunc
)
wrapped
;
PyObject
*
arg
;
Py_ssize_t
i
;
...
...
@@ -342,6 +361,7 @@ static PyObject* wrap_sq_item(PyObject* self, PyObject* args, void* wrapped) noe
}
static
PyObject
*
wrap_ssizessizeargfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_ssizessizeargfunc"
);
ssizessizeargfunc
func
=
(
ssizessizeargfunc
)
wrapped
;
Py_ssize_t
i
,
j
;
...
...
@@ -351,6 +371,7 @@ static PyObject* wrap_ssizessizeargfunc(PyObject* self, PyObject* args, void* wr
}
static
PyObject
*
wrap_sq_setitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_sq_setitem"
);
ssizeobjargproc
func
=
(
ssizeobjargproc
)
wrapped
;
Py_ssize_t
i
;
int
res
;
...
...
@@ -369,6 +390,7 @@ static PyObject* wrap_sq_setitem(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_sq_delitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_sq_delitem"
);
ssizeobjargproc
func
=
(
ssizeobjargproc
)
wrapped
;
Py_ssize_t
i
;
int
res
;
...
...
@@ -388,6 +410,7 @@ static PyObject* wrap_sq_delitem(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_ssizessizeobjargproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_ssizessizeobjargproc"
);
ssizessizeobjargproc
func
=
(
ssizessizeobjargproc
)
wrapped
;
Py_ssize_t
i
,
j
;
int
res
;
...
...
@@ -403,6 +426,7 @@ static PyObject* wrap_ssizessizeobjargproc(PyObject* self, PyObject* args, void*
}
static
PyObject
*
wrap_delslice
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_delslice"
);
ssizessizeobjargproc
func
=
(
ssizessizeobjargproc
)
wrapped
;
Py_ssize_t
i
,
j
;
int
res
;
...
...
@@ -418,6 +442,7 @@ static PyObject* wrap_delslice(PyObject* self, PyObject* args, void* wrapped) no
/* XXX objobjproc is a misnomer; should be objargpred */
static
PyObject
*
wrap_objobjproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_objobjproc"
);
objobjproc
func
=
(
objobjproc
)
wrapped
;
int
res
;
PyObject
*
value
;
...
...
@@ -433,6 +458,7 @@ static PyObject* wrap_objobjproc(PyObject* self, PyObject* args, void* wrapped)
}
static
PyObject
*
wrap_objobjargproc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_objobjargproc"
);
objobjargproc
func
=
(
objobjargproc
)
wrapped
;
int
res
;
PyObject
*
key
,
*
value
;
...
...
@@ -447,6 +473,7 @@ static PyObject* wrap_objobjargproc(PyObject* self, PyObject* args, void* wrappe
}
static
PyObject
*
wrap_delitem
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_delitem"
);
objobjargproc
func
=
(
objobjargproc
)
wrapped
;
int
res
;
PyObject
*
key
;
...
...
@@ -462,6 +489,7 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe
}
static
PyObject
*
wrap_cmpfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_cmpfunc"
);
cmpfunc
func
=
(
cmpfunc
)
wrapped
;
int
res
;
PyObject
*
other
;
...
...
@@ -482,6 +510,7 @@ static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noe
static
PyObject
*
wrap_init
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
,
PyObject
*
kwds
)
noexcept
{
STAT_TIMER
(
t0
,
"us_timer_wrap_init"
);
initproc
func
=
(
initproc
)
wrapped
;
if
(
func
(
self
,
args
,
kwds
)
<
0
)
...
...
src/capi/types.h
View file @
fb62db02
...
...
@@ -54,6 +54,7 @@ public:
}
static
Box
*
__call__
(
BoxedCApiFunction
*
self
,
BoxedTuple
*
varargs
,
BoxedDict
*
kwargs
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedcapifunction__call__"
);
assert
(
self
->
cls
==
capifunc_cls
);
assert
(
varargs
->
cls
==
tuple_cls
);
assert
(
kwargs
->
cls
==
dict_cls
);
...
...
@@ -111,6 +112,8 @@ public:
DEFAULT_CLASS
(
wrapperobject_cls
);
static
Box
*
__call__
(
BoxedWrapperObject
*
self
,
Box
*
args
,
Box
*
kwds
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedwrapperobject__call__"
);
assert
(
self
->
cls
==
wrapperobject_cls
);
assert
(
args
->
cls
==
tuple_cls
);
assert
(
kwds
->
cls
==
dict_cls
);
...
...
src/codegen/ast_interpreter.cpp
View file @
fb62db02
...
...
@@ -83,7 +83,6 @@ private:
Value
doBinOp
(
Box
*
left
,
Box
*
right
,
int
op
,
BinExpType
exp_type
);
void
doStore
(
AST_expr
*
node
,
Value
value
);
void
doStore
(
InternedString
name
,
Value
value
);
void
eraseDeadSymbols
();
Value
visit_assert
(
AST_Assert
*
node
);
Value
visit_assign
(
AST_Assign
*
node
);
...
...
@@ -285,6 +284,8 @@ public:
Value
ASTInterpreter
::
execute
(
ASTInterpreter
&
interpreter
,
CFGBlock
*
start_block
,
AST_stmt
*
start_at
)
{
threading
::
allowGLReadPreemption
();
STAT_TIMER
(
t0
,
"us_timer_astinterpreter_execute"
);
void
*
frame_addr
=
__builtin_frame_address
(
0
);
RegisterHelper
frame_registerer
(
&
interpreter
,
frame_addr
);
...
...
@@ -321,31 +322,6 @@ Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block
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
)
{
if
(
op
==
AST_TYPE
::
Div
&&
(
source_info
->
parent_module
->
future_flags
&
FF_DIVISION
))
{
op
=
AST_TYPE
::
TrueDiv
;
...
...
@@ -463,7 +439,26 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
if
(
ENABLE_OSR
&&
backedge
&&
(
globals
->
cls
==
module_cls
))
{
bool
can_osr
=
!
FORCE_INTERPRETER
&&
(
globals
->
cls
==
module_cls
);
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
;
for
(
auto
&
p
:
compiled_func
->
clfunc
->
osr_versions
)
{
...
...
@@ -479,7 +474,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
for
(
auto
&
name
:
phis
->
definedness
.
getDefinedNamesAtEnd
(
current_block
))
{
auto
it
=
sym_table
.
find
(
name
);
if
(
!
source_info
->
liveness
->
isLiveAtEnd
(
name
,
current_block
))
if
(
!
liveness
->
isLiveAtEnd
(
name
,
current_block
))
continue
;
if
(
phis
->
isPotentiallyUndefinedAfter
(
name
,
current_block
))
{
...
...
@@ -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),
// 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
)
{
static
StatCounter
times_osr_cancel
(
"num_osr_cancel_to_many_syms"
);
static
StatCounter
times_osr_cancel
(
"num_osr_cancel_to
o
_many_syms"
);
times_osr_cancel
.
log
();
next_block
=
node
->
target
;
return
Value
();
...
...
@@ -543,6 +542,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
arg_array
.
push_back
(
it
.
second
);
}
STAT_TIMER
(
t0
,
"us_timer_astinterpreter_jump_osrexit"
);
CompiledFunction
*
partial_func
=
compilePartialFuncInternal
(
&
exit
);
auto
arg_tuple
=
getTupleFromArgsArray
(
&
arg_array
[
0
],
arg_array
.
size
());
Box
*
r
=
partial_func
->
call
(
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
...
...
@@ -930,6 +930,8 @@ Value ASTInterpreter::visit_print(AST_Print* node) {
static
const
std
::
string
newline_str
(
"
\n
"
);
static
const
std
::
string
space_str
(
" "
);
STAT_TIMER
(
t0
,
"us_timer_visit_print"
);
Box
*
dest
=
node
->
dest
?
visit_expr
(
node
->
dest
).
o
:
getSysStdout
();
int
nvals
=
node
->
values
.
size
();
assert
(
nvals
<=
1
&&
"cfg should have lowered it to 0 or 1 values"
);
...
...
src/codegen/codegen.cpp
View file @
fb62db02
...
...
@@ -35,8 +35,7 @@ namespace pyston {
DS_DEFINE_RWLOCK
(
codegen_rwlock
);
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
)),
body
(
std
::
move
(
body
))
{
:
parent_module
(
m
),
scoping
(
scoping
),
ast
(
ast
),
cfg
(
NULL
),
fn
(
std
::
move
(
fn
)),
body
(
std
::
move
(
body
))
{
assert
(
this
->
fn
.
size
());
switch
(
ast
->
type
)
{
...
...
src/codegen/entry.cpp
View file @
fb62db02
...
...
@@ -362,7 +362,7 @@ static void handle_sigint(int signum) {
// For now, just call abort(), so that we get a traceback at least.
fprintf
(
stderr
,
"SIGINT!
\n
"
);
joinRuntime
();
Stats
::
dump
();
Stats
::
dump
(
false
);
abort
();
}
...
...
src/codegen/irgen.cpp
View file @
fb62db02
...
...
@@ -342,7 +342,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
CompiledFunction
*
cf
=
irstate
->
getCurFunction
();
ConcreteCompilerType
*
rtn_type
=
irstate
->
getReturnType
();
// llvm::MDNode* func_info = irstate->getFuncDbgInfo();
PhiAnalysis
*
phi_analysis
=
source
->
phis
[
entry_descriptor
]
;
PhiAnalysis
*
phi_analysis
=
irstate
->
getPhis
()
;
assert
(
phi_analysis
);
if
(
entry_descriptor
!=
NULL
)
...
...
@@ -1055,7 +1055,15 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
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
);
...
...
src/codegen/irgen/hooks.cpp
View file @
fb62db02
...
...
@@ -182,6 +182,7 @@ static void compileIR(CompiledFunction* cf, EffortLevel effort) {
// The codegen_lock needs to be held in W mode before calling this function:
CompiledFunction
*
compileFunction
(
CLFunction
*
f
,
FunctionSpecialization
*
spec
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
)
{
STAT_TIMER
(
t0
,
"us_timer_compileFunction"
);
Timer
_t
(
"for compileFunction()"
,
1000
);
assert
((
entry_descriptor
!=
NULL
)
+
(
spec
!=
NULL
)
==
1
);
...
...
@@ -228,19 +229,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
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
;
...
...
@@ -328,10 +316,13 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
assert
(
cf
->
clfunc
->
versions
.
size
());
}
if
(
cf
->
is_interpreted
)
if
(
cf
->
is_interpreted
)
{
STAT_TIMER
(
t0
,
"us_timer_interpreted_module_toplevel"
);
astInterpretFunction
(
cf
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
else
}
else
{
STAT_TIMER
(
t1
,
"us_timer_jitted_module_toplevel"
);
((
void
(
*
)())
cf
->
code
)();
}
}
Box
*
evalOrExec
(
CLFunction
*
cl
,
Box
*
globals
,
Box
*
boxedLocals
)
{
...
...
src/codegen/irgen/irgenerator.cpp
View file @
fb62db02
...
...
@@ -42,6 +42,19 @@ extern "C" void dumpLLVM(llvm::Value* v) {
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
::
BasicBlock
&
entry_block
=
getLLVMFunction
()
->
getEntryBlock
();
...
...
@@ -944,7 +957,7 @@ private:
CompilerVariable
*
evalName
(
AST_Name
*
node
,
UnwindInfo
unw_info
)
{
auto
scope_info
=
irstate
->
getScopeInfo
();
bool
is_kill
=
irstate
->
get
SourceInfo
()
->
liveness
->
isKill
(
node
,
myblock
);
bool
is_kill
=
irstate
->
get
Liveness
()
->
isKill
(
node
,
myblock
);
assert
(
!
is_kill
||
node
->
id
.
str
()[
0
]
==
'#'
);
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
node
->
id
);
...
...
@@ -2271,7 +2284,7 @@ private:
// ASSERT(p.first[0] != '!' || isIsDefinedName(p.first), "left a fake variable in the real
// 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,
// p.second->isGrabbed(), p.second->getVrefs());
...
...
src/codegen/irgen/irgenerator.h
View file @
fb62db02
...
...
@@ -56,7 +56,8 @@ class IRGenState {
private:
CompiledFunction
*
cf
;
SourceInfo
*
source_info
;
PhiAnalysis
*
phis
;
std
::
unique_ptr
<
LivenessAnalysis
>
liveness
;
std
::
unique_ptr
<
PhiAnalysis
>
phis
;
ParamNames
*
param_names
;
GCBuilder
*
gc
;
llvm
::
MDNode
*
func_dbg_info
;
...
...
@@ -69,13 +70,9 @@ private:
public:
IRGenState
(
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
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
),
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
(
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
);
~
IRGenState
();
CompiledFunction
*
getCurFunction
()
{
return
cf
;
}
...
...
@@ -93,7 +90,8 @@ public:
SourceInfo
*
getSourceInfo
()
{
return
source_info
;
}
PhiAnalysis
*
getPhis
()
{
return
phis
;
}
LivenessAnalysis
*
getLiveness
()
{
return
liveness
.
get
();
}
PhiAnalysis
*
getPhis
()
{
return
phis
.
get
();
}
ScopeInfo
*
getScopeInfo
();
ScopeInfo
*
getScopeInfoForNode
(
AST
*
node
);
...
...
src/codegen/parser.cpp
View file @
fb62db02
...
...
@@ -982,6 +982,7 @@ AST_Module* parse_string(const char* code) {
}
AST_Module
*
parse_file
(
const
char
*
fn
)
{
STAT_TIMER
(
t0
,
"us_timer_cpyton_parsing"
);
Timer
_t
(
"parsing"
);
if
(
ENABLE_PYPA_PARSER
)
{
...
...
@@ -1071,9 +1072,10 @@ static ParseResult _reparse(const char* fn, const std::string& cache_fn, AST_Mod
// it's not a huge deal right now, but this caching version can significantly cut down
// on the startup time (40ms -> 10ms).
AST_Module
*
caching_parse_file
(
const
char
*
fn
)
{
STAT_TIMER
(
t0
,
"us_timer_caching_parse_file"
);
static
StatCounter
us_parsing
(
"us_parsing"
);
Timer
_t
(
"parsing"
);
_t
.
setExitCallback
([](
long
t
)
{
us_parsing
.
log
(
t
);
});
_t
.
setExitCallback
([](
uint64_t
t
)
{
us_parsing
.
log
(
t
);
});
int
code
;
std
::
string
cache_fn
=
std
::
string
(
fn
)
+
"c"
;
...
...
src/codegen/unwinding.cpp
View file @
fb62db02
...
...
@@ -494,6 +494,7 @@ void unwindPythonStack(std::function<bool(std::unique_ptr<PythonFrameIteratorImp
}
static
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
getTopPythonFrame
()
{
STAT_TIMER
(
t0
,
"us_timer_getTopPythonFrame"
);
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
rtn
(
nullptr
);
unwindPythonStack
([
&
](
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
iter
)
{
rtn
=
std
::
move
(
iter
);
...
...
@@ -514,6 +515,7 @@ static const LineInfo* lineInfoForFrame(PythonFrameIteratorImpl& frame_it) {
static
StatCounter
us_gettraceback
(
"us_gettraceback"
);
BoxedTraceback
*
getTraceback
()
{
STAT_TIMER
(
t0
,
"us_timer_gettraceback"
);
if
(
!
ENABLE_FRAME_INTROSPECTION
)
{
static
bool
printed_warning
=
false
;
if
(
!
printed_warning
)
{
...
...
src/core/stats.cpp
View file @
fb62db02
...
...
@@ -17,13 +17,115 @@
#include <algorithm>
#include "core/thread_utils.h"
#include "gc/heap.h"
namespace
pyston
{
#if !DISABLE_STATS
std
::
vector
<
long
>*
Stats
::
counts
;
#if STAT_TIMERS
extern
"C"
const
char
*
getStatTimerNameById
(
int
id
)
{
return
Stats
::
getStatName
(
id
).
c_str
();
}
extern
"C"
int
getStatTimerId
()
{
return
StatTimer
::
getStack
()
->
getId
();
}
extern
"C"
const
char
*
getStatTimerName
()
{
return
getStatTimerNameById
(
getStatTimerId
());
}
__thread
StatTimer
*
StatTimer
::
stack
;
StatTimer
::
StatTimer
(
int
statid
,
bool
push
)
{
uint64_t
at_time
=
getCPUTicks
();
_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
;
bool
Stats
::
enabled
;
timespec
Stats
::
start_ts
;
uint64_t
Stats
::
start_tick
;
StatCounter
::
StatCounter
(
const
std
::
string
&
name
)
:
id
(
Stats
::
getStatId
(
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:
static
std
::
unordered_map
<
int
,
std
::
string
>
names
;
Stats
::
names
=
&
names
;
static
std
::
vector
<
long
>
counts
;
static
std
::
vector
<
uint64_t
>
counts
;
Stats
::
counts
=
&
counts
;
static
std
::
unordered_map
<
std
::
string
,
int
>
made
;
...
...
@@ -51,11 +153,40 @@ int Stats::getStatId(const std::string& name) {
return
rtn
;
}
std
::
string
Stats
::
getStatName
(
int
id
)
{
return
(
*
names
)[
id
];
}
void
Stats
::
startEstimatingCPUFreq
()
{
if
(
!
Stats
::
enabled
)
return
;
clock_gettime
(
CLOCK_REALTIME
,
&
Stats
::
start_ts
);
Stats
::
start_tick
=
getCPUTicks
();
}
// returns our estimate of the MHz of the cpu. MHz is handy because we're mostly interested in microsoecond-resolution
// timing.
double
Stats
::
estimateCPUFreq
()
{
timespec
dump_ts
;
clock_gettime
(
CLOCK_REALTIME
,
&
dump_ts
);
uint64_t
end_tick
=
getCPUTicks
();
uint64_t
wall_clock_ns
=
(
dump_ts
.
tv_sec
-
start_ts
.
tv_sec
)
*
1000000000
+
(
dump_ts
.
tv_nsec
-
start_ts
.
tv_nsec
);
return
(
double
)(
end_tick
-
Stats
::
start_tick
)
*
1000
/
wall_clock_ns
;
}
void
Stats
::
dump
(
bool
includeZeros
)
{
if
(
!
Stats
::
enabled
)
return
;
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
;
for
(
const
auto
&
p
:
*
names
)
{
...
...
@@ -64,10 +195,42 @@ void Stats::dump(bool includeZeros) {
std
::
sort
(
pairs
.
begin
(),
pairs
.
end
());
uint64_t
ticks_in_main
=
0
;
uint64_t
accumulated_stat_timer_ticks
=
0
;
for
(
int
i
=
0
;
i
<
pairs
.
size
();
i
++
)
{
if
(
includeZeros
||
(
*
counts
)[
pairs
[
i
].
second
]
>
0
)
printf
(
"%s: %ld
\n
"
,
pairs
[
i
].
first
.
c_str
(),
(
*
counts
)[
pairs
[
i
].
second
]);
if
(
includeZeros
||
(
*
counts
)[
pairs
[
i
].
second
]
>
0
)
{
if
(
startswith
(
pairs
[
i
].
first
,
"us_"
)
||
startswith
(
pairs
[
i
].
first
,
"_init_us_"
))
{
fprintf
(
stderr
,
"%s: %lu
\n
"
,
pairs
[
i
].
first
.
c_str
(),
(
uint64_t
)((
*
counts
)[
pairs
[
i
].
second
]
/
cycles_per_us
));
}
else
fprintf
(
stderr
,
"%s: %lu
\n
"
,
pairs
[
i
].
first
.
c_str
(),
(
*
counts
)[
pairs
[
i
].
second
]);
if
(
startswith
(
pairs
[
i
].
first
,
"us_timer_"
))
accumulated_stat_timer_ticks
+=
(
*
counts
)[
pairs
[
i
].
second
];
if
(
pairs
[
i
].
first
==
"ticks_in_main"
)
ticks_in_main
=
(
*
counts
)[
pairs
[
i
].
second
];
}
}
if
(
includeZeros
||
accumulated_stat_timer_ticks
>
0
)
fprintf
(
stderr
,
"ticks_all_timers: %lu
\n
"
,
accumulated_stat_timer_ticks
);
#if 0
// I want to enable this, but am leaving it disabled for the time
// being because it causes test failures due to:
//
// 1) some tests exit from main from inside catch blocks, without
// going through the logic to stop the timers.
// 2) some tests create multiple threads which causes problems
// with our non-per thread stat timers.
if (ticks_in_main && ticks_in_main != accumulated_stat_timer_ticks) {
fprintf(stderr, "WARNING: accumulated stat timer ticks != ticks in main - don't trust timer output.");
}
#endif
fprintf
(
stderr
,
"(End of stats)
\n
"
);
}
void
Stats
::
endOfInit
()
{
...
...
src/core/stats.h
View file @
fb62db02
...
...
@@ -22,23 +22,48 @@
#include <vector>
#include "core/options.h"
#include "core/util.h"
namespace
pyston
{
#define DISABLE_STATS 0
#define STAT_ALLOCATIONS 0 && !DISABLE_STATS
#define STAT_TIMERS 0 && !DISABLE_STATS
#if STAT_TIMERS
#define STAT_TIMER(id, name) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id)
#define STAT_TIMER2(id, name, at_time) \
static int _stid##id = Stats::getStatId(name); \
StatTimer _st##id(_stid##id, at_time)
#else
#define STAT_TIMER(id, name) StatTimer _st##id(0);
#define STAT_TIMER2(id, name, at_time) StatTimer _st##id(0);
#endif
#define STAT_TIMER_NAME(id) _st##id
#if !DISABLE_STATS
struct
Stats
{
private:
static
std
::
vector
<
long
>*
counts
;
static
std
::
vector
<
uint64_t
>*
counts
;
static
std
::
unordered_map
<
int
,
std
::
string
>*
names
;
static
bool
enabled
;
static
timespec
start_ts
;
static
uint64_t
start_tick
;
public:
static
void
startEstimatingCPUFreq
();
static
double
estimateCPUFreq
();
static
int
getStatId
(
const
std
::
string
&
name
);
static
std
::
string
getStatName
(
int
id
);
static
void
setEnabled
(
bool
enabled
)
{
Stats
::
enabled
=
enabled
;
}
static
void
log
(
int
id
,
in
t
count
=
1
)
{
(
*
counts
)[
id
]
+=
count
;
}
static
void
log
(
int
id
,
uint64_
t
count
=
1
)
{
(
*
counts
)[
id
]
+=
count
;
}
static
void
clear
()
{
std
::
fill
(
counts
->
begin
(),
counts
->
end
(),
0
);
}
static
void
dump
(
bool
includeZeros
=
true
);
...
...
@@ -52,7 +77,7 @@ private:
public:
StatCounter
(
const
std
::
string
&
name
);
void
log
(
in
t
count
=
1
)
{
Stats
::
log
(
id
,
count
);
}
void
log
(
uint64_
t
count
=
1
)
{
Stats
::
log
(
id
,
count
);
}
};
struct
StatPerThreadCounter
{
...
...
@@ -62,24 +87,77 @@ private:
public:
StatPerThreadCounter
(
const
std
::
string
&
name
);
void
log
(
in
t
count
=
1
)
{
Stats
::
log
(
id
,
count
);
}
void
log
(
uint64_
t
count
=
1
)
{
Stats
::
log
(
id
,
count
);
}
};
#else
struct
Stats
{
static
void
startEstimatingCPUFreq
()
{}
static
double
estimateCPUFreq
()
{
return
0
;
}
static
void
setEnabled
(
bool
enabled
)
{}
static
void
dump
()
{
printf
(
"(Stats disabled)
\n
"
);
}
static
void
dump
(
bool
includeZeros
=
true
)
{
printf
(
"(Stats disabled)
\n
"
);
}
static
void
clear
()
{}
static
void
log
(
int
id
,
int
count
=
1
)
{}
static
int
getStatId
(
const
std
::
string
&
name
)
{
return
0
;
}
static
void
endOfInit
()
{}
};
struct
StatCounter
{
StatCounter
(
const
char
*
name
)
{}
void
log
(
in
t
count
=
1
){};
void
log
(
uint64_
t
count
=
1
){};
};
struct
StatPerThreadCounter
{
StatPerThreadCounter
(
const
char
*
name
)
{}
void
log
(
int
count
=
1
){};
void
log
(
uint64_t
count
=
1
){};
};
#endif
#if STAT_TIMERS
class
StatTimer
{
private:
static
__thread
StatTimer
*
stack
;
// the 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
}
...
...
src/core/types.h
View file @
fb62db02
...
...
@@ -243,8 +243,6 @@ public:
ScopingAnalysis
*
scoping
;
AST
*
ast
;
CFG
*
cfg
;
LivenessAnalysis
*
liveness
;
std
::
unordered_map
<
const
OSREntryDescriptor
*
,
PhiAnalysis
*>
phis
;
bool
is_generator
;
std
::
string
fn
;
// equivalent of code.co_filename
...
...
@@ -487,13 +485,26 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
return Box::operator new(size, default_cls); \
}
#if STAT_ALLOCATIONS
#define ALLOC_STATS(cls) \
std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
Stats::log(Stats::getStatId(per_name_alloc_name)); \
Stats::log(Stats::getStatId(per_name_allocsize_name), size);
#else
#define ALLOC_STATS(cls)
#endif
// The restrictions on when you can use the SIMPLE (ie fast) variant are encoded as
// asserts in the 1-arg operator new function:
#define DEFAULT_CLASS_SIMPLE(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
ALLOC_STATS(cls); \
return Box::operator new(size, cls); \
} \
void* operator new(size_t size) __attribute__((visibility("default"))) { \
ALLOC_STATS(default_cls); \
/* In the simple cases, we can inline the following methods and simplify things a lot: \
* - Box::operator new \
* - cls->tp_alloc \
...
...
src/core/util.cpp
View file @
fb62db02
...
...
@@ -16,6 +16,9 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
...
...
@@ -26,6 +29,18 @@
namespace
pyston
{
static
inline
uint64_t
rdtsc
()
{
unsigned
long
lo
,
hi
;
asm
(
"rdtsc"
:
"=a"
(
lo
),
"=d"
(
hi
));
return
(
lo
|
(
hi
<<
32
));
}
uint64_t
getCPUTicks
()
{
// unsigned int _unused;
// return __rdtscp(&_unused);
return
rdtsc
();
}
int
Timer
::
level
=
0
;
Timer
::
Timer
(
const
char
*
desc
,
long
min_usec
)
:
min_usec
(
min_usec
),
ended
(
true
)
{
...
...
@@ -36,7 +51,7 @@ void Timer::restart(const char* newdesc) {
assert
(
ended
);
desc
=
newdesc
;
gettimeofday
(
&
start_time
,
NULL
);
start_time
=
getCPUTicks
(
);
Timer
::
level
++
;
ended
=
false
;
}
...
...
@@ -46,14 +61,14 @@ void Timer::restart(const char* newdesc, long new_min_usec) {
restart
(
newdesc
);
}
long
Timer
::
end
(
)
{
uint64_t
Timer
::
end
(
uint64_t
*
ended_at
)
{
if
(
!
ended
)
{
timeval
end
;
gettimeofday
(
&
end
,
NULL
);
long
us
=
1000000L
*
(
end
.
tv_sec
-
start_time
.
tv_sec
)
+
(
end
.
tv_usec
-
start_time
.
tv_usec
);
uint64_t
end
=
getCPUTicks
();
uint64_t
duration
=
end
-
start_time
;
Timer
::
level
--
;
if
(
VERBOSITY
(
"time"
)
>=
2
&&
desc
)
{
uint64_t
us
=
(
uint64_t
)(
duration
/
Stats
::
estimateCPUFreq
());
if
(
us
>
min_usec
)
{
for
(
int
i
=
0
;
i
<
Timer
::
level
;
i
++
)
{
putchar
(
' '
);
...
...
@@ -70,15 +85,17 @@ long Timer::end() {
fflush
(
stdout
);
}
}
if
(
ended_at
)
*
ended_at
=
end
;
ended
=
true
;
return
us
;
return
duration
;
}
return
-
1
;
}
Timer
::~
Timer
()
{
if
(
!
ended
)
{
long
t
=
end
();
uint64_t
t
=
end
();
if
(
exit_callback
)
exit_callback
(
t
);
}
...
...
src/core/util.h
View file @
fb62db02
...
...
@@ -24,30 +24,36 @@
namespace
pyston
{
uint64_t
getCPUTicks
();
class
Timer
{
private:
static
int
level
;
timeval
start_time
;
uint64_t
start_time
;
const
char
*
desc
;
long
min_usec
;
bool
ended
;
std
::
function
<
void
(
long
)
>
exit_callback
;
std
::
function
<
void
(
uint64_t
)
>
exit_callback
;
public:
Timer
(
const
char
*
desc
=
NULL
,
long
min_usec
=
-
1
);
~
Timer
();
void
setExitCallback
(
std
::
function
<
void
(
long
)
>
_exit_callback
)
{
exit_callback
=
_exit_callback
;
}
void
setExitCallback
(
std
::
function
<
void
(
uint64_t
)
>
_exit_callback
)
{
exit_callback
=
_exit_callback
;
}
void
restart
(
const
char
*
newdesc
,
long
new_min_usec
);
void
restart
(
const
char
*
newdesc
=
NULL
);
long
end
();
long
split
(
const
char
*
newdesc
=
NULL
)
{
long
rtn
=
end
();
// returns the duration. if @ended_at is non-null, it's filled in
// with the tick the timer stopped at.
uint64_t
end
(
uint64_t
*
ended_at
=
NULL
);
uint64_t
split
(
const
char
*
newdesc
=
NULL
)
{
uint64_t
rtn
=
end
();
restart
(
newdesc
);
return
rtn
;
}
uint64_t
getStartTime
()
const
{
return
start_time
;
}
};
bool
startswith
(
const
std
::
string
&
s
,
const
std
::
string
&
pattern
);
...
...
src/gc/collector.cpp
View file @
fb62db02
...
...
@@ -339,6 +339,8 @@ void runCollection() {
static
StatCounter
sc
(
"gc_collections"
);
sc
.
log
();
STAT_TIMER
(
t0
,
"us_timer_gc_collection"
);
ncollections
++
;
if
(
VERBOSITY
(
"gc"
)
>=
2
)
...
...
src/gc/gc_alloc.h
View file @
fb62db02
...
...
@@ -28,7 +28,9 @@ namespace pyston {
namespace
gc
{
static
StatCounter
gc_alloc_bytes
(
"zzz_gc_alloc_bytes"
);
extern
"C"
inline
void
*
gc_alloc
(
size_t
bytes
,
GCKind
kind_id
)
{
STAT_TIMER
(
t0
,
"us_timer_gc_alloc"
);
size_t
alloc_bytes
=
bytes
+
sizeof
(
GCAllocation
);
#ifndef NVALGRIND
...
...
@@ -89,8 +91,10 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
// if (VERBOSITY()) printf("Allocated %ld bytes at [%p, %p)\n", bytes, r, (char*)r + bytes);
#endif
// printf("Allocated %p\n", r);
#if STAT_ALLOCATIONS
gc_alloc_bytes
.
log
(
bytes
);
#endif
return
r
;
}
...
...
@@ -128,6 +132,10 @@ extern "C" inline void* gc_realloc(void* ptr, size_t bytes) {
alloc
->
kind_data
=
bytes
;
}
#if STAT_ALLOCATIONS
gc_alloc_bytes
.
log
(
bytes
);
#endif
return
rtn
;
}
...
...
src/gc/heap.cpp
View file @
fb62db02
...
...
@@ -185,16 +185,32 @@ struct HeapStatistics {
void
print
(
const
char
*
name
)
const
{
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
))
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
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
;
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
;
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
)
{
...
...
@@ -202,11 +218,24 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
stats
->
total
.
nbytes
+=
nbytes
;
if
(
al
->
kind_id
==
GCKind
::
PYTHON
)
{
Box
*
b
=
(
Box
*
)
al
->
user_data
;
auto
&
t
=
stats
->
by_cls
[
b
->
cls
]
;
stats
->
python
.
nallocs
++
;
stats
->
python
.
nbytes
+=
nbytes
;
t
.
nallocs
++
;
t
.
nbytes
+=
nbytes
;
if
(
stats
->
collect_cls_stats
)
{
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
)
{
stats
->
conservative
.
nallocs
++
;
stats
->
conservative
.
nbytes
+=
nbytes
;
...
...
@@ -216,6 +245,18 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
}
else
if
(
al
->
kind_id
==
GCKind
::
HIDDEN_CLASS
)
{
stats
->
hcls
.
nallocs
++
;
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
{
RELEASE_ASSERT
(
0
,
"%d"
,
(
int
)
al
->
kind_id
);
}
...
...
@@ -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
;
HeapStatistics
stats
;
fprintf
(
stderr
,
"
\n
Collecting heap stats for pid %d...
\n
"
,
getpid
());
HeapStatistics
stats
(
collect_cls_stats
,
collect_hcls_stats
);
small_arena
.
getStatistics
(
&
stats
);
large_arena
.
getStatistics
(
&
stats
);
huge_arena
.
getStatistics
(
&
stats
);
stats
.
python
.
print
(
"python"
);
stats
.
conservative
.
print
(
"conservative"
);
stats
.
untracked
.
print
(
"untracked"
);
stats
.
hcls
.
print
(
"hcls"
);
for
(
const
auto
&
p
:
stats
.
by_cls
)
{
p
.
second
.
print
(
getFullNameOfClass
(
p
.
first
).
c_str
());
stats
.
precise
.
print
(
"precise"
);
if
(
collect_cls_stats
)
{
for
(
const
auto
&
p
:
stats
.
by_cls
)
{
p
.
second
.
print
(
getFullNameOfClass
(
p
.
first
).
c_str
());
}
}
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
()
{
global_heap
.
dumpHeapStatistics
();
void
dumpHeapStatistics
(
int
level
)
{
global_heap
.
dumpHeapStatistics
(
level
);
}
//////
...
...
src/gc/heap.h
View file @
fb62db02
...
...
@@ -22,6 +22,7 @@
#include "core/common.h"
#include "core/threading.h"
#include "core/types.h"
namespace
pyston
{
...
...
@@ -535,13 +536,13 @@ public:
huge_arena
.
freeUnmarked
(
weakly_referenced
);
}
void
dumpHeapStatistics
();
void
dumpHeapStatistics
(
int
level
);
friend
void
markPhase
();
};
extern
Heap
global_heap
;
void
dumpHeapStatistics
();
void
dumpHeapStatistics
(
int
level
);
}
// namespace gc
}
// namespace pyston
...
...
src/jit.cpp
View file @
fb62db02
...
...
@@ -139,223 +139,240 @@ int handleArg(char code) {
}
static
int
main
(
int
argc
,
char
**
argv
)
{
Timer
_t
(
"for jit startup"
);
// llvm::sys::PrintStackTraceOnErrorSignal();
// llvm::PrettyStackTraceProgram X(argc, argv);
llvm
::
llvm_shutdown_obj
Y
;
int
code
;
const
char
*
command
=
NULL
;
timespec
before_ts
,
after_ts
;
Timer
main_time
;
int
rtncode
;
{
STAT_TIMER2
(
t0
,
"us_timer_main_toplevel"
,
main_time
.
getStartTime
());
int
code
;
const
char
*
command
=
NULL
;
char
*
env_args
=
getenv
(
"PYSTON_RUN_ARGS"
);
char
*
env_args
=
getenv
(
"PYSTON_RUN_ARGS"
);
if
(
env_args
)
{
while
(
*
env_args
)
{
int
r
=
handleArg
(
*
env_args
);
if
(
r
)
return
r
;
env_args
++
;
if
(
env_args
)
{
while
(
*
env_args
)
{
int
r
=
handleArg
(
*
env_args
);
if
(
r
)
return
r
;
env_args
++
;
}
}
}
// Suppress getopt errors so we can throw them ourselves
opterr
=
0
;
while
((
code
=
getopt
(
argc
,
argv
,
"+:OqdIibpjtrsSvnxEc:FuPT"
))
!=
-
1
)
{
if
(
code
==
'c'
)
{
assert
(
optarg
);
command
=
optarg
;
// no more option parsing; the rest of our arguments go into sys.argv.
break
;
}
else
if
(
code
==
':'
)
{
fprintf
(
stderr
,
"Argument expected for the -%c option
\n
"
,
optopt
);
return
2
;
}
else
if
(
code
==
'?'
)
{
fprintf
(
stderr
,
"Unknown option: -%c
\n
"
,
optopt
);
return
2
;
}
else
{
int
r
=
handleArg
(
code
);
if
(
r
)
return
r
;
// Suppress getopt errors so we can throw them ourselves
opterr
=
0
;
while
((
code
=
getopt
(
argc
,
argv
,
"+:OqdIibpjtrsSvnxEc:FuPT"
))
!=
-
1
)
{
if
(
code
==
'c'
)
{
assert
(
optarg
);
command
=
optarg
;
// no more option parsing; the rest of our arguments go into sys.argv.
break
;
}
else
if
(
code
==
':'
)
{
fprintf
(
stderr
,
"Argument expected for the -%c option
\n
"
,
optopt
);
return
2
;
}
else
if
(
code
==
'?'
)
{
fprintf
(
stderr
,
"Unknown option: -%c
\n
"
,
optopt
);
return
2
;
}
else
{
int
r
=
handleArg
(
code
);
if
(
r
)
return
r
;
}
}
}
const
char
*
fn
=
NULL
;
Stats
::
startEstimatingCPUFreq
()
;
threading
::
registerMainThread
();
threading
::
acquireGLRead
();
const
char
*
fn
=
NULL
;
Py_SetProgramName
(
argv
[
0
]);
threading
::
registerMainThread
();
threading
::
acquireGLRead
();
if
(
unbuffered
)
{
setvbuf
(
stdin
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
setvbuf
(
stdout
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
setvbuf
(
stderr
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
}
Py_SetProgramName
(
argv
[
0
]);
{
Timer
_t
(
"for initCodegen"
);
initCodegen
();
}
if
(
unbuffered
)
{
setvbuf
(
stdin
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
setvbuf
(
stdout
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
setvbuf
(
stderr
,
(
char
*
)
NULL
,
_IONBF
,
BUFSIZ
);
}
// Arguments left over after option parsing are of the form:
// [ script | - ] [ arguments... ]
// unless we've been already parsed a `-c command` option, in which case only:
// [ arguments...]
// are parsed.
if
(
command
)
addToSysArgv
(
"-c"
);
else
if
(
optind
!=
argc
)
{
addToSysArgv
(
argv
[
optind
]);
if
(
strcmp
(
"-"
,
argv
[
optind
])
!=
0
)
fn
=
argv
[
optind
];
++
optind
;
}
else
addToSysArgv
(
""
);
for
(
int
i
=
optind
;
i
<
argc
;
i
++
)
{
addToSysArgv
(
argv
[
i
]);
}
{
Timer
_t
(
"for initCodegen"
);
initCodegen
();
}
llvm
::
StringRef
module_search_path
=
Py_GetPath
();
while
(
true
)
{
std
::
pair
<
llvm
::
StringRef
,
llvm
::
StringRef
>
split_str
=
module_search_path
.
split
(
DELIM
);
if
(
split_str
.
first
==
module_search_path
)
break
;
// could not find the delimiter
appendToSysPath
(
split_str
.
first
);
module_search_path
=
split_str
.
second
;
}
// Arguments left over after option parsing are of the form:
// [ script | - ] [ arguments... ]
// unless we've been already parsed a `-c command` option, in which case only:
// [ arguments...]
// are parsed.
if
(
command
)
addToSysArgv
(
"-c"
);
else
if
(
optind
!=
argc
)
{
addToSysArgv
(
argv
[
optind
]);
if
(
strcmp
(
"-"
,
argv
[
optind
])
!=
0
)
fn
=
argv
[
optind
];
++
optind
;
}
else
addToSysArgv
(
""
);
for
(
int
i
=
optind
;
i
<
argc
;
i
++
)
{
addToSysArgv
(
argv
[
i
]);
}
if
(
!
fn
)
{
// if we are in repl or command mode prepend "" to the path
prependToSysPath
(
""
);
}
llvm
::
StringRef
module_search_path
=
Py_GetPath
();
while
(
true
)
{
std
::
pair
<
llvm
::
StringRef
,
llvm
::
StringRef
>
split_str
=
module_search_path
.
split
(
DELIM
);
if
(
split_str
.
first
==
module_search_path
)
break
;
// could not find the delimiter
appendToSysPath
(
split_str
.
first
);
module_search_path
=
split_str
.
second
;
}
if
(
!
Py_NoSiteFlag
)
{
try
{
std
::
string
module_name
=
"site"
;
importModuleLevel
(
module_name
,
None
,
None
,
0
);
}
catch
(
ExcInfo
e
)
{
e
.
printExcAndTraceback
();
return
1
;
if
(
!
fn
)
{
// if we are in repl or command mode prepend "" to the path
prependToSysPath
(
""
);
}
}
// Set encoding for standard streams. This needs to be done after
// sys.path is properly set up, so that we can import the
// encodings module.
setEncodingAndErrors
();
// end of argument parsing
_t
.
split
(
"to run"
);
BoxedModule
*
main_module
=
NULL
;
// if the user invoked `pyston -c command`
if
(
command
!=
NULL
)
{
try
{
main_module
=
createModule
(
"__main__"
,
"<string>"
);
AST_Module
*
m
=
parse_string
(
command
);
compileAndRunModule
(
m
,
main_module
);
}
catch
(
ExcInfo
e
)
{
int
retcode
=
1
;
(
void
)
handle_toplevel_exn
(
e
,
&
retcode
);
Stats
::
dump
();
return
retcode
;
if
(
!
Py_NoSiteFlag
)
{
try
{
std
::
string
module_name
=
"site"
;
importModuleLevel
(
module_name
,
None
,
None
,
0
);
}
catch
(
ExcInfo
e
)
{
e
.
printExcAndTraceback
();
return
1
;
}
}
}
if
(
fn
!=
NULL
)
{
llvm
::
SmallString
<
128
>
path
;
// Set encoding for standard streams. This needs to be done after
// sys.path is properly set up, so that we can import the
// encodings module.
setEncodingAndErrors
();
if
(
!
llvm
::
sys
::
path
::
is_absolute
(
fn
))
{
char
cwd_buf
[
1026
];
char
*
cwd
=
getcwd
(
cwd_buf
,
sizeof
(
cwd_buf
));
assert
(
cwd
);
path
=
cwd
;
}
// end of argument parsing
_t
.
split
(
"to run"
);
BoxedModule
*
main_module
=
NULL
;
llvm
::
sys
::
path
::
append
(
path
,
fn
);
llvm
::
sys
::
path
::
remove_filename
(
path
);
prependToSysPath
(
path
.
str
());
main_module
=
createModule
(
"__main__"
,
fn
);
try
{
AST_Module
*
ast
=
caching_parse_file
(
fn
);
compileAndRunModule
(
ast
,
main_module
);
}
catch
(
ExcInfo
e
)
{
int
retcode
=
1
;
(
void
)
handle_toplevel_exn
(
e
,
&
retcode
);
if
(
!
force_repl
)
{
Stats
::
dump
();
// if the user invoked `pyston -c command`
if
(
command
!=
NULL
)
{
try
{
main_module
=
createModule
(
"__main__"
,
"<string>"
);
AST_Module
*
m
=
parse_string
(
command
);
compileAndRunModule
(
m
,
main_module
);
}
catch
(
ExcInfo
e
)
{
int
retcode
=
1
;
(
void
)
handle_toplevel_exn
(
e
,
&
retcode
);
Stats
::
dump
(
false
);
return
retcode
;
}
}
}
if
(
force_repl
||
!
(
command
||
fn
))
{
printf
(
"Pyston v%d.%d (rev "
STRINGIFY
(
GITREV
)
")"
,
PYSTON_VERSION_MAJOR
,
PYSTON_VERSION_MINOR
);
printf
(
", targeting Python %d.%d.%d
\n
"
,
PYTHON_VERSION_MAJOR
,
PYTHON_VERSION_MINOR
,
PYTHON_VERSION_MICRO
);
if
(
fn
!=
NULL
)
{
llvm
::
SmallString
<
128
>
path
;
if
(
!
main_module
)
{
main_module
=
createModule
(
"__main__"
,
"<stdin>"
);
}
else
{
// main_module->fn = "<stdin>";
}
for
(;;)
{
char
*
line
=
readline
(
">> "
);
if
(
!
line
)
break
;
if
(
!
llvm
::
sys
::
path
::
is_absolute
(
fn
))
{
char
cwd_buf
[
1026
];
char
*
cwd
=
getcwd
(
cwd_buf
,
sizeof
(
cwd_buf
));
assert
(
cwd
);
path
=
cwd
;
}
add_history
(
line
);
llvm
::
sys
::
path
::
append
(
path
,
fn
);
llvm
::
sys
::
path
::
remove_filename
(
path
);
prependToSysPath
(
path
.
str
());
main_module
=
createModule
(
"__main__"
,
fn
);
try
{
AST_Module
*
m
=
parse_string
(
line
);
Timer
_t
(
"repl"
);
if
(
m
->
body
.
size
()
>
0
&&
m
->
body
[
0
]
->
type
==
AST_TYPE
::
Expr
)
{
AST_Expr
*
e
=
ast_cast
<
AST_Expr
>
(
m
->
body
[
0
]);
AST_Call
*
c
=
new
AST_Call
();
AST_Name
*
r
=
new
AST_Name
(
m
->
interned_strings
->
get
(
"repr"
),
AST_TYPE
::
Load
,
0
);
c
->
func
=
r
;
c
->
starargs
=
NULL
;
c
->
kwargs
=
NULL
;
c
->
args
.
push_back
(
e
->
value
);
c
->
lineno
=
0
;
AST_Print
*
p
=
new
AST_Print
();
p
->
dest
=
NULL
;
p
->
nl
=
true
;
p
->
values
.
push_back
(
c
);
p
->
lineno
=
0
;
m
->
body
[
0
]
=
p
;
}
compileAndRunModule
(
m
,
main_module
);
AST_Module
*
ast
=
caching_parse_file
(
fn
);
compileAndRunModule
(
ast
,
main_module
);
}
catch
(
ExcInfo
e
)
{
int
retcode
=
0xdeadbeef
;
// should never be seen
if
(
handle_toplevel_exn
(
e
,
&
retcode
))
{
Stats
::
dump
();
int
retcode
=
1
;
(
void
)
handle_toplevel_exn
(
e
,
&
retcode
);
if
(
!
force_repl
)
{
Stats
::
dump
(
false
);
return
retcode
;
}
}
}
}
threading
::
finishMainThread
();
if
(
force_repl
||
!
(
command
||
fn
))
{
printf
(
"Pyston v%d.%d (rev "
STRINGIFY
(
GITREV
)
")"
,
PYSTON_VERSION_MAJOR
,
PYSTON_VERSION_MINOR
);
printf
(
", targeting Python %d.%d.%d
\n
"
,
PYTHON_VERSION_MAJOR
,
PYTHON_VERSION_MINOR
,
PYTHON_VERSION_MICRO
);
if
(
!
main_module
)
{
main_module
=
createModule
(
"__main__"
,
"<stdin>"
);
}
else
{
// main_module->fn = "<stdin>";
}
for
(;;)
{
char
*
line
=
readline
(
">> "
);
if
(
!
line
)
break
;
add_history
(
line
);
try
{
AST_Module
*
m
=
parse_string
(
line
);
Timer
_t
(
"repl"
);
if
(
m
->
body
.
size
()
>
0
&&
m
->
body
[
0
]
->
type
==
AST_TYPE
::
Expr
)
{
AST_Expr
*
e
=
ast_cast
<
AST_Expr
>
(
m
->
body
[
0
]);
AST_Call
*
c
=
new
AST_Call
();
AST_Name
*
r
=
new
AST_Name
(
m
->
interned_strings
->
get
(
"repr"
),
AST_TYPE
::
Load
,
0
);
c
->
func
=
r
;
c
->
starargs
=
NULL
;
c
->
kwargs
=
NULL
;
c
->
args
.
push_back
(
e
->
value
);
c
->
lineno
=
0
;
AST_Print
*
p
=
new
AST_Print
();
p
->
dest
=
NULL
;
p
->
nl
=
true
;
p
->
values
.
push_back
(
c
);
p
->
lineno
=
0
;
m
->
body
[
0
]
=
p
;
}
compileAndRunModule
(
m
,
main_module
);
}
catch
(
ExcInfo
e
)
{
int
retcode
=
0xdeadbeef
;
// should never be seen
if
(
handle_toplevel_exn
(
e
,
&
retcode
))
{
Stats
::
dump
(
false
);
return
retcode
;
}
}
}
}
// Acquire the GIL to make sure we stop the other threads, since we will tear down
// data structures they are potentially running on.
// Note: we will purposefully not release the GIL on exiting.
threading
::
promoteGL
();
threading
::
finishMainThread
();
_t
.
split
(
"joinRuntime"
);
// Acquire the GIL to make sure we stop the other threads, since we will tear down
// data structures they are potentially running on.
// Note: we will purposefully not release the GIL on exiting.
threading
::
promoteGL
();
int
rtncode
=
joinRuntime
();
_t
.
split
(
"finishing up"
);
_t
.
split
(
"joinRuntime"
);
rtncode
=
joinRuntime
();
_t
.
split
(
"finishing up"
);
uint64_t
main_time_ended_at
;
uint64_t
main_time_duration
=
main_time
.
end
(
&
main_time_ended_at
);
static
StatCounter
mt
(
"ticks_in_main"
);
mt
.
log
(
main_time_duration
);
STAT_TIMER_NAME
(
t0
).
pause
(
main_time_ended_at
);
}
Stats
::
dump
(
true
);
Stats
::
dump
();
return
rtncode
;
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
fb62db02
...
...
@@ -304,6 +304,7 @@ extern "C" Box* ord(Box* obj) {
}
Box
*
range
(
Box
*
start
,
Box
*
stop
,
Box
*
step
)
{
STAT_TIMER
(
t0
,
"us_timer_builtin_range"
);
i64
istart
,
istop
,
istep
;
if
(
stop
==
NULL
)
{
istart
=
0
;
...
...
@@ -347,6 +348,7 @@ Box* notimplementedRepr(Box* self) {
}
Box
*
sorted
(
Box
*
obj
,
Box
*
cmp
,
Box
*
key
,
Box
**
args
)
{
STAT_TIMER
(
t0
,
"us_timer_builtin_sorted"
);
Box
*
reverse
=
args
[
0
];
BoxedList
*
rtn
=
new
BoxedList
();
...
...
@@ -359,6 +361,7 @@ Box* sorted(Box* obj, Box* cmp, Box* key, Box** args) {
}
Box
*
isinstance_func
(
Box
*
obj
,
Box
*
cls
)
{
STAT_TIMER
(
t0
,
"us_timer_builtin_isinstance"
);
int
rtn
=
PyObject_IsInstance
(
obj
,
cls
);
if
(
rtn
<
0
)
checkAndThrowCAPIException
();
...
...
@@ -366,6 +369,7 @@ Box* isinstance_func(Box* obj, Box* cls) {
}
Box
*
issubclass_func
(
Box
*
child
,
Box
*
parent
)
{
STAT_TIMER
(
t0
,
"us_timer_builtin_issubclass"
);
int
rtn
=
PyObject_IsSubclass
(
child
,
parent
);
if
(
rtn
<
0
)
checkAndThrowCAPIException
();
...
...
src/runtime/descr.cpp
View file @
fb62db02
...
...
@@ -19,7 +19,7 @@
namespace
pyston
{
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
)
return
self
;
...
...
@@ -169,8 +169,8 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
}
void
setupDescr
()
{
member_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
memberGet
,
UNKNOWN
,
3
)));
member_cls
->
freeze
();
member_
descriptor_
cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
memberGet
,
UNKNOWN
,
3
)));
member_
descriptor_
cls
->
freeze
();
property_cls
->
giveAttr
(
"__init__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
propertyInit
,
UNKNOWN
,
5
,
4
,
false
,
false
,
...
...
src/runtime/dict.cpp
View file @
fb62db02
...
...
@@ -48,6 +48,7 @@ Box* dictRepr(BoxedDict* self) {
}
Box
*
dictClear
(
BoxedDict
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_dictClear"
);
if
(
!
isSubclass
(
self
->
cls
,
dict_cls
))
raiseExcHelper
(
TypeError
,
"descriptor 'clear' requires a 'dict' object but received a '%s'"
,
getTypeName
(
self
));
...
...
@@ -56,6 +57,7 @@ Box* dictClear(BoxedDict* self) {
}
Box
*
dictCopy
(
BoxedDict
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_dictCopy"
);
if
(
!
isSubclass
(
self
->
cls
,
dict_cls
))
raiseExcHelper
(
TypeError
,
"descriptor 'copy' requires a 'dict' object but received a '%s'"
,
getTypeName
(
self
));
...
...
@@ -65,6 +67,7 @@ Box* dictCopy(BoxedDict* self) {
}
Box
*
dictItems
(
BoxedDict
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_dictItems"
);
BoxedList
*
rtn
=
new
BoxedList
();
rtn
->
ensure
(
self
->
d
.
size
());
...
...
@@ -77,6 +80,7 @@ Box* dictItems(BoxedDict* self) {
}
Box
*
dictValues
(
BoxedDict
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_dictValues"
);
BoxedList
*
rtn
=
new
BoxedList
();
rtn
->
ensure
(
self
->
d
.
size
());
for
(
const
auto
&
p
:
self
->
d
)
{
...
...
@@ -86,6 +90,7 @@ Box* dictValues(BoxedDict* self) {
}
Box
*
dictKeys
(
BoxedDict
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_dictKeys"
);
RELEASE_ASSERT
(
isSubclass
(
self
->
cls
,
dict_cls
),
""
);
BoxedList
*
rtn
=
new
BoxedList
();
...
...
@@ -182,6 +187,7 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept {
}
Box
*
dictGetitem
(
BoxedDict
*
self
,
Box
*
k
)
{
STAT_TIMER
(
t0
,
"us_timer_dictGetitem"
);
if
(
!
isSubclass
(
self
->
cls
,
dict_cls
))
raiseExcHelper
(
TypeError
,
"descriptor '__getitem__' requires a 'dict' object but received a '%s'"
,
getTypeName
(
self
));
...
...
@@ -306,6 +312,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
}
Box
*
dictSetitem
(
BoxedDict
*
self
,
Box
*
k
,
Box
*
v
)
{
STAT_TIMER
(
t0
,
"us_timer_dictSetitem"
);
// printf("Starting setitem\n");
Box
*&
pos
=
self
->
d
[
k
];
// printf("Got the pos\n");
...
...
@@ -320,6 +327,7 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
}
Box
*
dictDelitem
(
BoxedDict
*
self
,
Box
*
k
)
{
STAT_TIMER
(
t0
,
"us_timer_dictDelitem"
);
if
(
!
isSubclass
(
self
->
cls
,
dict_cls
))
raiseExcHelper
(
TypeError
,
"descriptor '__delitem__' requires a 'dict' object but received a '%s'"
,
getTypeName
(
self
));
...
...
src/runtime/float.cpp
View file @
fb62db02
...
...
@@ -741,6 +741,98 @@ static Box* float0(Box*, void*) {
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
()
{
_addFunc
(
"__add__"
,
BOXED_FLOAT
,
(
void
*
)
floatAddFloat
,
(
void
*
)
floatAddInt
,
(
void
*
)
floatAdd
);
float_cls
->
giveAttr
(
"__radd__"
,
float_cls
->
getattr
(
"__add__"
));
...
...
@@ -785,7 +877,13 @@ void setupFloat() {
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
(
"__getformat__"
,
new
BoxedClassmethod
(
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
floatGetFormat
,
STR
,
2
),
"__getformat__"
,
floatGetFormatDoc
)));
float_cls
->
freeze
();
floatFormatInit
();
}
void
teardownFloat
()
{
...
...
src/runtime/generator.cpp
View file @
fb62db02
...
...
@@ -86,28 +86,36 @@ Context* getReturnContextForGeneratorFrame(void* frame_addr) {
}
void
generatorEntry
(
BoxedGenerator
*
g
)
{
assert
(
g
->
cls
==
generator_cls
);
assert
(
g
->
function
->
cls
==
function_cls
);
{
STAT_TIMER2
(
t0
,
"us_timer_generator_toplevel"
,
g
->
timer_time
);
threading
::
pushGenerator
(
g
,
g
->
stack_begin
,
g
->
returnContext
);
assert
(
g
->
cls
==
generator_cls
);
assert
(
g
->
function
->
cls
==
function_cls
);
try
{
RegisterHelper
context_registerer
(
g
,
__builtin_frame_address
(
0
));
threading
::
pushGenerator
(
g
,
g
->
stack_begin
,
g
->
returnContext
);
try
{
RegisterHelper
context_registerer
(
g
,
__builtin_frame_address
(
0
));
// call body of the generator
BoxedFunctionBase
*
func
=
g
->
function
;
// call body of the generator
BoxedFunctionBase
*
func
=
g
->
function
;
Box
**
args
=
g
->
args
?
&
g
->
args
->
elts
[
0
]
:
nullptr
;
callCLFunc
(
func
->
f
,
nullptr
,
func
->
f
->
numReceivedArgs
(),
func
->
closure
,
g
,
func
->
globals
,
g
->
arg1
,
g
->
arg2
,
g
->
arg3
,
args
);
}
catch
(
ExcInfo
e
)
{
// unhandled exception: propagate the exception to the caller
g
->
exception
=
e
;
}
Box
**
args
=
g
->
args
?
&
g
->
args
->
elts
[
0
]
:
nullptr
;
callCLFunc
(
func
->
f
,
nullptr
,
func
->
f
->
numReceivedArgs
(),
func
->
closure
,
g
,
func
->
globals
,
g
->
arg1
,
g
->
arg2
,
g
->
arg3
,
args
);
}
catch
(
ExcInfo
e
)
{
// unhandled exception: propagate the exception to the caller
g
->
exception
=
e
;
}
// we returned from the body of the generator. next/send/throw will notify the caller
g
->
entryExited
=
true
;
threading
::
popGenerator
();
// we returned from the body of the generator. next/send/throw will notify the caller
g
->
entryExited
=
true
;
threading
::
popGenerator
();
#if STAT_TIMERS
g
->
timer_time
=
getCPUTicks
();
// store off the timer that our caller (in g->returnContext) will resume at
STAT_TIMER_NAME
(
t0
).
pause
(
g
->
timer_time
);
#endif
}
swapContext
(
&
g
->
context
,
g
->
returnContext
,
0
);
}
...
...
@@ -130,7 +138,21 @@ Box* generatorSend(Box* s, Box* v) {
self
->
returnValue
=
v
;
self
->
running
=
true
;
#if STAT_TIMERS
// store off the time that the generator will use to initialize its toplevel timer
self
->
timer_time
=
getCPUTicks
();
StatTimer
*
current_timers
=
StatTimer
::
swapStack
(
self
->
statTimers
,
self
->
timer_time
);
#endif
swapContext
(
&
self
->
returnContext
,
self
->
context
,
(
intptr_t
)
self
);
#if STAT_TIMERS
// if the generator exited we use the time that generatorEntry stored in self->timer_time (the same time it paused
// its timer at).
self
->
statTimers
=
StatTimer
::
swapStack
(
current_timers
,
self
->
entryExited
?
self
->
timer_time
:
getCPUTicks
());
#endif
self
->
running
=
false
;
// propagate exception to the caller
...
...
src/runtime/list.cpp
View file @
fb62db02
...
...
@@ -541,6 +541,8 @@ extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) {
}
Box
*
listMul
(
BoxedList
*
self
,
Box
*
rhs
)
{
STAT_TIMER
(
t0
,
"us_timer_listMul"
);
if
(
rhs
->
cls
!=
int_cls
)
{
raiseExcHelper
(
TypeError
,
"can't multiply sequence by non-int of type '%s'"
,
getTypeName
(
rhs
));
}
...
...
@@ -940,7 +942,7 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
}
Box
*
listEq
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
@@ -950,7 +952,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
}
Box
*
listNe
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
@@ -960,7 +962,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
}
Box
*
listLt
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
@@ -970,7 +972,7 @@ Box* listLt(BoxedList* self, Box* rhs) {
}
Box
*
listLe
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
@@ -980,7 +982,7 @@ Box* listLe(BoxedList* self, Box* rhs) {
}
Box
*
listGt
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
@@ -990,7 +992,7 @@ Box* listGt(BoxedList* self, Box* rhs) {
}
Box
*
listGe
(
BoxedList
*
self
,
Box
*
rhs
)
{
if
(
rhs
->
cls
!=
list_cls
)
{
if
(
!
isSubclass
(
rhs
->
cls
,
list_cls
)
)
{
return
NotImplemented
;
}
...
...
src/runtime/objmodel.cpp
View file @
fb62db02
...
...
@@ -125,6 +125,7 @@ static Box* (*callattrInternal3)(Box*, const std::string*, LookupScope, CallRewr
*
(
*
)(
Box
*
,
const
std
::
string
*
,
LookupScope
,
CallRewriteArgs
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
))
callattrInternal
;
size_t
PyHasher
::
operator
()(
Box
*
b
)
const
{
STAT_TIMER
(
t0
,
"us_timer_PyHasher"
);
if
(
b
->
cls
==
str_cls
)
{
StringHash
<
char
>
H
;
auto
s
=
static_cast
<
BoxedString
*>
(
b
);
...
...
@@ -138,6 +139,8 @@ size_t PyHasher::operator()(Box* b) const {
}
bool
PyEq
::
operator
()(
Box
*
lhs
,
Box
*
rhs
)
const
{
STAT_TIMER
(
t0
,
"us_timer_PyEq"
);
if
(
lhs
->
cls
==
rhs
->
cls
)
{
if
(
lhs
->
cls
==
str_cls
)
{
return
static_cast
<
BoxedString
*>
(
lhs
)
->
s
==
static_cast
<
BoxedString
*>
(
rhs
)
->
s
;
...
...
@@ -151,6 +154,8 @@ bool PyEq::operator()(Box* lhs, Box* rhs) const {
}
bool
PyLt
::
operator
()(
Box
*
lhs
,
Box
*
rhs
)
const
{
STAT_TIMER
(
t0
,
"us_timer_PyLt"
);
// TODO fix this
Box
*
cmp
=
compareInternal
(
lhs
,
rhs
,
AST_TYPE
::
Lt
,
NULL
);
assert
(
cmp
->
cls
==
bool_cls
);
...
...
@@ -211,6 +216,7 @@ extern "C" void my_assert(bool b) {
}
extern
"C"
bool
isSubclass
(
BoxedClass
*
child
,
BoxedClass
*
parent
)
{
STAT_TIMER
(
t0
,
"us_timer_isSubclass"
);
return
PyType_IsSubtype
(
child
,
parent
);
}
...
...
@@ -476,6 +482,7 @@ const char* getNameOfClass(BoxedClass* cls) {
}
HiddenClass
*
HiddenClass
::
getOrMakeChild
(
const
std
::
string
&
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_hiddenclass_getOrMakeChild"
);
assert
(
type
==
NORMAL
);
auto
it
=
children
.
find
(
attr
);
...
...
@@ -507,6 +514,8 @@ HiddenClass* HiddenClass::getAttrwrapperChild() {
* del attr from current HiddenClass, maintaining the order of the remaining attrs
*/
HiddenClass
*
HiddenClass
::
delAttrToMakeHC
(
const
std
::
string
&
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_hiddenclass_delAttrToMakeHC"
);
assert
(
type
==
NORMAL
);
int
idx
=
getOffset
(
attr
);
assert
(
idx
>=
0
);
...
...
@@ -655,8 +664,9 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
Box
*
key
=
boxString
(
attr
);
auto
it
=
d
->
d
.
find
(
key
);
if
(
it
==
d
->
d
.
end
())
if
(
it
==
d
->
d
.
end
())
{
return
NULL
;
}
return
it
->
second
;
}
...
...
@@ -980,7 +990,7 @@ Box* descriptorClsSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedClass* cls
}
// Special case: member descriptor
if
(
descr
->
cls
==
member_cls
)
{
if
(
descr
->
cls
==
member_
descriptor_
cls
)
{
if
(
rewrite_args
)
r_descr
->
addAttrGuard
(
BOX_CLS_OFFSET
,
(
uint64_t
)
descr
->
cls
);
...
...
@@ -1026,7 +1036,7 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, const
Box
*
descr
,
RewriterVar
*
r_descr
,
bool
for_call
,
Box
**
bind_obj_out
,
RewriterVar
**
r_bind_obj_out
)
{
// Special case: data descriptor: member descriptor
if
(
descr
->
cls
==
member_cls
)
{
if
(
descr
->
cls
==
member_
descriptor_
cls
)
{
static
StatCounter
slowpath
(
"slowpath_member_descriptor_get"
);
slowpath
.
log
();
...
...
@@ -1211,6 +1221,8 @@ Box* getattrInternalEx(Box* obj, const std::string& attr, GetattrRewriteArgs* re
if
(
!
cls_only
)
{
BoxedClass
*
cls
=
obj
->
cls
;
if
(
obj
->
cls
->
tp_getattro
&&
obj
->
cls
->
tp_getattro
!=
PyObject_GenericGetAttr
)
{
STAT_TIMER
(
t0
,
"us_timer_tp_getattro"
);
Box
*
r
=
obj
->
cls
->
tp_getattro
(
obj
,
boxString
(
attr
));
if
(
!
r
)
throwCAPIException
();
...
...
@@ -1218,6 +1230,8 @@ Box* getattrInternalEx(Box* obj, const std::string& attr, GetattrRewriteArgs* re
}
if
(
obj
->
cls
->
tp_getattr
)
{
STAT_TIMER
(
t0
,
"us_timer_tp_getattr"
);
Box
*
r
=
obj
->
cls
->
tp_getattr
(
obj
,
const_cast
<
char
*>
(
attr
.
c_str
()));
if
(
!
r
)
throwCAPIException
();
...
...
@@ -1242,6 +1256,8 @@ inline Box* getclsattrInternal(Box* obj, const std::string& attr, GetattrRewrite
}
extern
"C"
Box
*
getclsattr
(
Box
*
obj
,
const
char
*
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_getclsattr"
);
static
StatCounter
slowpath_getclsattr
(
"slowpath_getclsattr"
);
slowpath_getclsattr
.
log
();
...
...
@@ -1312,12 +1328,6 @@ Box* processDescriptor(Box* obj, Box* inst, Box* owner) {
}
static
Box
*
(
*
runtimeCall0
)(
Box
*
,
ArgPassSpec
)
=
(
Box
*
(
*
)(
Box
*
,
ArgPassSpec
))
runtimeCall
;
static
Box
*
(
*
runtimeCall1
)(
Box
*
,
ArgPassSpec
,
Box
*
)
=
(
Box
*
(
*
)(
Box
*
,
ArgPassSpec
,
Box
*
))
runtimeCall
;
static
Box
*
(
*
runtimeCall2
)(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
)
=
(
Box
*
(
*
)(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
))
runtimeCall
;
static
Box
*
(
*
runtimeCall3
)(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
)
=
(
Box
*
(
*
)(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
))
runtimeCall
;
Box
*
getattrInternalGeneric
(
Box
*
obj
,
const
std
::
string
&
attr
,
GetattrRewriteArgs
*
rewrite_args
,
bool
cls_only
,
bool
for_call
,
Box
**
bind_obj_out
,
RewriterVar
**
r_bind_obj_out
)
{
if
(
for_call
)
{
...
...
@@ -1635,6 +1645,8 @@ Box* getattrInternal(Box* obj, const std::string& attr, GetattrRewriteArgs* rewr
}
extern
"C"
Box
*
getattr
(
Box
*
obj
,
const
char
*
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_getattr"
);
static
StatCounter
slowpath_getattr
(
"slowpath_getattr"
);
slowpath_getattr
.
log
();
...
...
@@ -1722,7 +1734,7 @@ bool dataDescriptorSetSpecialCases(Box* obj, Box* val, Box* descr, SetattrRewrit
getset_descr
->
set
(
obj
,
val
,
getset_descr
->
closure
);
return
true
;
}
else
if
(
descr
->
cls
==
member_cls
)
{
}
else
if
(
descr
->
cls
==
member_
descriptor_
cls
)
{
BoxedMemberDescriptor
*
member_desc
=
static_cast
<
BoxedMemberDescriptor
*>
(
descr
);
PyMemberDef
member_def
;
memset
(
&
member_def
,
0
,
sizeof
(
member_def
));
...
...
@@ -1845,10 +1857,14 @@ void setattrGeneric(Box* obj, const std::string& attr, Box* val, SetattrRewriteA
}
extern
"C"
void
setattr
(
Box
*
obj
,
const
char
*
attr
,
Box
*
attr_val
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_setsattr"
);
static
StatCounter
slowpath_setattr
(
"slowpath_setattr"
);
slowpath_setattr
.
log
();
if
(
obj
->
cls
->
tp_setattr
)
{
STAT_TIMER
(
t1
,
"us_timer_tp_setattr"
);
int
rtn
=
obj
->
cls
->
tp_setattr
(
obj
,
const_cast
<
char
*>
(
attr
),
attr_val
);
if
(
rtn
)
throwCAPIException
();
...
...
@@ -1923,6 +1939,7 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
setattr
=
processDescriptor
(
setattr
,
obj
,
obj
->
cls
);
runtimeCallInternal
(
setattr
,
NULL
,
ArgPassSpec
(
2
),
boxstr
,
attr_val
,
NULL
,
NULL
,
NULL
);
}
else
{
STAT_TIMER
(
t0
,
"us_timer_tp_setattro"
);
int
r
=
tp_setattro
(
obj
,
boxstr
,
attr_val
);
if
(
r
)
throwCAPIException
();
...
...
@@ -1935,6 +1952,8 @@ bool isUserDefined(BoxedClass* cls) {
}
extern
"C"
bool
nonzero
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_nonzero"
);
assert
(
gc
::
isValidGCObject
(
obj
));
static
StatCounter
slowpath_nonzero
(
"slowpath_nonzero"
);
...
...
@@ -2009,7 +2028,7 @@ extern "C" bool nonzero(Box* obj) {
return
true
;
}
Box
*
r
=
runtimeCall
0
(
func
,
ArgPassSpec
(
0
)
);
Box
*
r
=
runtimeCall
Internal
(
func
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
// I believe this behavior is handled by the slot wrappers in CPython:
if
(
r
->
cls
==
bool_cls
)
{
BoxedBool
*
b
=
static_cast
<
BoxedBool
*>
(
r
);
...
...
@@ -2025,6 +2044,7 @@ extern "C" bool nonzero(Box* obj) {
}
extern
"C"
BoxedString
*
str
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_str"
);
static
StatCounter
slowpath_str
(
"slowpath_str"
);
slowpath_str
.
log
();
...
...
@@ -2046,6 +2066,7 @@ extern "C" BoxedString* str(Box* obj) {
}
extern
"C"
Box
*
strOrUnicode
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_strOrUnicode"
);
// Like str, but returns unicode objects unchanged.
if
(
obj
->
cls
==
unicode_cls
)
{
return
obj
;
...
...
@@ -2054,6 +2075,7 @@ extern "C" Box* strOrUnicode(Box* obj) {
}
extern
"C"
BoxedString
*
repr
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_repr"
);
static
StatCounter
slowpath_repr
(
"slowpath_repr"
);
slowpath_repr
.
log
();
...
...
@@ -2071,6 +2093,7 @@ extern "C" BoxedString* repr(Box* obj) {
}
extern
"C"
BoxedString
*
reprOrNull
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_reprOrNull"
);
try
{
Box
*
r
=
repr
(
obj
);
assert
(
r
->
cls
==
str_cls
);
// this should be checked by repr()
...
...
@@ -2081,6 +2104,7 @@ extern "C" BoxedString* reprOrNull(Box* obj) {
}
extern
"C"
BoxedString
*
strOrNull
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_strOrNull"
);
try
{
BoxedString
*
r
=
str
(
obj
);
return
static_cast
<
BoxedString
*>
(
r
);
...
...
@@ -2090,6 +2114,7 @@ extern "C" BoxedString* strOrNull(Box* obj) {
}
extern
"C"
bool
exceptionMatches
(
Box
*
obj
,
Box
*
cls
)
{
STAT_TIMER
(
t0
,
"us_timer_exceptionMatches"
);
int
rtn
=
PyErr_GivenExceptionMatches
(
obj
,
cls
);
RELEASE_ASSERT
(
rtn
>=
0
,
""
);
return
rtn
;
...
...
@@ -2114,7 +2139,7 @@ extern "C" BoxedInt* hash(Box* obj) {
raiseExcHelper
(
TypeError
,
"unhashable type: '%s'"
,
obj
->
cls
->
tp_name
);
}
Box
*
rtn
=
runtimeCall
0
(
hash
,
ArgPassSpec
(
0
)
);
Box
*
rtn
=
runtimeCall
Internal
(
hash
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
rtn
->
cls
!=
int_cls
)
{
raiseExcHelper
(
TypeError
,
"an integer is required"
);
}
...
...
@@ -2167,6 +2192,8 @@ Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, Arg
}
extern
"C"
BoxedInt
*
len
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_len"
);
static
StatCounter
slowpath_len
(
"slowpath_len"
);
slowpath_len
.
log
();
...
...
@@ -2174,6 +2201,8 @@ extern "C" BoxedInt* len(Box* obj) {
}
extern
"C"
i64
unboxedLen
(
Box
*
obj
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_unboxedLen"
);
static
StatCounter
slowpath_unboxedlen
(
"slowpath_unboxedlen"
);
slowpath_unboxedlen
.
log
();
...
...
@@ -2515,6 +2544,8 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope
extern
"C"
Box
*
callattr
(
Box
*
obj
,
const
std
::
string
*
attr
,
CallattrFlags
flags
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
const
std
::
string
*>*
keyword_names
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_callattr"
);
ASSERT
(
gc
::
isValidGCObject
(
obj
),
"%p"
,
obj
);
int
npassed_args
=
argspec
.
totalPassed
();
...
...
@@ -2704,6 +2735,9 @@ static StatCounter slowpath_callfunc_slowpath("slowpath_callfunc_slowpath");
Box
*
callFunc
(
BoxedFunctionBase
*
func
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
const
std
::
string
*>*
keyword_names
)
{
#if STAT_TIMERS
StatTimer
::
assertActive
();
#endif
/*
* Procedure:
* - First match up positional arguments; any extra go to varargs. error if too many.
...
...
@@ -3050,12 +3084,26 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
return
res
;
}
static
Box
*
callChosenCF
(
CompiledFunction
*
chosen_cf
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
Box
*
oarg1
,
Box
*
oarg2
,
Box
*
oarg3
,
Box
**
oargs
)
{
if
(
closure
&&
generator
)
return
chosen_cf
->
closure_generator_call
(
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
closure
)
return
chosen_cf
->
closure_call
(
closure
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
generator
)
return
chosen_cf
->
generator_call
(
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
return
chosen_cf
->
call
(
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
Box
*
callCLFunc
(
CLFunction
*
f
,
CallRewriteArgs
*
rewrite_args
,
int
num_output_args
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
Box
*
globals
,
Box
*
oarg1
,
Box
*
oarg2
,
Box
*
oarg3
,
Box
**
oargs
)
{
CompiledFunction
*
chosen_cf
=
pickVersion
(
f
,
num_output_args
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
assert
(
chosen_cf
->
is_interpreted
==
(
chosen_cf
->
code
==
NULL
));
if
(
chosen_cf
->
is_interpreted
)
{
STAT_TIMER
(
t0
,
"us_timer_astInterpretFunction"
);
return
astInterpretFunction
(
chosen_cf
,
num_output_args
,
closure
,
generator
,
globals
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
...
...
@@ -3084,18 +3132,21 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
}
Box
*
r
;
if
(
closure
&&
generator
)
r
=
chosen_cf
->
closure_generator_call
(
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
closure
)
r
=
chosen_cf
->
closure_call
(
closure
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
if
(
generator
)
r
=
chosen_cf
->
generator_call
(
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
else
r
=
chosen_cf
->
call
(
oarg1
,
oarg2
,
oarg3
,
oargs
);
// we duplicate the call to callChosenCf here so we can
// distinguish lexically between calls that target jitted python
// code and calls that target to builtins.
if
(
f
->
source
)
{
STAT_TIMER
(
t0
,
"us_timer_chosen_cf_body_jitted"
);
r
=
callChosenCF
(
chosen_cf
,
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
else
{
STAT_TIMER
(
t0
,
"us_timer_chosen_cf_body_builtins"
);
r
=
callChosenCF
(
chosen_cf
,
closure
,
generator
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
ASSERT
(
chosen_cf
->
spec
->
rtn_type
->
isFitBy
(
r
->
cls
),
"%s (%p) was supposed to return %s, but gave a %s"
,
g
.
func_addr_registry
.
getFuncNameAtAddress
(
chosen_cf
->
code
,
true
,
NULL
).
c_str
(),
chosen_cf
->
code
,
chosen_cf
->
spec
->
rtn_type
->
debugName
().
c_str
(),
r
->
cls
->
tp_name
);
return
r
;
}
...
...
@@ -3225,9 +3276,9 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box
**
new_args
=
(
Box
**
)
alloca
(
sizeof
(
Box
*
)
*
(
npassed_args
+
1
-
3
));
new_args
[
0
]
=
arg3
;
memcpy
(
new_args
+
1
,
args
,
(
npassed_args
-
3
)
*
sizeof
(
Box
*
));
Box
*
rtn
=
runtimeCall
(
im
->
func
,
ArgPassSpec
(
argspec
.
num_args
+
1
,
argspec
.
num_keywords
,
argspec
.
has_starargs
,
argspec
.
has_kwargs
),
im
->
obj
,
arg1
,
arg2
,
new_args
,
keyword_names
);
Box
*
rtn
=
runtimeCall
Internal
(
im
->
func
,
NULL
,
ArgPassSpec
(
argspec
.
num_args
+
1
,
argspec
.
num_keywords
,
argspec
.
has_starargs
,
argspec
.
has_kwargs
),
im
->
obj
,
arg1
,
arg2
,
new_args
,
keyword_names
);
return
rtn
;
}
}
...
...
@@ -3237,6 +3288,8 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
extern
"C"
Box
*
runtimeCall
(
Box
*
obj
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
const
std
::
string
*>*
keyword_names
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_runtimecall"
);
int
npassed_args
=
argspec
.
totalPassed
();
static
StatCounter
slowpath_runtimecall
(
"slowpath_runtimecall"
);
...
...
@@ -3394,6 +3447,8 @@ extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, Bin
}
extern
"C"
Box
*
binop
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_binop"
);
static
StatCounter
slowpath_binop
(
"slowpath_binop"
);
slowpath_binop
.
log
();
// static StatCounter nopatch_binop("nopatch_binop");
...
...
@@ -3430,11 +3485,13 @@ extern "C" Box* binop(Box* lhs, Box* rhs, int op_type) {
}
extern
"C"
Box
*
augbinop
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
static
StatCounter
slowpath_binop
(
"slowpath_binop"
);
slowpath_binop
.
log
();
// static StatCounter nopatch_binop("nopatch_binop");
STAT_TIMER
(
t0
,
"us_timer_slowpath_augbinop"
);
// int id = Stats::getStatId("slowpath_binop_" + *getTypeName(lhs) + op_name + *getTypeName(rhs));
static
StatCounter
slowpath_augbinop
(
"slowpath_augbinop"
);
slowpath_augbinop
.
log
();
// static StatCounter nopatch_binop("nopatch_augbinop");
// int id = Stats::getStatId("slowpath_augbinop_" + *getTypeName(lhs) + op_name + *getTypeName(rhs));
// Stats::log(id);
std
::
unique_ptr
<
Rewriter
>
rewriter
((
Rewriter
*
)
NULL
);
...
...
@@ -3597,6 +3654,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
}
extern
"C"
Box
*
compare
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_compare"
);
static
StatCounter
slowpath_compare
(
"slowpath_compare"
);
slowpath_compare
.
log
();
static
StatCounter
nopatch_compare
(
"nopatch_compare"
);
...
...
@@ -3622,6 +3681,8 @@ extern "C" Box* compare(Box* lhs, Box* rhs, int op_type) {
}
extern
"C"
Box
*
unaryop
(
Box
*
operand
,
int
op_type
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_unaryop"
);
static
StatCounter
slowpath_unaryop
(
"slowpath_unaryop"
);
slowpath_unaryop
.
log
();
...
...
@@ -3631,11 +3692,13 @@ extern "C" Box* unaryop(Box* operand, int op_type) {
ASSERT
(
attr_func
,
"%s.%s"
,
getTypeName
(
operand
),
op_name
.
c_str
());
Box
*
rtn
=
runtimeCall
0
(
attr_func
,
ArgPassSpec
(
0
)
);
Box
*
rtn
=
runtimeCall
Internal
(
attr_func
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
return
rtn
;
}
extern
"C"
Box
*
getitem
(
Box
*
value
,
Box
*
slice
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_getitem"
);
// This possibly could just be represented as a single callattr; the only tricky part
// are the error messages.
// Ex "(1)[1]" and "(1).__getitem__(1)" give different error messages.
...
...
@@ -3679,6 +3742,8 @@ extern "C" Box* getitem(Box* value, Box* slice) {
// target[slice] = value
extern
"C"
void
setitem
(
Box
*
target
,
Box
*
slice
,
Box
*
value
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_setitem"
);
static
StatCounter
slowpath_setitem
(
"slowpath_setitem"
);
slowpath_setitem
.
log
();
...
...
@@ -3711,6 +3776,8 @@ extern "C" void setitem(Box* target, Box* slice, Box* value) {
// del target[start:end:step]
extern
"C"
void
delitem
(
Box
*
target
,
Box
*
slice
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_delitem"
);
static
StatCounter
slowpath_delitem
(
"slowpath_delitem"
);
slowpath_delitem
.
log
();
...
...
@@ -3793,7 +3860,7 @@ extern "C" void delattrGeneric(Box* obj, const std::string& attr, DelattrRewrite
if
(
delAttr
!=
NULL
)
{
Box
*
boxstr
=
boxString
(
attr
);
Box
*
rtn
=
runtimeCall
2
(
delAttr
,
ArgPassSpec
(
2
),
clsAttr
,
obj
);
Box
*
rtn
=
runtimeCall
Internal
(
delAttr
,
NULL
,
ArgPassSpec
(
2
),
clsAttr
,
obj
,
NULL
,
NULL
,
NULL
);
return
;
}
}
...
...
@@ -3841,7 +3908,7 @@ extern "C" void delattrInternal(Box* obj, const std::string& attr, DelattrRewrit
Box
*
delAttr
=
typeLookup
(
obj
->
cls
,
delattr_str
,
NULL
);
if
(
delAttr
!=
NULL
)
{
Box
*
boxstr
=
boxString
(
attr
);
Box
*
rtn
=
runtimeCall
2
(
delAttr
,
ArgPassSpec
(
2
),
obj
,
boxstr
);
Box
*
rtn
=
runtimeCall
Internal
(
delAttr
,
NULL
,
ArgPassSpec
(
2
),
obj
,
boxstr
,
NULL
,
NULL
,
NULL
);
return
;
}
...
...
@@ -3850,6 +3917,8 @@ extern "C" void delattrInternal(Box* obj, const std::string& attr, DelattrRewrit
// del target.attr
extern
"C"
void
delattr
(
Box
*
obj
,
const
char
*
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_delattr"
);
static
StatCounter
slowpath_delattr
(
"slowpath_delattr"
);
slowpath_delattr
.
log
();
...
...
@@ -3869,6 +3938,8 @@ extern "C" Box* createBoxedIterWrapper(Box* o) {
}
extern
"C"
Box
*
createBoxedIterWrapperIfNeeded
(
Box
*
o
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_createBoxedIterWrapperIfNeeded"
);
std
::
unique_ptr
<
Rewriter
>
rewriter
(
Rewriter
::
createRewriter
(
__builtin_extract_return_addr
(
__builtin_return_address
(
0
)),
1
,
"createBoxedIterWrapperIfNeeded"
));
...
...
@@ -3901,6 +3972,8 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) {
}
extern
"C"
Box
*
getPystonIter
(
Box
*
o
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_getPystonIter"
);
Box
*
r
=
getiter
(
o
);
// assert((typeLookup(r->cls, hasnext_str, NULL) == NULL) == (r->cls->tpp_hasnext == object_cls->tpp_hasnext));
if
(
r
->
cls
->
tpp_hasnext
==
object_cls
->
tpp_hasnext
)
...
...
@@ -3938,6 +4011,9 @@ static void assertInitNone(Box* obj) {
}
Box
*
typeNew
(
Box
*
_cls
,
Box
*
arg1
,
Box
*
arg2
,
Box
**
_args
)
{
STAT_TIMER
(
t0
,
"us_timer_typeNew"
);
Box
*
arg3
=
_args
[
0
];
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
...
...
@@ -4391,6 +4467,8 @@ extern "C" void delGlobal(Box* globals, const std::string* name) {
}
extern
"C"
Box
*
getGlobal
(
Box
*
globals
,
const
std
::
string
*
name
)
{
STAT_TIMER
(
t0
,
"us_timer_slowpath_getglobal"
);
static
StatCounter
slowpath_getglobal
(
"slowpath_getglobal"
);
slowpath_getglobal
.
log
();
static
StatCounter
nopatch_getglobal
(
"nopatch_getglobal"
);
...
...
@@ -4485,6 +4563,8 @@ extern "C" Box* getGlobal(Box* globals, const std::string* name) {
}
extern
"C"
Box
*
importFrom
(
Box
*
_m
,
const
std
::
string
*
name
)
{
STAT_TIMER
(
t0
,
"us_timer_importFrom"
);
Box
*
r
=
getattrInternal
(
_m
,
*
name
,
NULL
);
if
(
r
)
return
r
;
...
...
@@ -4493,6 +4573,8 @@ extern "C" Box* importFrom(Box* _m, const std::string* name) {
}
extern
"C"
Box
*
importStar
(
Box
*
_from_module
,
BoxedModule
*
to_module
)
{
STAT_TIMER
(
t0
,
"us_timer_importStar"
);
// TODO(kmod): it doesn't seem too bad to update this to take custom globals;
// it looks like mostly a matter of changing the getattr calls to getitem.
RELEASE_ASSERT
(
getGlobals
()
==
to_module
,
"importStar doesn't support custom globals yet"
);
...
...
src/runtime/stacktrace.cpp
View file @
fb62db02
...
...
@@ -96,6 +96,7 @@ void unwindExc(Box* exc_obj) {
void
raiseRaw
(
const
ExcInfo
&
e
)
__attribute__
((
__noreturn__
));
void
raiseRaw
(
const
ExcInfo
&
e
)
{
STAT_TIMER
(
t0
,
"us_timer_raiseraw"
);
// Should set these to None before getting here:
assert
(
e
.
type
);
assert
(
e
.
value
);
...
...
@@ -160,28 +161,31 @@ extern "C" void abort() {
// In case displaying the traceback recursively calls abort:
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
&&
traceback_cls
)
{
if
(
!
recursive
)
{
recursive
=
true
;
Stats
::
dump
();
fprintf
(
stderr
,
"Someone called abort!
\n
"
);
// If we call abort(), things may be seriously wrong. Set an alarm() to
// try to handle cases that we would just hang.
// (Ex if we abort() from a static constructor, and _printStackTrace uses
// that object, _printStackTrace will hang waiting for the first construction
// to finish.)
alarm
(
1
);
try
{
_printStacktrace
();
}
catch
(
ExcInfo
)
{
fprintf
(
stderr
,
"error printing stack trace during abort()"
);
}
// If traceback_cls is NULL, then we somehow died early on, and won't be able to display a traceback.
if
(
traceback_cls
)
{
// If we call abort(), things may be seriously wrong. Set an alarm() to
// try to handle cases that we would just hang.
// (Ex if we abort() from a static constructor, and _printStackTrace uses
// that object, _printStackTrace will hang waiting for the first construction
// to finish.)
alarm
(
1
);
try
{
_printStacktrace
();
}
catch
(
ExcInfo
)
{
fprintf
(
stderr
,
"error printing stack trace during abort()"
);
}
// Cancel the alarm.
// 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.
alarm
(
0
);
// Cancel the alarm.
// 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.
alarm
(
0
);
}
}
if
(
PAUSE_AT_ABORT
)
{
...
...
src/runtime/str.cpp
View file @
fb62db02
...
...
@@ -1112,6 +1112,7 @@ extern "C" Box* strMod(BoxedString* lhs, Box* rhs) {
}
extern
"C"
Box
*
strMul
(
BoxedString
*
lhs
,
Box
*
rhs
)
{
STAT_TIMER
(
t0
,
"us_timer_strMul"
);
assert
(
isSubclass
(
lhs
->
cls
,
str_cls
));
int
n
;
...
...
@@ -1514,6 +1515,7 @@ failed:
}
extern
"C"
size_t
unicodeHashUnboxed
(
PyUnicodeObject
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_unicodeHashUnboxed"
);
if
(
self
->
hash
!=
-
1
)
return
self
->
hash
;
...
...
@@ -1524,6 +1526,7 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
}
extern
"C"
Box
*
strHash
(
BoxedString
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_strHash"
);
assert
(
isSubclass
(
self
->
cls
,
str_cls
));
StringHash
<
char
>
H
;
...
...
src/runtime/tuple.cpp
View file @
fb62db02
...
...
@@ -168,6 +168,7 @@ Box* tupleAdd(BoxedTuple* self, Box* rhs) {
}
Box
*
tupleMul
(
BoxedTuple
*
self
,
Box
*
rhs
)
{
STAT_TIMER
(
t0
,
"us_timer_tupleMul"
);
if
(
rhs
->
cls
!=
int_cls
)
{
raiseExcHelper
(
TypeError
,
"can't multiply sequence by non-int of type '%s'"
,
getTypeName
(
rhs
));
}
...
...
@@ -337,6 +338,7 @@ Box* tupleIndex(BoxedTuple* self, Box* elt) {
}
Box
*
tupleHash
(
BoxedTuple
*
self
)
{
STAT_TIMER
(
t0
,
"us_timer_tupleHash"
);
assert
(
isSubclass
(
self
->
cls
,
tuple_cls
));
int64_t
rtn
=
3527539
;
...
...
src/runtime/types.cpp
View file @
fb62db02
...
...
@@ -655,7 +655,7 @@ extern "C" void closureGCHandler(GCVisitor* v, Box* b) {
extern
"C"
{
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
,
*
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
,
*
builtin_function_or_method_cls
,
*
attrwrapperiter_cls
,
*
set_cls
,
*
frozenset_cls
;
...
...
@@ -1270,6 +1270,8 @@ public:
}
static
Box
*
setitem
(
Box
*
_self
,
Box
*
_key
,
Box
*
value
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_setitem"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1282,6 +1284,7 @@ public:
}
static
Box
*
setdefault
(
Box
*
_self
,
Box
*
_key
,
Box
*
value
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_setdefault"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1297,6 +1300,7 @@ public:
}
static
Box
*
get
(
Box
*
_self
,
Box
*
_key
,
Box
*
def
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_get"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1311,6 +1315,7 @@ public:
}
static
Box
*
getitem
(
Box
*
_self
,
Box
*
_key
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_getitem"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1344,6 +1349,7 @@ public:
}
static
Box
*
delitem
(
Box
*
_self
,
Box
*
_key
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_delitem"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1409,6 +1415,7 @@ public:
}
static
Box
*
values
(
Box
*
_self
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_values"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1423,6 +1430,7 @@ public:
}
static
Box
*
items
(
Box
*
_self
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_items"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -1461,6 +1469,7 @@ public:
}
static
Box
*
update
(
Box
*
_self
,
Box
*
_container
)
{
STAT_TIMER
(
t0
,
"us_timer_AttrWrapper_update"
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
...
...
@@ -2101,8 +2110,8 @@ void setupRuntime() {
module_cls
=
new
BoxedHeapClass
(
object_cls
,
&
moduleGCHandler
,
offsetof
(
BoxedModule
,
attrs
),
0
,
sizeof
(
BoxedModule
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"module"
)));
member_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"membe
r"
)));
member_
descriptor_
cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"member_descripto
r"
)));
capifunc_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedCApiFunction
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"capifunc"
)));
method_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
,
...
...
@@ -2132,7 +2141,7 @@ void setupRuntime() {
float_cls
->
tp_mro
=
BoxedTuple
::
create
({
float_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
});
member_
cls
->
tp_mro
=
BoxedTuple
::
create
({
membe
r_cls
,
object_cls
});
member_
descriptor_cls
->
tp_mro
=
BoxedTuple
::
create
({
member_descripto
r_cls
,
object_cls
});
capifunc_cls
->
tp_mro
=
BoxedTuple
::
create
({
capifunc_cls
,
object_cls
});
module_cls
->
tp_mro
=
BoxedTuple
::
create
({
module_cls
,
object_cls
});
method_cls
->
tp_mro
=
BoxedTuple
::
create
({
method_cls
,
object_cls
});
...
...
@@ -2187,7 +2196,7 @@ void setupRuntime() {
float_cls
->
finishInitialization
();
function_cls
->
finishInitialization
();
builtin_function_or_method_cls
->
finishInitialization
();
member_cls
->
finishInitialization
();
member_
descriptor_
cls
->
finishInitialization
();
module_cls
->
finishInitialization
();
capifunc_cls
->
finishInitialization
();
method_cls
->
finishInitialization
();
...
...
src/runtime/types.h
View file @
fb62db02
...
...
@@ -85,9 +85,9 @@ extern "C" Box* getSysStdout();
extern
"C"
{
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
,
*
enumerate_cls
,
*
xrange_cls
,
*
member_
cls
,
*
method_cls
,
*
closure_cls
,
*
generator_cls
,
*
complex_cls
,
*
basestring
_cls
,
*
property_cls
,
*
staticmethod_cls
,
*
classmethod_cls
,
*
attrwrapper_cls
,
*
pyston_getset_cls
,
*
capi
_getset_cls
,
*
builtin_function_or_method_cls
,
*
set_cls
,
*
frozenset_cls
,
*
code_cls
;
*
enumerate_cls
,
*
xrange_cls
,
*
member_
descriptor_cls
,
*
method_cls
,
*
closure_cls
,
*
generator_cls
,
*
complex
_cls
,
*
basestring_cls
,
*
property_cls
,
*
staticmethod_cls
,
*
classmethod_cls
,
*
attrwrapper_cls
,
*
pyston
_getset_cls
,
*
capi_getset_cls
,
*
builtin_function_or_method_cls
,
*
set_cls
,
*
frozenset_cls
,
*
code_cls
;
}
#define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type)
...
...
@@ -410,12 +410,37 @@ public:
size_t
size
()
{
return
s
.
size
();
}
void
*
operator
new
(
size_t
size
,
size_t
ssize
)
__attribute__
((
visibility
(
"default"
)))
{
#if STAT_ALLOCATIONS
static
StatCounter
alloc_str
(
"alloc.str"
);
static
StatCounter
alloc_str1
(
"alloc.str(1)"
);
static
StatCounter
allocsize_str
(
"allocsize.str"
);
if
(
ssize
==
1
)
alloc_str1
.
log
();
else
alloc_str
.
log
();
allocsize_str
.
log
(
str_cls
->
tp_basicsize
+
ssize
+
1
);
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
gc_alloc
(
str_cls
->
tp_basicsize
+
ssize
+
1
,
gc
::
GCKind
::
PYTHON
));
rtn
->
cls
=
str_cls
;
return
rtn
;
}
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
ssize
)
__attribute__
((
visibility
(
"default"
)))
{
#if STAT_ALLOCATIONS
static
StatCounter
alloc_str
(
"alloc.str"
);
static
StatCounter
alloc_str1
(
"alloc.str(1)"
);
static
StatCounter
allocsize_str
(
"allocsize.str"
);
if
(
ssize
==
1
)
alloc_str1
.
log
();
else
alloc_str
.
log
();
allocsize_str
.
log
(
cls
->
tp_basicsize
+
ssize
+
1
);
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
cls
->
tp_alloc
(
cls
,
ssize
+
1
));
rtn
->
cls
=
cls
;
return
rtn
;
...
...
@@ -517,12 +542,43 @@ public:
Box
**
elts
;
void
*
operator
new
(
size_t
size
,
size_t
nelts
)
__attribute__
((
visibility
(
"default"
)))
{
#if STAT_ALLOCATIONS
static
StatCounter
alloc_tuple
(
"alloc.tuple"
);
static
StatCounter
alloc_tuple0
(
"alloc.tuple(0)"
);
static
StatCounter
allocsize_tuple
(
"allocsize.tuple"
);
static
StatCounter
allocsize_tuple0
(
"allocsize.tuple(0)"
);
if
(
nelts
==
0
)
{
alloc_tuple0
.
log
();
allocsize_tuple0
.
log
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
));
}
else
{
alloc_tuple
.
log
();
allocsize_tuple
.
log
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
));
}
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
gc_alloc
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
),
gc
::
GCKind
::
PYTHON
));
rtn
->
cls
=
tuple_cls
;
return
rtn
;
}
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
nelts
)
__attribute__
((
visibility
(
"default"
)))
{
#if STAT_ALLOCATIONS
static
StatCounter
alloc_tuple
(
"alloc.tuple"
);
static
StatCounter
alloc_tuple0
(
"alloc.tuple(0)"
);
static
StatCounter
allocsize_tuple
(
"allocsize.tuple"
);
static
StatCounter
allocsize_tuple0
(
"allocsize.tuple(0)"
);
if
(
nelts
==
0
)
{
alloc_tuple0
.
log
();
allocsize_tuple0
.
log
(
_PyObject_VAR_SIZE
(
cls
,
nelts
+
1
));
}
else
{
alloc_tuple
.
log
();
allocsize_tuple
.
log
(
_PyObject_VAR_SIZE
(
cls
,
nelts
+
1
));
}
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
cls
->
tp_alloc
(
cls
,
nelts
));
rtn
->
cls
=
cls
;
return
rtn
;
...
...
@@ -732,7 +788,7 @@ public:
BoxedMemberDescriptor
(
PyMemberDef
*
member
)
:
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
{
...
...
@@ -817,6 +873,11 @@ public:
struct
Context
*
context
,
*
returnContext
;
void
*
stack_begin
;
#if STAT_TIMERS
StatTimer
*
statTimers
;
uint64_t
timer_time
;
#endif
BoxedGenerator
(
BoxedFunctionBase
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
DEFAULT_CLASS
(
generator_cls
);
...
...
test/cpython/exception_hierarchy.txt
0 → 100644
View file @
fb62db02
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
test/tests/exec_syntax_error.py
View file @
fb62db02
s
=
"""
def f():
a = 1
...
...
@@ -11,7 +10,8 @@ f()
try
:
exec
s
except
Exception
as
e
:
print
repr
(
e
)
# avoid microrevision changes to Python error messages
print
repr
(
e
).
replace
(
"because "
,
""
)
s
=
"""
def f():
...
...
@@ -27,4 +27,5 @@ f()
try
:
exec
s
except
Exception
as
e
:
print
repr
(
e
)
# avoid microrevision changes to Python error messages
print
repr
(
e
).
replace
(
"because "
,
""
)
test/tests/float.py
View file @
fb62db02
...
...
@@ -50,3 +50,11 @@ except ValueError as e:
pass
# We don't print the right thing yet:
# 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
test/tests/list_subclassing.py
View file @
fb62db02
...
...
@@ -12,3 +12,27 @@ print l
print
len
(
MyList
.
__new__
(
MyList
))
l
[:]
=
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
))
test/tests/name_forcing_syntax_error.py
View file @
fb62db02
...
...
@@ -208,6 +208,6 @@ for case in cases:
try
:
exec
case
except
SyntaxError
as
se
:
print
se
.
message
print
se
.
message
.
replace
(
"because "
,
""
)
# TODO uncomment this
# traceback.print_exc()
test/tests/package_test.py
View file @
fb62db02
import
os
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.absolute_import
...
...
test/tests/test_package/absolute_import.py
View file @
fb62db02
import
os
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"
)
test/tests/test_package/absolute_import_with_future.py
View file @
fb62db02
...
...
@@ -2,4 +2,4 @@ from __future__ import absolute_import
import
os
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"
)
test/tests/test_package/intrapackage_import.py
View file @
fb62db02
import
os
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"
)
test/unittests/analysis.cpp
View file @
fb62db02
...
...
@@ -39,7 +39,7 @@ TEST_F(AnalysisTest, augassign) {
SourceInfo
*
si
=
new
SourceInfo
(
createModule
(
"augassign"
,
fn
),
scoping
,
func
,
func
->
body
,
fn
);
CFG
*
cfg
=
computeCFG
(
si
,
func
->
body
);
LivenessAnalysis
*
liveness
=
computeLivenessInfo
(
cfg
);
std
::
unique_ptr
<
LivenessAnalysis
>
liveness
=
computeLivenessInfo
(
cfg
);
//cfg->print();
...
...
@@ -49,7 +49,7 @@ TEST_F(AnalysisTest, augassign) {
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
)
{
...
...
@@ -67,7 +67,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
scoping
,
func
,
func
->
body
,
fn
);
CFG
*
cfg
=
computeCFG
(
si
,
func
->
body
);
LivenessAnalysis
*
liveness
=
computeLivenessInfo
(
cfg
);
std
::
unique_ptr
<
LivenessAnalysis
>
liveness
=
computeLivenessInfo
(
cfg
);
// cfg->print();
...
...
@@ -83,7 +83,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
AST_Jump
*
backedge
=
ast_cast
<
AST_Jump
>
(
loop_backedge
->
body
[
0
]);
ASSERT_LE
(
backedge
->
target
->
idx
,
loop_backedge
->
idx
);
PhiAnalysis
*
phis
;
std
::
unique_ptr
<
PhiAnalysis
>
phis
;
if
(
is_osr
)
{
OSREntryDescriptor
*
entry_descriptor
=
OSREntryDescriptor
::
create
(
NULL
,
backedge
);
...
...
@@ -91,9 +91,9 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
if
(
i_maybe_undefined
)
entry_descriptor
->
args
[
idi_str
]
=
NULL
;
entry_descriptor
->
args
[
iter_str
]
=
NULL
;
phis
=
computeRequiredPhis
(
entry_descriptor
,
liveness
,
scope_info
);
phis
=
computeRequiredPhis
(
entry_descriptor
,
liveness
.
get
()
,
scope_info
);
}
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.
...
...
tools/tester.py
View file @
fb62db02
...
...
@@ -125,6 +125,8 @@ def canonicalize_stderr(stderr):
(
"AttributeError: '(
\
w+)
'
object attribute '(
\
w+)
'
is read-only"
,
"AttributeError:
\
\
2"
),
(
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"
),
(
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
:
...
...
@@ -206,9 +208,6 @@ def get_test_options(fn, check_stats, run_memcheck):
elif
os
.
path
.
basename
(
fn
).
split
(
'.'
)[
0
]
in
TESTS_TO_SKIP
:
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
if
TEST_PYPY
:
...
...
@@ -217,11 +216,12 @@ def get_test_options(fn, check_stats, run_memcheck):
opts
.
check_stats
=
False
opts
.
expected
=
"success"
if
opts
.
collect_stats
:
opts
.
jit_args
=
[
'-s'
]
+
opts
.
jit_args
return
opts
def
determine_test_result
(
fn
,
opts
,
code
,
out
,
stderr
,
elapsed
):
last_stderr_line
=
stderr
.
strip
().
split
(
'
\
n
'
)[
-
1
]
if
opts
.
allow_warnings
:
out_lines
=
[]
for
l
in
out
.
split
(
'
\
n
'
):
...
...
@@ -233,13 +233,26 @@ def determine_test_result(fn, opts, code, out, stderr, elapsed):
out
=
"
\
n
"
.
join
(
out_lines
)
stats
=
None
if
code
>=
0
and
opts
.
collect_stats
:
if
opts
.
collect_stats
:
stats
=
{}
assert
out
.
count
(
"Stats:"
)
==
1
out
,
stats_str
=
out
.
split
(
"Stats:"
)
for
l
in
stats_str
.
strip
().
split
(
'
\
n
'
):
k
,
v
=
l
.
split
(
':'
)
stats
[
k
.
strip
()]
=
int
(
v
)
have_stats
=
(
stderr
.
count
(
"Stats:"
)
==
1
and
stderr
.
count
(
"(End of stats)"
)
==
1
)
if
code
>=
0
:
assert
have_stats
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
:
# fools the rest of this function into thinking the output is OK & just checking the exit code.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment