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
0c84c153
Commit
0c84c153
authored
Jul 14, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #703 from kmod/tiering_merge
type speculation support
parents
dae4f6b2
a077670c
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
147 additions
and
87 deletions
+147
-87
src/analysis/type_analysis.cpp
src/analysis/type_analysis.cpp
+2
-6
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+0
-22
src/asm_writing/rewriter.h
src/asm_writing/rewriter.h
+0
-1
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+12
-7
src/codegen/ast_interpreter.h
src/codegen/ast_interpreter.h
+2
-2
src/codegen/baseline_jit.cpp
src/codegen/baseline_jit.cpp
+24
-13
src/codegen/baseline_jit.h
src/codegen/baseline_jit.h
+12
-8
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+12
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+4
-1
src/codegen/irgen/util.cpp
src/codegen/irgen/util.cpp
+52
-3
src/codegen/patchpoints.cpp
src/codegen/patchpoints.cpp
+7
-5
src/codegen/patchpoints.h
src/codegen/patchpoints.h
+1
-0
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+1
-1
src/codegen/type_recording.h
src/codegen/type_recording.h
+1
-0
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+7
-5
src/core/threading.h
src/core/threading.h
+4
-2
src/core/types.h
src/core/types.h
+3
-2
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+3
-9
No files found.
src/analysis/type_analysis.cpp
View file @
0c84c153
...
...
@@ -74,10 +74,7 @@ static BoxedClass* simpleCallSpeculation(AST_Call* node, CompilerType* rtn_type,
if
(
node
->
func
->
type
==
AST_TYPE
::
Name
&&
ast_cast
<
AST_Name
>
(
node
->
func
)
->
id
.
s
()
==
"xrange"
)
return
xrange_cls
;
// if (node->func->type == AST_TYPE::Attribute && ast_cast<AST_Attribute>(node->func)->attr == "dot")
// return float_cls;
return
NULL
;
return
predictClassFor
(
node
);
}
typedef
llvm
::
DenseMap
<
InternedString
,
CompilerType
*>
TypeMap
;
...
...
@@ -115,8 +112,7 @@ private:
assert
(
old_type
);
assert
(
speculation
!=
TypeAnalysis
::
NONE
);
if
(
VERBOSITY
()
>=
3
)
printf
(
"Would maybe try to speculate but deopt is currently broken
\n
"
);
// TODO: reenable this
return
old_type
;
if
(
speculated_cls
!=
NULL
&&
speculated_cls
->
is_constant
)
{
...
...
src/asm_writing/rewriter.cpp
View file @
0c84c153
...
...
@@ -1940,28 +1940,6 @@ bool spillFrameArgumentIfNecessary(StackMap::Record::Location& l, uint8_t*& inst
}
}
void
*
extractSlowpathFunc
(
uint8_t
*
pp_addr
)
{
#ifndef NDEBUG
// mov $imm, %r11:
ASSERT
(
pp_addr
[
0
]
==
0x49
,
"%x"
,
pp_addr
[
0
]);
assert
(
pp_addr
[
1
]
==
0xbb
);
// 8 bytes of the addr
// callq *%r11:
assert
(
pp_addr
[
10
]
==
0x41
);
assert
(
pp_addr
[
11
]
==
0xff
);
assert
(
pp_addr
[
12
]
==
0xd3
);
int
i
=
INITIAL_CALL_SIZE
;
while
(
*
(
pp_addr
+
i
)
==
0x66
||
*
(
pp_addr
+
i
)
==
0x0f
||
*
(
pp_addr
+
i
)
==
0x2e
)
i
++
;
assert
(
*
(
pp_addr
+
i
)
==
0x90
||
*
(
pp_addr
+
i
)
==
0x1f
);
#endif
void
*
call_addr
=
*
(
void
**
)
&
pp_addr
[
2
];
return
call_addr
;
}
void
setSlowpathFunc
(
uint8_t
*
pp_addr
,
void
*
func
)
{
#ifndef NDEBUG
// mov $imm, %r11:
...
...
src/asm_writing/rewriter.h
View file @
0c84c153
...
...
@@ -518,7 +518,6 @@ public:
friend
class
RewriterVar
;
};
void
*
extractSlowpathFunc
(
uint8_t
*
pp_addr
);
void
setSlowpathFunc
(
uint8_t
*
pp_addr
,
void
*
func
);
struct
GRCompare
{
...
...
src/codegen/ast_interpreter.cpp
View file @
0c84c153
...
...
@@ -711,6 +711,9 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
std
::
map
<
InternedString
,
Box
*>
sorted_symbol_table
;
// TODO: maybe use a different placeholder?
static
Box
*
const
VAL_UNDEFINED
=
(
Box
*
)
-
1
;
for
(
auto
&
name
:
phis
->
definedness
.
getDefinedNamesAtEnd
(
current_block
))
{
auto
it
=
sym_table
.
find
(
name
);
if
(
!
liveness
->
isLiveAtEnd
(
name
,
current_block
))
...
...
@@ -722,10 +725,11 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sorted_symbol_table
[
getIsDefinedName
(
name
,
source_info
->
getInternedStrings
())]
=
(
Box
*
)
is_defined
;
if
(
is_defined
)
assert
(
sym_table
.
getMapped
(
it
->
second
)
!=
NULL
);
sorted_symbol_table
[
name
]
=
is_defined
?
sym_table
.
getMapped
(
it
->
second
)
:
NULL
;
sorted_symbol_table
[
name
]
=
is_defined
?
sym_table
.
getMapped
(
it
->
second
)
:
VAL_UNDEFINED
;
}
else
{
ASSERT
(
it
!=
sym_table
.
end
(),
"%s"
,
name
.
c_str
());
sorted_symbol_table
[
it
->
first
]
=
sym_table
.
getMapped
(
it
->
second
);
Box
*
v
=
sorted_symbol_table
[
it
->
first
]
=
sym_table
.
getMapped
(
it
->
second
);
assert
(
gc
::
isValidGCObject
(
v
));
}
}
...
...
@@ -1363,7 +1367,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
CallattrFlags
callattr_flags
{.
cls_only
=
callattr_clsonly
,
.
null_on_nonexistent
=
false
,
.
argspec
=
argspec
};
if
(
jit
)
v
.
var
=
jit
->
emitCallattr
(
func
,
attr
.
getBox
(),
callattr_flags
,
args_vars
,
keyword_names
);
v
.
var
=
jit
->
emitCallattr
(
node
,
func
,
attr
.
getBox
(),
callattr_flags
,
args_vars
,
keyword_names
);
v
.
o
=
callattr
(
func
.
o
,
attr
.
getBox
(),
callattr_flags
,
args
.
size
()
>
0
?
args
[
0
]
:
0
,
args
.
size
()
>
1
?
args
[
1
]
:
0
,
args
.
size
()
>
2
?
args
[
2
]
:
0
,
args
.
size
()
>
3
?
&
args
[
3
]
:
0
,
...
...
@@ -1373,7 +1377,7 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
Value
v
;
if
(
jit
)
v
.
var
=
jit
->
emitRuntimeCall
(
func
,
argspec
,
args_vars
,
keyword_names
);
v
.
var
=
jit
->
emitRuntimeCall
(
node
,
func
,
argspec
,
args_vars
,
keyword_names
);
v
.
o
=
runtimeCall
(
func
.
o
,
argspec
,
args
.
size
()
>
0
?
args
[
0
]
:
0
,
args
.
size
()
>
1
?
args
[
1
]
:
0
,
args
.
size
()
>
2
?
args
[
2
]
:
0
,
args
.
size
()
>
3
?
&
args
[
3
]
:
0
,
keyword_names
);
...
...
@@ -1547,7 +1551,8 @@ Value ASTInterpreter::visit_tuple(AST_Tuple* node) {
Value
ASTInterpreter
::
visit_attribute
(
AST_Attribute
*
node
)
{
Value
v
=
visit_expr
(
node
->
value
);
return
Value
(
pyston
::
getattr
(
v
.
o
,
node
->
attr
.
getBox
()),
jit
?
jit
->
emitGetAttr
(
v
,
node
->
attr
.
getBox
())
:
NULL
);
return
Value
(
pyston
::
getattr
(
v
.
o
,
node
->
attr
.
getBox
()),
jit
?
jit
->
emitGetAttr
(
v
,
node
->
attr
.
getBox
(),
node
)
:
NULL
);
}
}
...
...
@@ -1749,7 +1754,7 @@ Box* astInterpretFunctionEval(CLFunction* clfunc, Box* globals, Box* boxedLocals
return
v
.
o
?
v
.
o
:
None
;
}
Box
*
astInterpret
From
(
CLFunction
*
clfunc
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpret
Deopt
(
CLFunction
*
clfunc
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
)
{
assert
(
clfunc
);
assert
(
enclosing_stmt
);
...
...
src/codegen/ast_interpreter.h
View file @
0c84c153
...
...
@@ -75,7 +75,7 @@ void setupInterpreter();
Box
*
astInterpretFunction
(
CLFunction
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
Box
*
astInterpretFunctionEval
(
CLFunction
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
);
Box
*
astInterpret
From
(
CLFunction
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpret
Deopt
(
CLFunction
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
);
AST_stmt
*
getCurrentStatementForInterpretedFrame
(
void
*
frame_ptr
);
...
...
src/codegen/baseline_jit.cpp
View file @
0c84c153
...
...
@@ -19,6 +19,7 @@
#include "codegen/irgen/hooks.h"
#include "codegen/memmgr.h"
#include "codegen/type_recording.h"
#include "core/cfg.h"
#include "runtime/objmodel.h"
#include "runtime/set.h"
...
...
@@ -133,9 +134,11 @@ RewriterVar* JitFragmentWriter::emitBinop(RewriterVar* lhs, RewriterVar* rhs, in
return
emitPPCall
((
void
*
)
binop
,
{
lhs
,
rhs
,
imm
(
op_type
)
},
2
,
240
);
}
RewriterVar
*
JitFragmentWriter
::
emitCallattr
(
RewriterVar
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
RewriterVar
*
JitFragmentWriter
::
emitCallattr
(
AST_expr
*
node
,
RewriterVar
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
TypeRecorder
*
type_recorder
=
getTypeRecorderForNode
(
node
);
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
attr_var
=
imm
(
attr
);
RewriterVar
*
flags_var
=
imm
(
flags
.
asInt
());
...
...
@@ -159,7 +162,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
return
emitPPCall
((
void
*
)
callattr
,
call_args
,
2
,
640
);
return
emitPPCall
((
void
*
)
callattr
,
call_args
,
2
,
640
,
type_recorder
);
#else
// We could make this faster but for now: keep it simple, stupid...
RewriterVar
*
attr_var
=
imm
(
attr
);
...
...
@@ -177,6 +180,8 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
call_args
.
push_back
(
attr_var
);
call_args
.
push_back
(
flags_var
);
call_args
.
push_back
(
imm
(
type_recorder
));
if
(
args_array
)
call_args
.
push_back
(
args_array
);
if
(
keyword_names_var
)
...
...
@@ -247,8 +252,8 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
return
call
(
false
,
(
void
*
)
exceptionMatchesHelper
,
v
,
cls
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
)
{
return
emitPPCall
((
void
*
)
getattr
,
{
obj
,
imm
(
s
)
},
2
,
512
);
RewriterVar
*
JitFragmentWriter
::
emitGetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
,
AST_expr
*
node
)
{
return
emitPPCall
((
void
*
)
getattr
,
{
obj
,
imm
(
s
)
},
2
,
512
,
getTypeRecorderForNode
(
node
)
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetBlockLocal
(
InternedString
s
)
{
...
...
@@ -311,9 +316,11 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) {
return
call
(
false
,
(
void
*
)
repr
,
v
);
}
RewriterVar
*
JitFragmentWriter
::
emitRuntimeCall
(
RewriterVar
*
obj
,
ArgPassSpec
argspec
,
RewriterVar
*
JitFragmentWriter
::
emitRuntimeCall
(
AST_expr
*
node
,
RewriterVar
*
obj
,
ArgPassSpec
argspec
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
TypeRecorder
*
type_recorder
=
getTypeRecorderForNode
(
node
);
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
argspec_var
=
imm
(
argspec
.
asInt
());
RewriterVar
::
SmallVector
call_args
;
...
...
@@ -333,7 +340,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
return
emitPPCall
((
void
*
)
runtimeCall
,
call_args
,
2
,
640
);
return
emitPPCall
((
void
*
)
runtimeCall
,
call_args
,
2
,
640
,
type_recorder
);
#else
RewriterVar
*
argspec_var
=
imm
(
argspec
.
asInt
());
RewriterVar
*
keyword_names_var
=
keyword_names
?
imm
(
keyword_names
)
:
nullptr
;
...
...
@@ -347,6 +354,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
RewriterVar
::
SmallVector
call_args
;
call_args
.
push_back
(
obj
);
call_args
.
push_back
(
argspec_var
);
call_args
.
push_back
(
imm
(
type_recorder
));
if
(
args_array
)
call_args
.
push_back
(
args_array
);
if
(
keyword_names_var
)
...
...
@@ -570,12 +578,14 @@ RewriterVar* JitFragmentWriter::getInterp() {
}
RewriterVar
*
JitFragmentWriter
::
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
)
{
int
slot_size
,
TypeRecorder
*
type_recorder
)
{
RewriterVar
::
SmallVector
args_vec
(
args
.
begin
(),
args
.
end
());
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
result
=
createNewVar
();
addAction
([
=
]()
{
this
->
_emitPPCall
(
result
,
func_addr
,
args_vec
,
num_slots
,
slot_size
);
},
args
,
ActionType
::
NORMAL
);
if
(
type_recorder
)
return
call
(
false
,
(
void
*
)
recordType
,
imm
(
type_recorder
),
result
);
return
result
;
#else
assert
(
args_vec
.
size
()
<
7
);
...
...
@@ -583,13 +593,13 @@ RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<Rewri
#endif
}
Box
*
JitFragmentWriter
::
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
Box
*
JitFragmentWriter
::
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
TypeRecorder
*
type_recorder
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
flags
.
argspec
.
totalPassed
());
Box
*
r
=
callattr
(
obj
,
attr
,
flags
,
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
std
::
get
<
3
>
(
arg_tuple
),
keyword_names
);
assert
(
gc
::
isValidGCObject
(
r
));
return
r
;
return
r
ecordType
(
type_recorder
,
r
)
;
}
Box
*
JitFragmentWriter
::
createDictHelper
(
uint64_t
num
,
Box
**
keys
,
Box
**
values
)
{
...
...
@@ -639,11 +649,12 @@ Box* JitFragmentWriter::notHelper(Box* b) {
return
boxBool
(
!
b
->
nonzeroIC
());
}
Box
*
JitFragmentWriter
::
runtimeCallHelper
(
Box
*
obj
,
ArgPassSpec
argspec
,
Box
**
args
,
Box
*
JitFragmentWriter
::
runtimeCallHelper
(
Box
*
obj
,
ArgPassSpec
argspec
,
TypeRecorder
*
type_recorder
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
argspec
.
totalPassed
());
return
runtimeCall
(
obj
,
argspec
,
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
Box
*
r
=
runtimeCall
(
obj
,
argspec
,
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
std
::
get
<
3
>
(
arg_tuple
),
keyword_names
);
return
recordType
(
type_recorder
,
r
);
}
...
...
src/codegen/baseline_jit.h
View file @
0c84c153
...
...
@@ -33,6 +33,8 @@ class BoxedDict;
class
BoxedList
;
class
BoxedTuple
;
class
TypeRecorder
;
class
JitFragmentWriter
;
// This JIT tier is designed as Pystons entry level JIT tier (executed after a only a few dozens runs of a basic block)
...
...
@@ -193,7 +195,7 @@ public:
RewriterVar
*
emitAugbinop
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
);
RewriterVar
*
emitBinop
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
);
RewriterVar
*
emitCallattr
(
RewriterVar
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
RewriterVar
*
emitCallattr
(
AST_expr
*
node
,
RewriterVar
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
RewriterVar
*
emitCompare
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
);
RewriterVar
*
emitCreateDict
(
const
llvm
::
ArrayRef
<
RewriterVar
*>
keys
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
values
);
...
...
@@ -203,7 +205,7 @@ public:
RewriterVar
*
emitCreateTuple
(
const
llvm
::
ArrayRef
<
RewriterVar
*>
values
);
RewriterVar
*
emitDeref
(
InternedString
s
);
RewriterVar
*
emitExceptionMatches
(
RewriterVar
*
v
,
RewriterVar
*
cls
);
RewriterVar
*
emitGetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
);
RewriterVar
*
emitGetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
,
AST_expr
*
node
);
RewriterVar
*
emitGetBlockLocal
(
InternedString
s
);
RewriterVar
*
emitGetBoxedLocal
(
BoxedString
*
s
);
RewriterVar
*
emitGetBoxedLocals
();
...
...
@@ -217,8 +219,8 @@ public:
RewriterVar
*
emitNonzero
(
RewriterVar
*
v
);
RewriterVar
*
emitNotNonzero
(
RewriterVar
*
v
);
RewriterVar
*
emitRepr
(
RewriterVar
*
v
);
RewriterVar
*
emitRuntimeCall
(
RewriterVar
*
obj
,
ArgPassSpec
argspec
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
RewriterVar
*
emitRuntimeCall
(
AST_expr
*
node
,
RewriterVar
*
obj
,
ArgPassSpec
argspec
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
RewriterVar
*
emitUnaryop
(
RewriterVar
*
v
,
int
op_type
);
RewriterVar
*
emitUnpackIntoArray
(
RewriterVar
*
v
,
uint64_t
num
);
RewriterVar
*
emitYield
(
RewriterVar
*
v
);
...
...
@@ -255,10 +257,11 @@ private:
#endif
RewriterVar
*
getInterp
();
RewriterVar
*
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
);
RewriterVar
*
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
,
TypeRecorder
*
type_recorder
=
NULL
);
static
Box
*
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
Box
*
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
TypeRecorder
*
type_recorder
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
Box
*
createDictHelper
(
uint64_t
num
,
Box
**
keys
,
Box
**
values
);
static
Box
*
createListHelper
(
uint64_t
num
,
Box
**
data
);
static
Box
*
createSetHelper
(
uint64_t
num
,
Box
**
data
);
...
...
@@ -267,7 +270,8 @@ private:
static
Box
*
hasnextHelper
(
Box
*
b
);
static
Box
*
nonzeroHelper
(
Box
*
b
);
static
Box
*
notHelper
(
Box
*
b
);
static
Box
*
runtimeCallHelper
(
Box
*
obj
,
ArgPassSpec
argspec
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
Box
*
runtimeCallHelper
(
Box
*
obj
,
ArgPassSpec
argspec
,
TypeRecorder
*
type_recorder
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
void
_emitJump
(
CFGBlock
*
b
,
RewriterVar
*
block_next
,
int
&
size_of_exit_to_interp
);
void
_emitOSRPoint
(
RewriterVar
*
result
,
RewriterVar
*
node_var
);
...
...
src/codegen/irgen/hooks.cpp
View file @
0c84c153
...
...
@@ -670,6 +670,7 @@ void CompiledFunction::speculationFailed() {
CLFunction
*
cl
=
this
->
clfunc
;
assert
(
cl
);
assert
(
this
!=
cl
->
always_use_version
);
bool
found
=
false
;
for
(
int
i
=
0
;
i
<
clfunc
->
versions
.
size
();
i
++
)
{
...
...
@@ -681,6 +682,17 @@ void CompiledFunction::speculationFailed() {
}
}
if
(
!
found
)
{
for
(
auto
it
=
clfunc
->
osr_versions
.
begin
();
it
!=
clfunc
->
osr_versions
.
end
();
++
it
)
{
if
(
it
->
second
==
this
)
{
clfunc
->
osr_versions
.
erase
(
it
);
this
->
dependent_callsites
.
invalidateAll
();
found
=
true
;
break
;
}
}
}
if
(
!
found
)
{
for
(
int
i
=
0
;
i
<
clfunc
->
versions
.
size
();
i
++
)
{
printf
(
"%p
\n
"
,
clfunc
->
versions
[
i
]);
...
...
src/codegen/irgen/irgenerator.cpp
View file @
0c84c153
...
...
@@ -493,7 +493,10 @@ private:
assert
(
ast
);
EffortLevel
effort
=
irstate
->
getEffortLevel
();
bool
record_types
=
effort
!=
EffortLevel
::
MAXIMAL
;
// This is the only place we create type recorders for the llvm tier;
// if we are ok with never doing that there's a bunch of code that could
// be removed.
bool
record_types
=
false
;
TypeRecorder
*
type_recorder
;
if
(
record_types
)
{
...
...
src/codegen/irgen/util.cpp
View file @
0c84c153
...
...
@@ -20,10 +20,12 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "codegen/codegen.h"
#include "codegen/patchpoints.h"
#include "core/common.h"
#include "runtime/types.h"
...
...
@@ -158,9 +160,14 @@ llvm::Constant* getConstantDouble(double val) {
class
PrettifyingMaterializer
:
public
llvm
::
ValueMaterializer
{
private:
llvm
::
Module
*
module
;
llvm
::
ValueToValueMapTy
&
VMap
;
llvm
::
RemapFlags
flags
;
llvm
::
ValueMapTypeRemapper
*
type_remapper
;
public:
PrettifyingMaterializer
(
llvm
::
Module
*
module
)
:
module
(
module
)
{}
PrettifyingMaterializer
(
llvm
::
Module
*
module
,
llvm
::
ValueToValueMapTy
&
VMap
,
llvm
::
RemapFlags
flags
,
llvm
::
ValueMapTypeRemapper
*
type_remapper
)
:
module
(
module
),
VMap
(
VMap
),
flags
(
flags
),
type_remapper
(
type_remapper
)
{}
virtual
llvm
::
Value
*
materializeValueFor
(
llvm
::
Value
*
v
)
{
if
(
llvm
::
ConstantExpr
*
ce
=
llvm
::
dyn_cast
<
llvm
::
ConstantExpr
>
(
v
))
{
...
...
@@ -183,6 +190,46 @@ public:
return
module
->
getOrInsertGlobal
(
name
,
pt
->
getElementType
());
}
}
if
(
llvm
::
IntrinsicInst
*
ii
=
llvm
::
dyn_cast
<
llvm
::
IntrinsicInst
>
(
v
))
{
if
(
ii
->
getIntrinsicID
()
==
llvm
::
Intrinsic
::
experimental_patchpoint_i64
||
ii
->
getIntrinsicID
()
==
llvm
::
Intrinsic
::
experimental_patchpoint_void
||
ii
->
getIntrinsicID
()
==
llvm
::
Intrinsic
::
experimental_patchpoint_double
)
{
int
pp_id
=
-
1
;
for
(
int
i
=
0
;
i
<
ii
->
getNumArgOperands
();
i
++
)
{
llvm
::
Value
*
op
=
ii
->
getArgOperand
(
i
);
if
(
i
!=
1
)
{
if
(
i
==
0
)
{
llvm
::
ConstantInt
*
l_pp_id
=
llvm
::
cast
<
llvm
::
ConstantInt
>
(
op
);
pp_id
=
l_pp_id
->
getSExtValue
();
}
ii
->
setArgOperand
(
i
,
llvm
::
MapValue
(
op
,
VMap
,
flags
,
type_remapper
,
this
));
continue
;
}
else
{
assert
(
pp_id
!=
-
1
);
void
*
addr
=
PatchpointInfo
::
getSlowpathAddr
(
pp_id
);
bool
lookup_success
=
true
;
std
::
string
name
;
if
(
addr
==
(
void
*
)
None
)
{
name
=
"None"
;
}
else
{
name
=
g
.
func_addr_registry
.
getFuncNameAtAddress
(
addr
,
true
,
&
lookup_success
);
}
if
(
!
lookup_success
)
{
llvm
::
Constant
*
int_val
=
llvm
::
ConstantInt
::
get
(
g
.
i64
,
reinterpret_cast
<
uintptr_t
>
(
addr
),
false
);
llvm
::
Constant
*
ptr_val
=
llvm
::
ConstantExpr
::
getIntToPtr
(
int_val
,
g
.
i8_ptr
);
ii
->
setArgOperand
(
i
,
ptr_val
);
continue
;
}
else
{
ii
->
setArgOperand
(
i
,
module
->
getOrInsertGlobal
(
name
,
g
.
i8_ptr
));
}
}
}
return
ii
;
}
}
return
v
;
}
};
...
...
@@ -194,12 +241,14 @@ void dumpPrettyIR(llvm::Function* f) {
llvm
::
Function
*
new_f
=
tmp_module
->
begin
();
llvm
::
ValueToValueMapTy
VMap
;
PrettifyingMaterializer
materializer
(
tmp_module
.
get
());
llvm
::
RemapFlags
flags
=
llvm
::
RF_None
;
llvm
::
ValueMapTypeRemapper
*
type_remapper
=
NULL
;
PrettifyingMaterializer
materializer
(
tmp_module
.
get
(),
VMap
,
flags
,
type_remapper
);
for
(
llvm
::
Function
::
iterator
I
=
new_f
->
begin
(),
E
=
new_f
->
end
();
I
!=
E
;
++
I
)
{
VMap
[
I
]
=
I
;
}
for
(
llvm
::
inst_iterator
it
=
inst_begin
(
new_f
),
end
=
inst_end
(
new_f
);
it
!=
end
;
++
it
)
{
llvm
::
RemapInstruction
(
&*
it
,
VMap
,
llvm
::
RF_None
,
NULL
,
&
materializer
);
llvm
::
RemapInstruction
(
&*
it
,
VMap
,
flags
,
type_remapper
,
&
materializer
);
}
tmp_module
->
begin
()
->
dump
();
// tmp_module->dump();
...
...
src/codegen/patchpoints.cpp
View file @
0c84c153
...
...
@@ -162,7 +162,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
PatchpointInfo
*
pp
=
new_patchpoints
[
r
->
id
].
first
;
assert
(
pp
);
void
*
dst_func
=
new_patchpoints
[
r
->
id
].
second
;
void
*
slowpath_func
=
PatchpointInfo
::
getSlowpathAddr
(
r
->
id
)
;
if
(
VERBOSITY
()
>=
2
)
{
printf
(
"Processing pp %ld; [%d, %d)
\n
"
,
reinterpret_cast
<
int64_t
>
(
pp
),
r
->
offset
,
r
->
offset
+
pp
->
patchpointSize
());
...
...
@@ -179,10 +179,7 @@ void processStackmap(CompiledFunction* cf, StackMap* stackmap) {
uint8_t
*
end_addr
=
start_addr
+
pp
->
patchpointSize
();
if
(
ENABLE_JIT_OBJECT_CACHE
)
setSlowpathFunc
(
start_addr
,
dst_func
);
// TODO shouldn't have to do it this way
void
*
slowpath_func
=
extractSlowpathFunc
(
start_addr
);
setSlowpathFunc
(
start_addr
,
slowpath_func
);
//*start_addr = 0xcc;
// start_addr++;
...
...
@@ -287,6 +284,11 @@ PatchpointInfo* PatchpointInfo::create(CompiledFunction* parent_cf, const ICSetu
return
r
;
}
void
*
PatchpointInfo
::
getSlowpathAddr
(
unsigned
int
pp_id
)
{
RELEASE_ASSERT
(
pp_id
<
new_patchpoints
.
size
(),
""
);
return
new_patchpoints
[
pp_id
].
second
;
}
ICSetupInfo
*
createGenericIC
(
TypeRecorder
*
type_recorder
,
bool
has_return_value
,
int
size
)
{
return
ICSetupInfo
::
initialize
(
has_return_value
,
1
,
size
,
ICSetupInfo
::
Generic
,
type_recorder
);
}
...
...
src/codegen/patchpoints.h
View file @
0c84c153
...
...
@@ -97,6 +97,7 @@ public:
static
PatchpointInfo
*
create
(
CompiledFunction
*
parent_cf
,
const
ICSetupInfo
*
icinfo
,
int
num_ic_stackmap_args
,
void
*
func_addr
);
static
void
*
getSlowpathAddr
(
unsigned
int
pp_id
);
};
class
ICSetupInfo
{
...
...
src/codegen/runtime_hooks.cpp
View file @
0c84c153
...
...
@@ -170,7 +170,7 @@ void initGlobalFuncs(GlobalState& g) {
g
.
funcs
.
malloc
=
addFunc
((
void
*
)
malloc
,
g
.
i8_ptr
,
g
.
i64
);
g
.
funcs
.
free
=
addFunc
((
void
*
)
free
,
g
.
void_
,
g
.
i8_ptr
);
g
.
funcs
.
allowGLReadPreemption
=
addFunc
((
void
*
)
threading
::
allowGLReadPreemption
,
g
.
void_
);
g
.
funcs
.
allowGLReadPreemption
=
getFunc
((
void
*
)
threading
::
allowGLReadPreemption
,
"allowGLReadPreemption"
);
GET
(
softspace
);
...
...
src/codegen/type_recording.h
View file @
0c84c153
...
...
@@ -30,6 +30,7 @@ class TypeRecorder;
// (I think most compilers pass "this" as the argument 0 and then shift the rest of the
// arguments, but I'd rather not depend on that behavior since I can't find where that's
// specified.)
// The return value of this function is 'obj' for ease of use.
extern
"C"
Box
*
recordType
(
TypeRecorder
*
recorder
,
Box
*
obj
);
class
TypeRecorder
{
private:
...
...
src/codegen/unwinding.cpp
View file @
0c84c153
...
...
@@ -426,9 +426,11 @@ static bool inGeneratorEntry(unw_word_t ip) {
return
((
unw_word_t
)
generatorEntry
<
ip
&&
ip
<=
generator_entry_end
);
}
static
bool
inDeopt
(
unw_word_t
ip
)
{
static
unw_word_t
deopt_end
=
getFunctionEnd
((
unw_word_t
)
deopt
);
return
((
unw_word_t
)
deopt
<
ip
&&
ip
<=
deopt_end
);
static
bool
isDeopt
(
unw_word_t
ip
)
{
// Check for astInterpretDeopt() instead of deopt(), since deopt() will do some
// unwinding and we don't want it to skip things.
static
unw_word_t
deopt_end
=
getFunctionEnd
((
unw_word_t
)
astInterpretDeopt
);
return
((
unw_word_t
)
astInterpretDeopt
<
ip
&&
ip
<=
deopt_end
);
}
...
...
@@ -626,7 +628,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
unw_word_t
bp
=
get_cursor_bp
(
cursor
);
PythonFrameIteratorImpl
frame_iter
;
if
(
i
n
Deopt
(
ip
))
{
if
(
i
s
Deopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
...
...
@@ -667,7 +669,7 @@ template <typename Func> void unwindPythonStack(Func func) {
bool
stop_unwinding
=
false
;
PythonFrameIteratorImpl
frame_iter
;
if
(
i
n
Deopt
(
ip
))
{
if
(
i
s
Deopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
...
...
src/core/threading.h
View file @
0c84c153
...
...
@@ -89,7 +89,8 @@ void _allowGLReadPreemption();
// only be accessed by the thread that holds the gil:
extern
int
gil_check_count
;
extern
std
::
atomic
<
int
>
threads_waiting_on_gil
;
inline
void
allowGLReadPreemption
()
{
extern
"C"
inline
void
allowGLReadPreemption
()
__attribute__
((
visibility
(
"default"
)));
extern
"C"
inline
void
allowGLReadPreemption
()
{
#if ENABLE_SAMPLING_PROFILER
if
(
unlikely
(
sigprof_pending
))
{
// Output multiple stacktraces if we received multiple signals
...
...
@@ -167,7 +168,8 @@ inline void promoteGL() {
}
inline
void
demoteGL
()
{
}
inline
void
allowGLReadPreemption
()
{
extern
"C"
inline
void
allowGLReadPreemption
()
__attribute__
((
visibility
(
"default"
)));
extern
"C"
inline
void
allowGLReadPreemption
()
{
}
#endif
...
...
src/core/types.h
View file @
0c84c153
...
...
@@ -347,8 +347,9 @@ public:
compiled
->
clfunc
=
this
;
if
(
compiled
->
entry_descriptor
==
NULL
)
{
if
(
versions
.
size
()
==
0
&&
compiled
->
effort
==
EffortLevel
::
MAXIMAL
&&
compiled
->
spec
->
accepts_all_inputs
&&
compiled
->
spec
->
boxed_return_value
)
bool
could_have_speculations
=
(
source
.
get
()
!=
NULL
);
if
(
!
could_have_speculations
&&
versions
.
size
()
==
0
&&
compiled
->
effort
==
EffortLevel
::
MAXIMAL
&&
compiled
->
spec
->
accepts_all_inputs
&&
compiled
->
spec
->
boxed_return_value
)
always_use_version
=
compiled
;
assert
(
compiled
->
spec
->
arg_types
.
size
()
==
paramspec
.
totalReceived
());
...
...
src/runtime/objmodel.cpp
View file @
0c84c153
...
...
@@ -166,17 +166,11 @@ bool PyLt::operator()(Box* lhs, Box* rhs) const {
}
extern
"C"
Box
*
deopt
(
AST_expr
*
expr
,
Box
*
value
)
{
STAT_TIMER
(
t0
,
"us_timer_deopt"
,
10
);
static
StatCounter
num_deopt
(
"num_deopt"
);
num_deopt
.
log
();
printf
(
"Deopt!
\n
"
);
print_ast
(
expr
);
printf
(
"
\n
"
);
dump
(
value
);
printf
(
"
\n
"
);
RELEASE_ASSERT
(
0
,
"deopt is currently broken..."
);
auto
deopt_state
=
getDeoptState
();
// Should we only do this selectively?
...
...
@@ -189,7 +183,7 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) {
deopt_state
.
frame_state
.
frame_info
->
exc
.
value
=
NULL
;
}
return
astInterpret
From
(
deopt_state
.
cf
->
clfunc
,
expr
,
deopt_state
.
current_stmt
,
value
,
deopt_state
.
frame_state
);
return
astInterpret
Deopt
(
deopt_state
.
cf
->
clfunc
,
expr
,
deopt_state
.
current_stmt
,
value
,
deopt_state
.
frame_state
);
}
extern
"C"
bool
softspace
(
Box
*
b
,
bool
newval
)
{
...
...
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