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
b7873045
Commit
b7873045
authored
Jul 13, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #693 from undingen/bjit_pp
baseline jit: directly emit patchpoints instead of using runtime ICs
parents
03aedad4
a40ae31a
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
213 additions
and
253 deletions
+213
-253
src/asm_writing/assembler.cpp
src/asm_writing/assembler.cpp
+10
-0
src/asm_writing/assembler.h
src/asm_writing/assembler.h
+1
-0
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+22
-12
src/asm_writing/rewriter.h
src/asm_writing/rewriter.h
+4
-1
src/codegen/baseline_jit.cpp
src/codegen/baseline_jit.cpp
+152
-140
src/codegen/baseline_jit.h
src/codegen/baseline_jit.h
+22
-28
src/runtime/ics.h
src/runtime/ics.h
+0
-72
src/runtime/types.cpp
src/runtime/types.cpp
+2
-0
No files found.
src/asm_writing/assembler.cpp
View file @
b7873045
...
...
@@ -1034,6 +1034,16 @@ void Assembler::emitAnnotation(int num) {
nop
();
}
void
Assembler
::
skipBytes
(
int
num
)
{
if
(
addr
+
num
>=
end_addr
)
{
addr
=
end_addr
;
failed
=
true
;
return
;
}
addr
+=
num
;
}
ForwardJump
::
ForwardJump
(
Assembler
&
assembler
,
ConditionCode
condition
)
:
assembler
(
assembler
),
condition
(
condition
),
jmp_inst
(
assembler
.
curInstPointer
())
{
assembler
.
jmp_cond
(
JumpDestination
::
fromStart
(
assembler
.
bytesWritten
()
+
max_jump_size
),
condition
);
...
...
src/asm_writing/assembler.h
View file @
b7873045
...
...
@@ -193,6 +193,7 @@ public:
void
fillWithNops
();
void
fillWithNopsExcept
(
int
bytes
);
void
emitAnnotation
(
int
num
);
void
skipBytes
(
int
num
);
uint8_t
*
startAddr
()
const
{
return
start_addr
;
}
int
bytesLeft
()
const
{
return
end_addr
-
addr
;
}
...
...
src/asm_writing/rewriter.cpp
View file @
b7873045
...
...
@@ -792,10 +792,8 @@ RewriterVar* Rewriter::call(bool has_side_effects, void* func_addr, const Rewrit
return
result
;
}
void
Rewriter
::
_
call
(
RewriterVar
*
result
,
bool
has_side_effects
,
void
*
func_addr
,
const
RewriterVar
::
SmallVector
&
args
,
void
Rewriter
::
_
setupCall
(
RewriterVar
*
result
,
bool
has_side_effects
,
const
RewriterVar
::
SmallVector
&
args
,
const
RewriterVar
::
SmallVector
&
args_xmm
)
{
assembler
->
comment
(
"_call"
);
if
(
has_side_effects
)
assert
(
done_guarding
);
...
...
@@ -828,9 +826,6 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr
}
}
// RewriterVarUsage scratch = createNewVar(Location::any());
assembler
::
Register
r
=
allocReg
(
assembler
::
R11
);
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
{
Location
l
(
Location
::
forArg
(
i
));
RewriterVar
*
var
=
args
[
i
];
...
...
@@ -950,6 +945,19 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr
assert
(
!
l
.
isClobberedByCall
());
}
#endif
}
void
Rewriter
::
_call
(
RewriterVar
*
result
,
bool
has_side_effects
,
void
*
func_addr
,
const
RewriterVar
::
SmallVector
&
args
,
const
RewriterVar
::
SmallVector
&
args_xmm
)
{
assembler
->
comment
(
"_call"
);
// RewriterVarUsage scratch = createNewVar(Location::any());
assembler
::
Register
r
=
allocReg
(
assembler
::
R11
);
_setupCall
(
result
,
has_side_effects
,
args
,
args_xmm
);
// make sure setupCall doesn't use R11
assert
(
vars_by_location
.
count
(
assembler
::
R11
)
==
0
);
uint64_t
asm_address
=
(
uint64_t
)
assembler
->
curInstPointer
()
+
5
;
uint64_t
real_asm_address
=
asm_address
+
(
uint64_t
)
rewrite
->
getSlotStart
()
-
(
uint64_t
)
assembler
->
startAddr
();
...
...
@@ -962,10 +970,12 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr
assert
(
assembler
->
hasFailed
()
||
asm_address
==
(
uint64_t
)
assembler
->
curInstPointer
());
}
if
(
!
failed
)
{
assert
(
vars_by_location
.
count
(
assembler
::
RAX
)
==
0
);
result
->
initializeInReg
(
assembler
::
RAX
);
assertConsistent
();
}
result
->
releaseIfNoUses
();
}
...
...
@@ -1737,10 +1747,10 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const s
// the entire scratch space.
bool
VALIDATE_SCRATCH_SPACE
=
false
;
if
(
VALIDATE_SCRATCH_SPACE
)
{
int
scratch_size
=
rewrite
->
getScratchSize
();
int
scratch_size
=
this
->
rewrite
->
getScratchSize
();
for
(
int
i
=
0
;
i
<
scratch_size
;
i
+=
8
)
{
assembler
->
movq
(
assembler
::
Immediate
(
0x12345678UL
),
assembler
::
Indirect
(
assembler
::
RSP
,
i
+
rewrite
->
getScratchRspOffset
()));
assembler
::
Indirect
(
assembler
::
RSP
,
i
+
this
->
rewrite
->
getScratchRspOffset
()));
}
}
}
...
...
src/asm_writing/rewriter.h
View file @
b7873045
...
...
@@ -19,6 +19,7 @@
#include <memory>
#include <tuple>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
...
...
@@ -351,7 +352,7 @@ protected:
Rewriter
(
std
::
unique_ptr
<
ICSlotRewrite
>
rewrite
,
int
num_args
,
const
std
::
vector
<
int
>&
live_outs
);
llvm
::
SmallVector
<
RewriterAction
,
32
>
actions
;
void
addAction
(
std
::
function
<
void
()
>
action
,
std
::
vector
<
RewriterVar
*>
const
&
vars
,
ActionType
type
)
{
void
addAction
(
std
::
function
<
void
()
>
action
,
llvm
::
ArrayRef
<
RewriterVar
*>
vars
,
ActionType
type
)
{
assertPhaseCollecting
();
for
(
RewriterVar
*
var
:
vars
)
{
assert
(
var
!=
NULL
);
...
...
@@ -415,6 +416,8 @@ protected:
void
_trap
();
void
_loadConst
(
RewriterVar
*
result
,
int64_t
val
);
void
_setupCall
(
RewriterVar
*
result
,
bool
has_side_effects
,
const
RewriterVar
::
SmallVector
&
args
,
const
RewriterVar
::
SmallVector
&
args_xmm
);
void
_call
(
RewriterVar
*
result
,
bool
has_side_effects
,
void
*
func_addr
,
const
RewriterVar
::
SmallVector
&
args
,
const
RewriterVar
::
SmallVector
&
args_xmm
);
void
_add
(
RewriterVar
*
result
,
RewriterVar
*
a
,
int64_t
b
,
Location
dest
);
...
...
src/codegen/baseline_jit.cpp
View file @
b7873045
...
...
@@ -29,6 +29,7 @@ namespace pyston {
static
llvm
::
DenseSet
<
CFGBlock
*>
blocks_aborted
;
static
llvm
::
DenseMap
<
CFGBlock
*
,
std
::
vector
<
void
*>>
block_patch_locations
;
JitCodeBlock
::
JitCodeBlock
(
llvm
::
StringRef
name
)
:
frame_manager
(
false
/* don't omit frame pointers */
),
code
(
new
uint8_t
[
code_size
]),
...
...
@@ -49,6 +50,11 @@ JitCodeBlock::JitCodeBlock(llvm::StringRef name)
// subtract scratch size + 8bytes to align stack after the push.
a
.
sub
(
assembler
::
Immediate
(
scratch_size
+
8
),
assembler
::
RSP
);
a
.
push
(
assembler
::
RDI
);
// push interpreter pointer
// subtract space in order to be able to pass additional args on the stack without having to adjusting the SP when
// calling functions with more than 6 args.
a
.
sub
(
assembler
::
Immediate
(
num_stack_args
*
sizeof
(
void
*
)),
assembler
::
RSP
);
a
.
jmp
(
assembler
::
Indirect
(
assembler
::
RSI
,
offsetof
(
CFGBlock
,
code
)));
// jump to block
entry_offset
=
a
.
bytesWritten
();
...
...
@@ -65,7 +71,8 @@ std::unique_ptr<JitFragmentWriter> JitCodeBlock::newFragment(CFGBlock* block, in
is_currently_writing
=
true
;
StackInfo
stack_info
(
scratch_size
,
16
);
int
scratch_offset
=
num_stack_args
*
8
+
8
/* ASTInterpreter* */
+
8
/* alignment */
;
StackInfo
stack_info
(
scratch_size
,
scratch_offset
);
std
::
unordered_set
<
int
>
live_outs
;
void
*
fragment_start
=
a
.
curInstPointer
()
-
patch_jump_offset
;
...
...
@@ -106,7 +113,7 @@ JitFragmentWriter::JitFragmentWriter(CFGBlock* block, std::unique_ptr<ICInfo> ic
interp
(
0
),
ic_info
(
std
::
move
(
ic_info
))
{
interp
=
createNewVar
();
addLocationToVar
(
interp
,
Location
(
Location
::
Stack
,
0
));
addLocationToVar
(
interp
,
Location
(
Location
::
Stack
,
JitCodeBlock
::
interpreter_ptr_offset
));
interp
->
setAttr
(
ASTInterpreterJitInterface
::
getCurrentBlockOffset
(),
imm
(
block
));
}
...
...
@@ -119,24 +126,41 @@ RewriterVar* JitFragmentWriter::imm(void* val) {
}
RewriterVar
*
JitFragmentWriter
::
emitAugbinop
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
augbinopICHelper
,
imm
(
new
AugBinopIC
),
lhs
,
rhs
,
imm
(
op_type
));
#else
return
call
(
false
,
(
void
*
)
augbinop
,
lhs
,
rhs
,
imm
(
op_type
));
#endif
return
emitPPCall
((
void
*
)
augbinop
,
{
lhs
,
rhs
,
imm
(
op_type
)
},
2
,
320
);
}
RewriterVar
*
JitFragmentWriter
::
emitBinop
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
binopICHelper
,
imm
(
new
BinopIC
),
lhs
,
rhs
,
imm
(
op_type
));
#else
return
call
(
false
,
(
void
*
)
binop
,
lhs
,
rhs
,
imm
(
op_type
));
#endif
return
emitPPCall
((
void
*
)
binop
,
{
lhs
,
rhs
,
imm
(
op_type
)
},
2
,
240
);
}
RewriterVar
*
JitFragmentWriter
::
emitCallattr
(
RewriterVar
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
attr_var
=
imm
(
attr
);
RewriterVar
*
flags_var
=
imm
(
flags
.
asInt
());
RewriterVar
::
SmallVector
call_args
;
call_args
.
push_back
(
obj
);
call_args
.
push_back
(
attr_var
);
call_args
.
push_back
(
flags_var
);
call_args
.
push_back
(
args
.
size
()
>
0
?
args
[
0
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
1
?
args
[
1
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
2
?
args
[
2
]
:
imm
(
0ul
));
if
(
args
.
size
()
>
3
)
{
RewriterVar
*
scratch
=
allocate
(
args
.
size
()
-
3
);
for
(
int
i
=
0
;
i
<
args
.
size
()
-
3
;
++
i
)
scratch
->
setAttr
(
i
*
sizeof
(
void
*
),
args
[
i
+
3
]);
call_args
.
push_back
(
scratch
);
}
else
if
(
keyword_names
)
{
call_args
.
push_back
(
imm
(
0ul
));
}
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
return
emitPPCall
((
void
*
)
callattr
,
call_args
,
2
,
640
);
#else
// We could make this faster but for now: keep it simple, stupid...
RewriterVar
*
attr_var
=
imm
(
attr
);
RewriterVar
*
flags_var
=
imm
(
flags
.
asInt
());
...
...
@@ -148,41 +172,23 @@ RewriterVar* JitFragmentWriter::emitCallattr(RewriterVar* obj, BoxedString* attr
else
RELEASE_ASSERT
(
!
keyword_names_var
,
"0 args but keyword names are set"
);
bool
use_ic
=
false
;
RewriterVar
::
SmallVector
call_args
;
call_args
.
push_back
(
obj
);
call_args
.
push_back
(
attr_var
);
call_args
.
push_back
(
flags_var
);
#if ENABLE_BASELINEJIT_ICS
if
(
!
keyword_names_var
&&
flags
.
argspec
.
totalPassed
()
<
4
)
{
// looks like runtime ICs with 7 or more args don't work right now..
use_ic
=
true
;
call_args
.
push_back
(
imm
(
new
CallattrIC
));
}
#endif
if
(
args_array
)
call_args
.
push_back
(
args_array
);
if
(
keyword_names_var
)
call_args
.
push_back
(
keyword_names_var
);
#if ENABLE_BASELINEJIT_ICS
if
(
use_ic
)
return
call
(
false
,
(
void
*
)
callattrHelperIC
,
call_args
);
#endif
return
call
(
false
,
(
void
*
)
callattrHelper
,
call_args
);
#endif
}
RewriterVar
*
JitFragmentWriter
::
emitCompare
(
RewriterVar
*
lhs
,
RewriterVar
*
rhs
,
int
op_type
)
{
// TODO: can directly emit the assembly for Is/IsNot
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
compareICHelper
,
imm
(
new
CompareIC
),
lhs
,
rhs
,
imm
(
op_type
));
#else
return
call
(
false
,
(
void
*
)
compare
,
lhs
,
rhs
,
imm
(
op_type
));
#endif
// TODO: can directly emit the assembly for Is/IsNot
return
emitPPCall
((
void
*
)
compare
,
{
lhs
,
rhs
,
imm
(
op_type
)
},
2
,
240
);
}
RewriterVar
*
JitFragmentWriter
::
emitCreateDict
(
const
llvm
::
ArrayRef
<
RewriterVar
*>
keys
,
...
...
@@ -242,11 +248,7 @@ RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar
}
RewriterVar
*
JitFragmentWriter
::
emitGetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
getAttrICHelper
,
imm
(
new
GetAttrIC
),
obj
,
imm
(
s
));
#else
return
call
(
false
,
(
void
*
)
getattr
,
obj
,
imm
(
s
));
#endif
return
emitPPCall
((
void
*
)
getattr
,
{
obj
,
imm
(
s
)
},
2
,
512
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetBlockLocal
(
InternedString
s
)
{
...
...
@@ -265,23 +267,15 @@ RewriterVar* JitFragmentWriter::emitGetBoxedLocals() {
}
RewriterVar
*
JitFragmentWriter
::
emitGetClsAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
)
{
return
call
(
false
,
(
void
*
)
getclsattr
,
obj
,
imm
(
s
)
);
return
emitPPCall
((
void
*
)
getclsattr
,
{
obj
,
imm
(
s
)
},
2
,
512
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetGlobal
(
Box
*
global
,
BoxedString
*
s
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
getGlobalICHelper
,
imm
(
new
GetGlobalIC
),
imm
(
global
),
imm
(
s
));
#else
return
call
(
false
,
(
void
*
)
getGlobal
,
imm
(
global
),
imm
(
s
));
#endif
return
emitPPCall
((
void
*
)
getGlobal
,
{
imm
(
global
),
imm
(
s
)
},
2
,
512
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetItem
(
RewriterVar
*
value
,
RewriterVar
*
slice
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
getitemICHelper
,
imm
(
new
GetItemIC
),
value
,
slice
);
#else
return
call
(
false
,
(
void
*
)
getitem
,
value
,
slice
);
#endif
return
emitPPCall
((
void
*
)
getitem
,
{
value
,
slice
},
2
,
512
);
}
RewriterVar
*
JitFragmentWriter
::
emitGetLocal
(
InternedString
s
)
{
...
...
@@ -320,7 +314,27 @@ RewriterVar* JitFragmentWriter::emitRepr(RewriterVar* v) {
RewriterVar
*
JitFragmentWriter
::
emitRuntimeCall
(
RewriterVar
*
obj
,
ArgPassSpec
argspec
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
// We could make this faster but for now: keep it simple, stupid..
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
argspec_var
=
imm
(
argspec
.
asInt
());
RewriterVar
::
SmallVector
call_args
;
call_args
.
push_back
(
obj
);
call_args
.
push_back
(
argspec_var
);
call_args
.
push_back
(
args
.
size
()
>
0
?
args
[
0
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
1
?
args
[
1
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
2
?
args
[
2
]
:
imm
(
0ul
));
if
(
args
.
size
()
>
3
)
{
RewriterVar
*
scratch
=
allocate
(
args
.
size
()
-
3
);
for
(
int
i
=
0
;
i
<
args
.
size
()
-
3
;
++
i
)
scratch
->
setAttr
(
i
*
sizeof
(
void
*
),
args
[
i
+
3
]);
call_args
.
push_back
(
scratch
);
}
else
call_args
.
push_back
(
imm
(
0ul
));
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
return
emitPPCall
((
void
*
)
runtimeCall
,
call_args
,
2
,
640
);
#else
RewriterVar
*
argspec_var
=
imm
(
argspec
.
asInt
());
RewriterVar
*
keyword_names_var
=
keyword_names
?
imm
(
keyword_names
)
:
nullptr
;
...
...
@@ -330,38 +344,20 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(RewriterVar* obj, ArgPassSpec ar
}
else
RELEASE_ASSERT
(
!
keyword_names_var
,
"0 args but keyword names are set"
);
bool
use_ic
=
false
;
RewriterVar
::
SmallVector
call_args
;
call_args
.
push_back
(
obj
);
call_args
.
push_back
(
argspec_var
);
#if ENABLE_BASELINEJIT_ICS
if
(
!
keyword_names
)
{
// looks like runtime ICs with 7 or more args don't work right now..
use_ic
=
true
;
call_args
.
push_back
(
imm
(
new
RuntimeCallIC
));
}
#endif
if
(
args_array
)
call_args
.
push_back
(
args_array
);
if
(
keyword_names_var
)
call_args
.
push_back
(
keyword_names_var
);
#if ENABLE_BASELINEJIT_ICS
if
(
use_ic
)
return
call
(
false
,
(
void
*
)
runtimeCallHelperIC
,
call_args
);
#endif
return
call
(
false
,
(
void
*
)
runtimeCallHelper
,
call_args
);
#endif
}
RewriterVar
*
JitFragmentWriter
::
emitUnaryop
(
RewriterVar
*
v
,
int
op_type
)
{
#if ENABLE_BASELINEJIT_ICS
return
call
(
false
,
(
void
*
)
unaryopICHelper
,
imm
(
new
UnaryopIC
),
v
,
imm
(
op_type
));
#else
return
call
(
false
,
(
void
*
)
unaryop
,
v
,
imm
(
op_type
));
#endif
return
emitPPCall
((
void
*
)
unaryop
,
{
v
,
imm
(
op_type
)
},
2
,
160
);
}
RewriterVar
*
JitFragmentWriter
::
emitUnpackIntoArray
(
RewriterVar
*
v
,
uint64_t
num
)
{
...
...
@@ -414,11 +410,7 @@ void JitFragmentWriter::emitReturn(RewriterVar* v) {
}
void
JitFragmentWriter
::
emitSetAttr
(
RewriterVar
*
obj
,
BoxedString
*
s
,
RewriterVar
*
attr
)
{
#if ENABLE_BASELINEJIT_ICS
call
(
false
,
(
void
*
)
setAttrICHelper
,
imm
(
new
SetAttrIC
),
obj
,
imm
(
s
),
attr
);
#else
call
(
false
,
(
void
*
)
setattr
,
obj
,
imm
(
s
),
attr
);
#endif
emitPPCall
((
void
*
)
setattr
,
{
obj
,
imm
(
s
),
attr
},
2
,
512
);
}
void
JitFragmentWriter
::
emitSetBlockLocal
(
InternedString
s
,
RewriterVar
*
v
)
{
...
...
@@ -434,19 +426,11 @@ void JitFragmentWriter::emitSetExcInfo(RewriterVar* type, RewriterVar* value, Re
}
void
JitFragmentWriter
::
emitSetGlobal
(
Box
*
global
,
BoxedString
*
s
,
RewriterVar
*
v
)
{
#if ENABLE_BASELINEJIT_ICS
call
(
false
,
(
void
*
)
setGlobalICHelper
,
imm
(
new
SetGlobalIC
),
imm
(
global
),
imm
(
s
),
v
);
#else
call
(
false
,
(
void
*
)
setGlobal
,
imm
(
global
),
imm
(
s
),
v
);
#endif
emitPPCall
((
void
*
)
setGlobal
,
{
imm
(
global
),
imm
(
s
),
v
},
2
,
512
);
}
void
JitFragmentWriter
::
emitSetItem
(
RewriterVar
*
target
,
RewriterVar
*
slice
,
RewriterVar
*
value
)
{
#if ENABLE_BASELINEJIT_ICS
call
(
false
,
(
void
*
)
setitemICHelper
,
imm
(
new
SetItemIC
),
target
,
slice
,
value
);
#else
call
(
false
,
(
void
*
)
setitem
,
target
,
slice
,
value
);
#endif
emitPPCall
((
void
*
)
setitem
,
{
target
,
slice
,
value
},
2
,
512
);
}
void
JitFragmentWriter
::
emitSetItemName
(
BoxedString
*
s
,
RewriterVar
*
v
)
{
...
...
@@ -524,6 +508,22 @@ int JitFragmentWriter::finishCompilation() {
block_patch_locations
[
side_exit_patch_location
.
first
].
push_back
(
patch_location
);
}
for
(
auto
&&
pp_info
:
pp_infos
)
{
SpillMap
_spill_map
;
uint8_t
*
start_addr
=
pp_info
.
start_addr
;
uint8_t
*
end_addr
=
pp_info
.
end_addr
;
std
::
pair
<
uint8_t
*
,
uint8_t
*>
p
=
initializePatchpoint3
(
pp_info
.
func_addr
,
start_addr
,
end_addr
,
0
/* scratch_offset */
,
0
/* scratch_size */
,
std
::
unordered_set
<
int
>
(),
_spill_map
);
uint8_t
*
slowpath_start
=
p
.
first
;
uint8_t
*
slowpath_rtn_addr
=
p
.
second
;
std
::
unique_ptr
<
ICInfo
>
pp
=
registerCompiledPatchpoint
(
start_addr
,
slowpath_start
,
end_addr
,
slowpath_rtn_addr
,
pp_info
.
ic
.
get
(),
pp_info
.
stack_info
,
std
::
unordered_set
<
int
>
());
pp
.
release
();
}
void
*
next_fragment_start
=
(
uint8_t
*
)
block
->
code
+
assembler
->
bytesWritten
();
code_block
.
fragmentFinished
(
assembler
->
bytesWritten
(),
num_bytes_overlapping
,
next_fragment_start
);
return
num_bytes_exit
;
...
...
@@ -569,23 +569,20 @@ RewriterVar* JitFragmentWriter::getInterp() {
return
interp
;
}
Box
*
JitFragmentWriter
::
augbinopICHelper
(
AugBinopIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
)
{
return
ic
->
call
(
lhs
,
rhs
,
op
);
}
Box
*
JitFragmentWriter
::
binopICHelper
(
BinopIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
)
{
return
ic
->
call
(
lhs
,
rhs
,
op
);
}
RewriterVar
*
JitFragmentWriter
::
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
)
{
RewriterVar
::
SmallVector
args_vec
(
args
.
begin
(),
args
.
end
());
#if ENABLE_BASELINEJIT_ICS
Box
*
JitFragmentWriter
::
callattrHelperIC
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
CallattrIC
*
ic
,
Box
**
args
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
flags
.
argspec
.
totalPassed
());
return
ic
->
call
(
obj
,
attr
,
flags
,
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
NULL
,
NULL
);
}
RewriterVar
*
result
=
createNewVar
();
addAction
([
=
]()
{
this
->
_emitPPCall
(
result
,
func_addr
,
args_vec
,
num_slots
,
slot_size
);
},
args
,
ActionType
::
NORMAL
);
return
result
;
#else
assert
(
args_vec
.
size
()
<
7
);
return
call
(
false
,
func_addr
,
args_vec
);
#endif
}
Box
*
JitFragmentWriter
::
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
flags
.
argspec
.
totalPassed
());
...
...
@@ -595,10 +592,6 @@ Box* JitFragmentWriter::callattrHelper(Box* obj, BoxedString* attr, CallattrFlag
return
r
;
}
Box
*
JitFragmentWriter
::
compareICHelper
(
CompareIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
)
{
return
ic
->
call
(
lhs
,
rhs
,
op
);
}
Box
*
JitFragmentWriter
::
createDictHelper
(
uint64_t
num
,
Box
**
keys
,
Box
**
values
)
{
BoxedDict
*
dict
=
(
BoxedDict
*
)
createDict
();
for
(
uint64_t
i
=
0
;
i
<
num
;
++
i
)
{
...
...
@@ -634,18 +627,6 @@ Box* JitFragmentWriter::exceptionMatchesHelper(Box* obj, Box* cls) {
return
boxBool
(
exceptionMatches
(
obj
,
cls
));
}
Box
*
JitFragmentWriter
::
getAttrICHelper
(
GetAttrIC
*
ic
,
Box
*
o
,
BoxedString
*
attr
)
{
return
ic
->
call
(
o
,
attr
);
}
Box
*
JitFragmentWriter
::
getGlobalICHelper
(
GetGlobalIC
*
ic
,
Box
*
o
,
BoxedString
*
s
)
{
return
ic
->
call
(
o
,
s
);
}
Box
*
JitFragmentWriter
::
getitemICHelper
(
GetItemIC
*
ic
,
Box
*
o
,
Box
*
attr
)
{
return
ic
->
call
(
o
,
attr
);
}
Box
*
JitFragmentWriter
::
hasnextHelper
(
Box
*
b
)
{
return
boxBool
(
pyston
::
hasnext
(
b
));
}
...
...
@@ -658,13 +639,6 @@ Box* JitFragmentWriter::notHelper(Box* b) {
return
boxBool
(
!
b
->
nonzeroIC
());
}
#if ENABLE_BASELINEJIT_ICS
Box
*
JitFragmentWriter
::
runtimeCallHelperIC
(
Box
*
obj
,
ArgPassSpec
argspec
,
RuntimeCallIC
*
ic
,
Box
**
args
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
argspec
.
totalPassed
());
return
ic
->
call
(
obj
,
argspec
,
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
std
::
get
<
3
>
(
arg_tuple
));
}
#endif
Box
*
JitFragmentWriter
::
runtimeCallHelper
(
Box
*
obj
,
ArgPassSpec
argspec
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
auto
arg_tuple
=
getTupleFromArgsArray
(
&
args
[
0
],
argspec
.
totalPassed
());
...
...
@@ -672,22 +646,6 @@ Box* JitFragmentWriter::runtimeCallHelper(Box* obj, ArgPassSpec argspec, Box** a
std
::
get
<
3
>
(
arg_tuple
),
keyword_names
);
}
Box
*
JitFragmentWriter
::
setAttrICHelper
(
SetAttrIC
*
ic
,
Box
*
o
,
BoxedString
*
attr
,
Box
*
value
)
{
return
ic
->
call
(
o
,
attr
,
value
);
}
Box
*
JitFragmentWriter
::
setGlobalICHelper
(
SetGlobalIC
*
ic
,
Box
*
o
,
BoxedString
*
s
,
Box
*
v
)
{
return
ic
->
call
(
o
,
s
,
v
);
}
Box
*
JitFragmentWriter
::
setitemICHelper
(
SetItemIC
*
ic
,
Box
*
o
,
Box
*
attr
,
Box
*
value
)
{
return
ic
->
call
(
o
,
attr
,
value
);
}
Box
*
JitFragmentWriter
::
unaryopICHelper
(
UnaryopIC
*
ic
,
Box
*
obj
,
int
op
)
{
return
ic
->
call
(
obj
,
op
);
}
void
JitFragmentWriter
::
_emitJump
(
CFGBlock
*
b
,
RewriterVar
*
block_next
,
int
&
size_of_exit_to_interp
)
{
size_of_exit_to_interp
=
0
;
...
...
@@ -733,6 +691,60 @@ void JitFragmentWriter::_emitOSRPoint(RewriterVar* result, RewriterVar* node_var
assertConsistent
();
}
void
JitFragmentWriter
::
_emitPPCall
(
RewriterVar
*
result
,
void
*
func_addr
,
const
RewriterVar
::
SmallVector
&
args
,
int
num_slots
,
int
slot_size
)
{
assembler
::
Register
r
=
allocReg
(
assembler
::
R11
);
if
(
args
.
size
()
>
6
)
{
// only 6 args can get passed in registers.
assert
(
args
.
size
()
<=
6
+
JitCodeBlock
::
num_stack_args
);
for
(
int
i
=
6
;
i
<
args
.
size
();
++
i
)
{
assembler
::
Register
reg
=
args
[
i
]
->
getInReg
(
Location
::
any
(),
true
);
assembler
->
mov
(
reg
,
assembler
::
Indirect
(
assembler
::
RSP
,
sizeof
(
void
*
)
*
(
i
-
6
)));
args
[
i
]
->
bumpUse
();
}
RewriterVar
::
SmallVector
reg_args
(
args
.
begin
(),
args
.
begin
()
+
6
);
assert
(
reg_args
.
size
()
==
6
);
_setupCall
(
result
,
false
,
reg_args
,
RewriterVar
::
SmallVector
());
}
else
_setupCall
(
result
,
false
,
args
,
RewriterVar
::
SmallVector
());
// make sure setupCall doesn't use R11
assert
(
vars_by_location
.
count
(
assembler
::
R11
)
==
0
);
int
pp_size
=
slot_size
*
num_slots
;
// make space for patchpoint
uint8_t
*
pp_start
=
rewrite
->
getSlotStart
()
+
assembler
->
bytesWritten
();
constexpr
int
call_size
=
16
;
assembler
->
skipBytes
(
pp_size
+
call_size
);
uint8_t
*
pp_end
=
rewrite
->
getSlotStart
()
+
assembler
->
bytesWritten
();
assert
(
assembler
->
hasFailed
()
||
(
pp_start
+
pp_size
+
call_size
==
pp_end
));
std
::
unique_ptr
<
ICSetupInfo
>
setup_info
(
ICSetupInfo
::
initialize
(
true
,
num_slots
,
slot_size
,
ICSetupInfo
::
Generic
,
NULL
));
// calculate available scratch space
int
pp_scratch_size
=
0
;
int
pp_scratch_location
=
rewrite
->
getScratchRspOffset
()
+
rewrite
->
getScratchSize
();
for
(
int
i
=
rewrite
->
getScratchSize
()
-
8
;
i
>=
0
;
i
-=
8
)
{
Location
l
(
Location
::
Scratch
,
i
);
if
(
vars_by_location
.
count
(
l
))
break
;
pp_scratch_size
+=
8
;
pp_scratch_location
-=
8
;
}
StackInfo
stack_info
(
pp_scratch_size
,
pp_scratch_location
);
pp_infos
.
emplace_back
(
PPInfo
{
func_addr
,
pp_start
,
pp_end
,
std
::
move
(
setup_info
),
stack_info
});
assert
(
vars_by_location
.
count
(
assembler
::
RAX
)
==
0
);
result
->
initializeInReg
(
assembler
::
RAX
);
assertConsistent
();
result
->
releaseIfNoUses
();
}
void
JitFragmentWriter
::
_emitReturn
(
RewriterVar
*
return_val
)
{
return_val
->
getInReg
(
assembler
::
RDX
,
true
);
assembler
->
mov
(
assembler
::
Immediate
(
0ul
),
assembler
::
RAX
);
// TODO: use xor
...
...
src/codegen/baseline_jit.h
View file @
b7873045
...
...
@@ -19,6 +19,7 @@
#include "asm_writing/rewriter.h"
#include "codegen/ast_interpreter.h"
#include "codegen/patchpoints.h"
#include "gc/heap.h"
#include "runtime/ics.h"
...
...
@@ -32,17 +33,6 @@ class BoxedDict;
class
BoxedList
;
class
BoxedTuple
;
class
SetGlobalIC
;
class
GetGlobalIC
;
class
SetAttrIC
;
class
GetAttrIC
;
class
SetItemIC
;
class
GetItemIC
;
class
CompareIC
;
class
AugBinopIC
;
class
UnaryopIC
;
class
RuntimeCallIC
;
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)
...
...
@@ -100,6 +90,7 @@ class JitFragmentWriter;
// mov %rsp,%rbp
// sub $0x108,%rsp ; setup scratch, 0x108 = scratch_size + 8 (=stack alignment)
// push %rdi ; save the pointer to ASTInterpreter instance
// sub $0x16,%rsp ; space for two func args passed on the stack
// jmpq *0x8(%rsi) ; jump to block->code
// possible values: first_JitFragment, second_JitFragment,...
//
...
...
@@ -130,10 +121,14 @@ class JitFragmentWriter;
//
//
class
JitCodeBlock
{
p
rivate
:
p
ublic
:
static
constexpr
int
scratch_size
=
256
;
static
constexpr
int
code_size
=
4096
*
2
;
static
constexpr
int
code_size
=
32768
;
static
constexpr
int
num_stack_args
=
2
;
static
constexpr
int
interpreter_ptr_offset
=
num_stack_args
*
8
;
private:
EHFrameManager
frame_manager
;
std
::
unique_ptr
<
uint8_t
[]
>
code
;
int
entry_offset
;
...
...
@@ -178,6 +173,16 @@ private:
// it in this field and process it only when we know we successfully generated the code.
std
::
pair
<
CFGBlock
*
,
int
/* offset from fragment start*/
>
side_exit_patch_location
;
struct
PPInfo
{
void
*
func_addr
;
uint8_t
*
start_addr
;
uint8_t
*
end_addr
;
std
::
unique_ptr
<
ICSetupInfo
>
ic
;
StackInfo
stack_info
;
};
llvm
::
SmallVector
<
PPInfo
,
8
>
pp_infos
;
public:
JitFragmentWriter
(
CFGBlock
*
block
,
std
::
unique_ptr
<
ICInfo
>
ic_info
,
std
::
unique_ptr
<
ICSlotRewrite
>
rewrite
,
int
code_offset
,
int
num_bytes_overlapping
,
void
*
entry_code
,
JitCodeBlock
&
code_block
);
...
...
@@ -250,35 +255,24 @@ private:
#endif
RewriterVar
*
getInterp
();
static
Box
*
augbinopICHelper
(
AugBinopIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
);
static
Box
*
binopICHelper
(
BinopIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
);
RewriterVar
*
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
);
static
Box
*
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
Box
**
args
,
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
Box
*
compareICHelper
(
CompareIC
*
ic
,
Box
*
lhs
,
Box
*
rhs
,
int
op
);
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
);
static
Box
*
createTupleHelper
(
uint64_t
num
,
Box
**
data
);
static
Box
*
exceptionMatchesHelper
(
Box
*
obj
,
Box
*
cls
);
static
Box
*
getAttrICHelper
(
GetAttrIC
*
ic
,
Box
*
o
,
BoxedString
*
attr
);
static
Box
*
getGlobalICHelper
(
GetGlobalIC
*
ic
,
Box
*
o
,
BoxedString
*
s
);
static
Box
*
getitemICHelper
(
GetItemIC
*
ic
,
Box
*
o
,
Box
*
attr
);
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
*
setAttrICHelper
(
SetAttrIC
*
ic
,
Box
*
o
,
BoxedString
*
attr
,
Box
*
value
);
static
Box
*
setGlobalICHelper
(
SetGlobalIC
*
ic
,
Box
*
o
,
BoxedString
*
s
,
Box
*
v
);
static
Box
*
setitemICHelper
(
SetItemIC
*
ic
,
Box
*
o
,
Box
*
attr
,
Box
*
value
);
static
Box
*
unaryopICHelper
(
UnaryopIC
*
ic
,
Box
*
obj
,
int
op
);
#if ENABLE_BASELINEJIT_ICS
static
Box
*
callattrHelperIC
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
CallattrIC
*
ic
,
Box
**
args
);
static
Box
*
runtimeCallHelperIC
(
Box
*
obj
,
ArgPassSpec
argspec
,
RuntimeCallIC
*
ic
,
Box
**
args
);
#endif
void
_emitJump
(
CFGBlock
*
b
,
RewriterVar
*
block_next
,
int
&
size_of_exit_to_interp
);
void
_emitOSRPoint
(
RewriterVar
*
result
,
RewriterVar
*
node_var
);
void
_emitPPCall
(
RewriterVar
*
result
,
void
*
func_addr
,
const
RewriterVar
::
SmallVector
&
args
,
int
num_slots
,
int
slot_size
);
void
_emitReturn
(
RewriterVar
*
v
);
void
_emitSideExit
(
RewriterVar
*
var
,
RewriterVar
*
val_constant
,
CFGBlock
*
next_block
,
RewriterVar
*
false_path
);
};
...
...
src/runtime/ics.h
View file @
b7873045
...
...
@@ -77,29 +77,6 @@ public:
}
};
class
RuntimeCallIC
:
public
RuntimeIC
{
public:
RuntimeCallIC
()
:
RuntimeIC
((
void
*
)
runtimeCall
,
2
,
320
)
{}
Box
*
call
(
Box
*
obj
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
{
return
(
Box
*
)
call_ptr
(
obj
,
argspec
,
arg1
,
arg2
,
arg3
,
args
);
}
};
class
UnaryopIC
:
public
RuntimeIC
{
public:
UnaryopIC
()
:
RuntimeIC
((
void
*
)
unaryop
,
2
,
160
)
{}
Box
*
call
(
Box
*
obj
,
int
op_type
)
{
return
(
Box
*
)
call_ptr
(
obj
,
op_type
);
}
};
class
AugBinopIC
:
public
RuntimeIC
{
public:
AugBinopIC
()
:
RuntimeIC
((
void
*
)
augbinop
,
2
,
240
)
{}
Box
*
call
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
return
(
Box
*
)
call_ptr
(
lhs
,
rhs
,
op_type
);
}
};
class
BinopIC
:
public
RuntimeIC
{
public:
BinopIC
()
:
RuntimeIC
((
void
*
)
binop
,
2
,
240
)
{}
...
...
@@ -107,55 +84,6 @@ public:
Box
*
call
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
return
(
Box
*
)
call_ptr
(
lhs
,
rhs
,
op_type
);
}
};
class
CompareIC
:
public
RuntimeIC
{
public:
CompareIC
()
:
RuntimeIC
((
void
*
)
compare
,
2
,
240
)
{}
Box
*
call
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
)
{
return
(
Box
*
)
call_ptr
(
lhs
,
rhs
,
op_type
);
}
};
class
GetItemIC
:
public
RuntimeIC
{
public:
GetItemIC
()
:
RuntimeIC
((
void
*
)
getitem
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
Box
*
attr
)
{
return
(
Box
*
)
call_ptr
(
obj
,
attr
);
}
};
class
SetItemIC
:
public
RuntimeIC
{
public:
SetItemIC
()
:
RuntimeIC
((
void
*
)
setitem
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
Box
*
attr
,
Box
*
v
)
{
return
(
Box
*
)
call_ptr
(
obj
,
attr
,
v
);
}
};
class
GetAttrIC
:
public
RuntimeIC
{
public:
GetAttrIC
()
:
RuntimeIC
((
void
*
)
getattr
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
BoxedString
*
attr
)
{
return
(
Box
*
)
call_ptr
(
obj
,
attr
);
}
};
class
SetAttrIC
:
public
RuntimeIC
{
public:
SetAttrIC
()
:
RuntimeIC
((
void
*
)
setattr
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
BoxedString
*
attr
,
Box
*
v
)
{
return
(
Box
*
)
call_ptr
(
obj
,
attr
,
v
);
}
};
class
GetGlobalIC
:
public
RuntimeIC
{
public:
GetGlobalIC
()
:
RuntimeIC
((
void
*
)
getGlobal
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
BoxedString
*
s
)
{
return
(
Box
*
)
call_ptr
(
obj
,
s
);
}
};
class
SetGlobalIC
:
public
RuntimeIC
{
public:
SetGlobalIC
()
:
RuntimeIC
((
void
*
)
setGlobal
,
2
,
512
)
{}
Box
*
call
(
Box
*
obj
,
BoxedString
*
s
,
Box
*
v
)
{
return
(
Box
*
)
call_ptr
(
obj
,
s
,
v
);
}
};
class
NonzeroIC
:
public
RuntimeIC
{
public:
NonzeroIC
()
:
RuntimeIC
((
void
*
)
nonzero
,
1
,
40
)
{}
...
...
src/runtime/types.cpp
View file @
b7873045
...
...
@@ -932,6 +932,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
assertInitNone
,
srewrite_args
.
out_rtn
);
}
}
else
{
rewrite_args
=
NULL
;
init_attr
=
processDescriptor
(
init_attr
,
made
,
cls
);
ArgPassSpec
init_argspec
=
argspec
;
...
...
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