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
229fb465
Commit
229fb465
authored
Jun 02, 2016
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rewriter: directly embed additional ref uses and bump uses early when emitting calls
parent
ce2d965d
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
166 additions
and
170 deletions
+166
-170
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+63
-49
src/asm_writing/rewriter.h
src/asm_writing/rewriter.h
+39
-11
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+3
-6
src/codegen/baseline_jit.cpp
src/codegen/baseline_jit.cpp
+40
-84
src/codegen/baseline_jit.h
src/codegen/baseline_jit.h
+4
-3
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+17
-17
No files found.
src/asm_writing/rewriter.cpp
View file @
229fb465
...
...
@@ -917,18 +917,9 @@ RewriterVar* Rewriter::loadConst(int64_t val, Location dest) {
}
RewriterVar
*
Rewriter
::
call
(
bool
has_side_effects
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
)
{
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
,
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
)
{
STAT_TIMER
(
t0
,
"us_timer_rewriter"
,
10
);
RewriterVar
*
result
=
createNewVar
();
RewriterVar
::
SmallVector
uses
;
for
(
RewriterVar
*
v
:
args
)
{
assert
(
v
!=
NULL
);
uses
.
push_back
(
v
);
}
for
(
RewriterVar
*
v
:
args_xmm
)
{
assert
(
v
!=
NULL
);
uses
.
push_back
(
v
);
}
ActionType
type
;
if
(
has_side_effects
)
...
...
@@ -936,36 +927,65 @@ RewriterVar* Rewriter::call(bool has_side_effects, void* func_addr, llvm::ArrayR
else
type
=
ActionType
::
NORMAL
;
// It's not nice to pass llvm::SmallVectors through a closure, especially with our SmallFunction
// optimization, so just regionAlloc them and copy the data in:
RewriterVar
**
_args
=
(
RewriterVar
**
)
this
->
regionAlloc
(
sizeof
(
RewriterVar
*
)
*
args
.
size
());
memcpy
(
_args
,
args
.
begin
(),
sizeof
(
RewriterVar
*
)
*
args
.
size
());
RewriterVar
**
_args_xmm
=
(
RewriterVar
**
)
this
->
regionAlloc
(
sizeof
(
RewriterVar
*
)
*
args_xmm
.
size
());
memcpy
(
_args_xmm
,
args_xmm
.
begin
(),
sizeof
(
RewriterVar
*
)
*
args_xmm
.
size
());
int
args_size
=
args
.
size
();
assert
(
args_xmm
.
size
()
<=
0x7fff
);
// Hack: pack this into a short to make sure it fits in the closure
short
xmm_args_size
=
args_xmm
.
size
();
// TODO: we don't need to generate the decref info for calls which can't throw
bool
can_throw
=
true
;
auto
args_array_ref
=
regionAllocArgs
(
args
,
args_xmm
,
additional_uses
);
// Hack: explicitly order the closure arguments so they pad nicer
addAction
([
args_size
,
xmm_args_size
,
has_side_effects
,
can_throw
,
this
,
result
,
func_addr
,
_args
,
_args_xmm
]()
{
this
->
_call
(
result
,
has_side_effects
,
can_throw
,
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
(
_args
,
args_size
),
llvm
::
ArrayRef
<
RewriterVar
*>
(
_args_xmm
,
xmm_args_size
));
for
(
int
i
=
0
;
i
<
args_size
;
i
++
)
_args
[
i
]
->
bumpUse
();
for
(
int
i
=
0
;
i
<
xmm_args_size
;
i
++
)
_args_xmm
[
i
]
->
bumpUse
();
},
uses
,
type
);
struct
LambdaClosure
{
RewriterVar
**
args_array
;
struct
{
unsigned
int
has_side_effects
:
1
;
unsigned
int
can_throw
:
1
;
unsigned
int
num_args
:
16
;
unsigned
int
num_args_xmm
:
16
;
unsigned
int
num_additional_uses
:
16
;
};
llvm
::
ArrayRef
<
RewriterVar
*>
allArgs
()
const
{
return
llvm
::
makeArrayRef
(
args_array
,
num_args
+
num_args_xmm
+
num_additional_uses
);
}
llvm
::
ArrayRef
<
RewriterVar
*>
args
()
const
{
return
allArgs
().
slice
(
0
,
num_args
);
}
llvm
::
ArrayRef
<
RewriterVar
*>
argsXmm
()
const
{
return
allArgs
().
slice
(
num_args
,
num_args_xmm
);
}
llvm
::
ArrayRef
<
RewriterVar
*>
additionalUses
()
const
{
return
allArgs
().
slice
((
int
)
num_args
+
(
int
)
num_args_xmm
,
num_additional_uses
);
}
LambdaClosure
(
llvm
::
MutableArrayRef
<
RewriterVar
*>
args_array_ref
,
llvm
::
ArrayRef
<
RewriterVar
*>
_args
,
llvm
::
ArrayRef
<
RewriterVar
*>
_args_xmm
,
llvm
::
ArrayRef
<
RewriterVar
*>
_addition_uses
,
bool
has_side_effects
,
bool
can_throw
)
:
args_array
(
args_array_ref
.
data
()),
has_side_effects
(
has_side_effects
),
can_throw
(
can_throw
),
num_args
(
_args
.
size
()),
num_args_xmm
(
_args_xmm
.
size
()),
num_additional_uses
(
_addition_uses
.
size
())
{
assert
(
_args
.
size
()
<
1
<<
16
);
assert
(
_args_xmm
.
size
()
<
1
<<
16
);
assert
(
_addition_uses
.
size
()
<
1
<<
16
);
}
}
lambda_closure
(
args_array_ref
,
args
,
args_xmm
,
additional_uses
,
has_side_effects
,
can_throw
);
assert
(
lambda_closure
.
args
().
size
()
==
args
.
size
());
assert
(
lambda_closure
.
argsXmm
().
size
()
==
args_xmm
.
size
());
assert
(
lambda_closure
.
additionalUses
().
size
()
==
additional_uses
.
size
());
addAction
([
this
,
result
,
func_addr
,
lambda_closure
]()
{
this
->
_call
(
result
,
lambda_closure
.
has_side_effects
,
lambda_closure
.
can_throw
,
func_addr
,
lambda_closure
.
args
(),
lambda_closure
.
argsXmm
(),
lambda_closure
.
allArgs
());
},
lambda_closure
.
allArgs
(),
type
);
return
result
;
}
void
Rewriter
::
_setupCall
(
bool
has_side_effects
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
,
Location
preserve
)
{
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
,
Location
preserve
,
llvm
::
ArrayRef
<
RewriterVar
*>
bump_if_possible
)
{
if
(
has_side_effects
)
assert
(
done_guarding
);
...
...
@@ -1052,6 +1072,10 @@ void Rewriter::_setupCall(bool has_side_effects, llvm::ArrayRef<RewriterVar*> ar
}
#endif
for
(
auto
&&
use
:
bump_if_possible
)
{
use
->
bumpUseEarlyIfPossible
();
}
// Spill caller-saved registers:
for
(
auto
check_reg
:
caller_save_registers
)
{
// check_reg.dump();
...
...
@@ -1114,7 +1138,8 @@ void Rewriter::_setupCall(bool has_side_effects, llvm::ArrayRef<RewriterVar*> ar
}
void
Rewriter
::
_call
(
RewriterVar
*
result
,
bool
has_side_effects
,
bool
can_throw
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
)
{
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
,
llvm
::
ArrayRef
<
RewriterVar
*>
vars_to_bump
)
{
if
(
LOG_IC_ASSEMBLY
)
assembler
->
comment
(
"_call"
);
...
...
@@ -1123,17 +1148,7 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, bool can_throw,
if
(
failed
)
return
;
_setupCall
(
has_side_effects
,
args
,
args_xmm
,
assembler
::
R11
);
// This duty is now on the caller:
/*
for (RewriterVar* arg : args) {
arg->bumpUse();
}
for (RewriterVar* arg_xmm : args_xmm) {
arg_xmm->bumpUse();
}
*/
_setupCall
(
has_side_effects
,
args
,
args_xmm
,
assembler
::
R11
,
vars_to_bump
);
assertConsistent
();
...
...
@@ -1164,6 +1179,10 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, bool can_throw,
if
(
result
)
result
->
releaseIfNoUses
();
for
(
RewriterVar
*
var
:
vars_to_bump
)
{
var
->
bumpUseLateIfNecessary
();
}
}
std
::
vector
<
Location
>
Rewriter
::
getDecrefLocations
()
{
...
...
@@ -1286,12 +1305,7 @@ void RewriterVar::refConsumed(RewriterAction* action) {
last_refconsumed_numuses
=
uses
.
size
();
if
(
!
action
)
action
=
rewriter
->
getLastAction
();
action
->
consumed_refs
.
emplace_back
(
this
);
}
void
RewriterVar
::
refUsed
()
{
// TODO: This is a pretty silly implementation that might prevent other optimizations?
rewriter
->
addAction
([
=
]()
{
this
->
bumpUse
();
},
{
this
},
ActionType
::
NORMAL
);
action
->
consumed_refs
.
push_front
(
this
);
}
bool
RewriterVar
::
needsDecref
(
int
current_action_index
)
{
...
...
@@ -1892,7 +1906,7 @@ void Rewriter::_checkAndThrowCAPIException(RewriterVar* r, int64_t exc_val, asse
}
else
assembler
->
cmp
(
var_reg
,
assembler
::
Immediate
(
exc_val
),
type
);
_setupCall
(
false
,
RewriterVar
::
SmallVector
(),
RewriterVar
::
SmallVector
()
);
_setupCall
(
false
,
{}
);
{
assembler
::
ForwardJump
jnz
(
*
assembler
,
assembler
::
COND_NOT_ZERO
);
assembler
->
mov
(
assembler
::
Immediate
((
void
*
)
throwCAPIException
),
assembler
::
R11
);
...
...
src/asm_writing/rewriter.h
View file @
229fb465
...
...
@@ -16,6 +16,7 @@
#define PYSTON_ASMWRITING_REWRITER_H
#include <deque>
#include <forward_list>
#include <list>
#include <map>
#include <memory>
...
...
@@ -192,8 +193,6 @@ public:
// if no action is specified it will assume the last action consumed the reference
void
refConsumed
(
RewriterAction
*
action
=
NULL
);
void
refUsed
();
// registerOwnedAttr tells the refcounter that a certain memory location holds a pointer
// to an owned reference. This must be paired with a call to deregisterOwnedAttr
// Call these right before emitting the store (for register) or decref (for deregister).
...
...
@@ -237,11 +236,11 @@ private:
// /* some code */
// bumpUseLateIfNecessary();
void
bumpUseEarlyIfPossible
()
{
if
(
reftype
!=
RefType
::
OWNED
)
if
(
reftype
!=
RefType
::
OWNED
&&
!
hasScratchAllocation
()
)
bumpUse
();
}
void
bumpUseLateIfNecessary
()
{
if
(
reftype
==
RefType
::
OWNED
)
if
(
reftype
==
RefType
::
OWNED
||
hasScratchAllocation
()
)
bumpUse
();
}
...
...
@@ -339,8 +338,9 @@ public:
class
RewriterAction
{
public:
SmallFunction
<
56
>
action
;
std
::
vector
<
RewriterVar
*>
consumed_refs
;
SmallFunction
<
48
>
action
;
std
::
forward_list
<
RewriterVar
*>
consumed_refs
;
template
<
typename
F
>
RewriterAction
(
F
&&
action
)
:
action
(
std
::
forward
<
F
>
(
action
))
{}
...
...
@@ -367,7 +367,33 @@ private:
protected:
// Allocates `bytes` bytes of data. The allocation will get freed when the rewriter gets freed.
void
*
regionAlloc
(
size_t
bytes
)
{
return
allocator
.
Allocate
(
bytes
,
16
/* alignment */
);
}
void
*
regionAlloc
(
size_t
bytes
,
int
alignment
=
16
)
{
return
allocator
.
Allocate
(
bytes
,
alignment
);
}
template
<
typename
T
>
llvm
::
MutableArrayRef
<
T
>
regionAlloc
(
size_t
num_elements
)
{
return
llvm
::
MutableArrayRef
<
T
>
(
allocator
.
Allocate
<
T
>
(
num_elements
),
num_elements
);
}
// This takes a variable number of llvm::ArrayRef<RewriterVar*> and copies in all elements into a single contiguous
// memory location.
template
<
typename
...
Args
>
llvm
::
MutableArrayRef
<
RewriterVar
*>
regionAllocArgs
(
llvm
::
ArrayRef
<
RewriterVar
*>
arg1
,
Args
...
args
)
{
size_t
num_total_args
=
0
;
for
(
auto
&&
array
:
{
arg1
,
args
...
})
{
num_total_args
+=
array
.
size
();
}
if
(
num_total_args
==
0
)
return
llvm
::
MutableArrayRef
<
RewriterVar
*>
();
auto
args_array_ref
=
regionAlloc
<
RewriterVar
*>
(
num_total_args
);
auto
insert_point
=
args_array_ref
;
for
(
auto
&&
array
:
{
arg1
,
args
...
})
{
if
(
!
array
.
empty
())
{
memcpy
(
insert_point
.
data
(),
array
.
data
(),
array
.
size
()
*
sizeof
(
RewriterVar
*
));
insert_point
=
insert_point
.
slice
(
array
.
size
());
}
}
assert
(
insert_point
.
size
()
==
0
);
return
args_array_ref
;
}
// Helps generating the best code for loading a const integer value.
// By keeping track of the last known value of every register and reusing it.
...
...
@@ -511,11 +537,13 @@ protected:
void
_slowpathJump
(
bool
condition_eq
);
void
_trap
();
void
_loadConst
(
RewriterVar
*
result
,
int64_t
val
);
void
_setupCall
(
bool
has_side_effects
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
,
Location
preserve
=
Location
::
any
());
void
_setupCall
(
bool
has_side_effects
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
=
{},
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
=
{},
Location
preserve
=
Location
::
any
(),
llvm
::
ArrayRef
<
RewriterVar
*>
bump_if_possible
=
{});
// _call does not call bumpUse on its arguments:
void
_call
(
RewriterVar
*
result
,
bool
has_side_effects
,
bool
can_throw
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
=
{});
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
=
{},
llvm
::
ArrayRef
<
RewriterVar
*>
vars_to_bump
=
{});
void
_add
(
RewriterVar
*
result
,
RewriterVar
*
a
,
int64_t
b
,
Location
dest
);
int
_allocate
(
RewriterVar
*
result
,
int
n
);
void
_allocateAndCopy
(
RewriterVar
*
result
,
RewriterVar
*
array
,
int
n
);
...
...
@@ -613,7 +641,7 @@ public:
// inline cache. (Extra allocations don't count even though they're potentially visible if you look
// hard enough.)
RewriterVar
*
call
(
bool
has_side_effects
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
=
{},
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
=
{});
llvm
::
ArrayRef
<
RewriterVar
*>
args_xmm
=
{}
,
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
=
{}
);
template
<
typename
...
Args
>
RewriterVar
*
call
(
bool
has_side_effects
,
void
*
func_addr
,
RewriterVar
*
arg1
,
Args
...
args
)
{
return
call
(
has_side_effects
,
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
({
arg1
,
args
...
}),
{});
...
...
src/codegen/ast_interpreter.cpp
View file @
229fb465
...
...
@@ -1172,12 +1172,9 @@ Value ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::
closure_var
=
jit
->
imm
(
0ul
);
if
(
!
passed_globals_var
)
passed_globals_var
=
jit
->
imm
(
0ul
);
rtn
.
var
=
jit
->
call
(
false
,
(
void
*
)
createFunctionFromMetadata
,
jit
->
imm
(
md
),
closure_var
,
passed_globals_var
,
defaults_var
,
jit
->
imm
(
args
->
defaults
.
size
()))
->
setType
(
RefType
::
OWNED
);
for
(
auto
d_var
:
defaults_vars
)
{
d_var
->
refUsed
();
}
rtn
.
var
=
jit
->
call
(
false
,
(
void
*
)
createFunctionFromMetadata
,
{
jit
->
imm
(
md
),
closure_var
,
passed_globals_var
,
defaults_var
,
jit
->
imm
(
args
->
defaults
.
size
())
},
{},
defaults_vars
)
->
setType
(
RefType
::
OWNED
);
}
rtn
.
o
=
createFunctionFromMetadata
(
md
,
closure
,
passed_globals
,
u
.
il
);
...
...
src/codegen/baseline_jit.cpp
View file @
229fb465
...
...
@@ -222,10 +222,10 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B
call_args
.
push_back
(
args
.
size
()
>
1
?
args
[
1
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
2
?
args
[
2
]
:
imm
(
0ul
));
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
;
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
],
RewriterVar
::
SetattrType
::
REF_USED
);
additional_uses
=
args
.
slice
(
3
);
RewriterVar
*
scratch
=
allocArgs
(
additional_uses
,
RewriterVar
::
SetattrType
::
REF_USED
);
call_args
.
push_back
(
scratch
);
}
else
if
(
keyword_names
)
{
call_args
.
push_back
(
imm
(
0ul
));
...
...
@@ -234,11 +234,8 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
auto
r
=
emitPPCall
((
void
*
)
callattr
,
call_args
,
2
,
640
,
node
,
type_recorder
).
first
->
setType
(
RefType
::
OWNED
);
for
(
int
i
=
3
;
i
<
args
.
size
();
i
++
)
{
args
[
i
]
->
refUsed
();
}
return
r
;
return
emitPPCall
((
void
*
)
callattr
,
call_args
,
2
,
640
,
node
,
type_recorder
,
additional_uses
)
.
first
->
setType
(
RefType
::
OWNED
);
#else
// We could make this faster but for now: keep it simple, stupid...
RewriterVar
*
attr_var
=
imm
(
attr
);
...
...
@@ -285,44 +282,9 @@ void JitFragmentWriter::emitDictSet(RewriterVar* dict, RewriterVar* k, RewriterV
v
->
refConsumed
();
}
// TODO: merge this function's functionality with refUsed
RewriterVar
*
JitFragmentWriter
::
emitCallWithAllocatedArgs
(
void
*
func_addr
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
)
{
RewriterVar
*
result
=
createNewVar
();
RewriterVar
::
SmallVector
uses
;
for
(
RewriterVar
*
v
:
args
)
{
assert
(
v
!=
NULL
);
uses
.
push_back
(
v
);
}
for
(
RewriterVar
*
v
:
additional_uses
)
{
assert
(
v
!=
NULL
);
uses
.
push_back
(
v
);
}
// It's not nice to pass llvm::SmallVectors through a closure, especially with our SmallFunction
// optimization, so just regionAlloc them and copy the data in:
RewriterVar
**
_args
=
(
RewriterVar
**
)
this
->
regionAlloc
(
sizeof
(
RewriterVar
*
)
*
args
.
size
());
memcpy
(
_args
,
args
.
begin
(),
sizeof
(
RewriterVar
*
)
*
args
.
size
());
RewriterVar
**
_args_additional
=
(
RewriterVar
**
)
this
->
regionAlloc
(
sizeof
(
RewriterVar
*
)
*
additional_uses
.
size
());
memcpy
(
_args_additional
,
additional_uses
.
begin
(),
sizeof
(
RewriterVar
*
)
*
additional_uses
.
size
());
int
args_size
=
args
.
size
();
assert
(
additional_uses
.
size
()
<=
0x7fff
);
// Hack: pack this into a short to make sure it fits in the closure
short
args_additional_size
=
additional_uses
.
size
();
bool
can_throw
=
true
;
// Hack: explicitly order the closure arguments so they pad nicer
addAction
([
args_size
,
args_additional_size
,
can_throw
,
func_addr
,
this
,
result
,
_args
,
_args_additional
]()
{
this
->
_call
(
result
,
false
,
can_throw
,
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
(
_args
,
args_size
),
llvm
::
ArrayRef
<
RewriterVar
*>
());
for
(
int
i
=
0
;
i
<
args_size
;
i
++
)
_args
[
i
]
->
bumpUse
();
for
(
int
i
=
0
;
i
<
args_additional_size
;
i
++
)
_args_additional
[
i
]
->
bumpUse
();
},
uses
,
ActionType
::
NORMAL
);
return
result
;
return
call
(
false
,
func_addr
,
args
,
{},
additional_uses
);
}
RewriterVar
*
JitFragmentWriter
::
emitCreateList
(
const
llvm
::
ArrayRef
<
RewriterVar
*>
values
)
{
...
...
@@ -504,21 +466,18 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj
call_args
.
push_back
(
args
.
size
()
>
1
?
args
[
1
]
:
imm
(
0ul
));
call_args
.
push_back
(
args
.
size
()
>
2
?
args
[
2
]
:
imm
(
0ul
));
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
;
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
],
RewriterVar
::
SetattrType
::
REF_USED
);
additional_uses
=
args
.
slice
(
3
);
RewriterVar
*
scratch
=
allocArgs
(
additional_uses
,
RewriterVar
::
SetattrType
::
REF_USED
);
call_args
.
push_back
(
scratch
);
}
else
call_args
.
push_back
(
imm
(
0ul
));
if
(
keyword_names
)
call_args
.
push_back
(
imm
(
keyword_names
));
auto
r
=
emitPPCall
((
void
*
)
runtimeCall
,
call_args
,
2
,
640
,
node
,
type_recorder
).
first
->
setType
(
RefType
::
OWNED
);
for
(
int
i
=
3
;
i
<
args
.
size
();
i
++
)
{
args
[
i
]
->
refUsed
();
}
return
r
;
return
emitPPCall
((
void
*
)
runtimeCall
,
call_args
,
2
,
640
,
node
,
type_recorder
,
additional_uses
)
.
first
->
setType
(
RefType
::
OWNED
);
#else
RewriterVar
*
argspec_var
=
imm
(
argspec
.
asInt
());
RewriterVar
*
keyword_names_var
=
keyword_names
?
imm
(
keyword_names
)
:
nullptr
;
...
...
@@ -576,11 +535,9 @@ RewriterVar* JitFragmentWriter::emitYield(RewriterVar* v) {
auto
&&
args
=
allocArgs
(
local_args
,
RewriterVar
::
SetattrType
::
REF_USED
);
RewriterVar
*
generator
=
interp
->
getAttr
(
ASTInterpreterJitInterface
::
getGeneratorOffset
());
auto
rtn
=
call
(
false
,
(
void
*
)
yield
,
generator
,
v
,
args
,
imm
(
local_args
.
size
()))
->
setType
(
RefType
::
OWNED
);
auto
rtn
=
call
(
false
,
(
void
*
)
yield
,
{
generator
,
v
,
args
,
imm
(
local_args
.
size
())
},
{},
local_args
)
->
setType
(
RefType
::
OWNED
);
v
->
refConsumed
();
for
(
auto
&&
var
:
local_args
)
{
var
->
refUsed
();
}
return
rtn
;
}
...
...
@@ -906,31 +863,38 @@ uint64_t JitFragmentWriter::asUInt(InternedString s) {
}
#endif
std
::
pair
<
RewriterVar
*
,
RewriterAction
*>
JitFragmentWriter
::
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
,
AST
*
ast_node
,
TypeRecorder
*
type_recorder
)
{
std
::
pair
<
RewriterVar
*
,
RewriterAction
*>
JitFragmentWriter
::
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
unsigned
char
num_slots
,
unsigned
short
slot_size
,
AST
*
ast_node
,
TypeRecorder
*
type_recorder
,
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
)
{
if
(
LOG_BJIT_ASSEMBLY
)
comment
(
"BJIT: emitPPCall() start"
);
RewriterVar
::
SmallVector
args_vec
(
args
.
begin
(),
args
.
end
());
#if ENABLE_BASELINEJIT_ICS
RewriterVar
*
result
=
createNewVar
();
auto
args_array_ref
=
regionAllocArgs
(
args
,
additional_uses
);
assert
(
args
.
size
()
<
1ul
<<
32
);
int
args_size
=
args
.
size
();
RewriterVar
**
_args
=
(
RewriterVar
**
)
regionAlloc
(
sizeof
(
RewriterVar
*
)
*
args_size
);
memcpy
(
_args
,
args
.
begin
(),
sizeof
(
RewriterVar
*
)
*
args_size
);
assert
(
additional_uses
.
size
()
<
1
<<
8
);
unsigned
char
num_additional
=
additional_uses
.
size
();
RewriterVar
**
args_array
=
args_array_ref
.
data
();
RewriterAction
*
call_action
=
addAction
([
=
]()
{
this
->
_emitPPCall
(
result
,
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
(
_args
,
args_size
),
num_slots
,
slot_size
,
ast_node
);
},
args
,
ActionType
::
NORMAL
);
RewriterAction
*
call_action
=
addAction
([
this
,
result
,
func_addr
,
ast_node
,
args_array
,
args_size
,
slot_size
,
num_slots
,
num_additional
]()
{
auto
all_args
=
llvm
::
makeArrayRef
(
args_array
,
args_size
+
num_additional
);
auto
args
=
all_args
.
slice
(
0
,
args_size
);
this
->
_emitPPCall
(
result
,
func_addr
,
args
,
num_slots
,
slot_size
,
ast_node
,
all_args
);
},
args_array_ref
,
ActionType
::
NORMAL
);
if
(
type_recorder
)
{
RewriterVar
*
type_recorder_var
=
imm
(
type_recorder
);
RewriterVar
*
obj_cls_var
=
result
->
getAttr
(
offsetof
(
Box
,
cls
));
addAction
([
=
]()
{
_emitRecordType
(
type_recorder_var
,
obj_cls_var
);
},
{
type_recorder_var
,
obj_cls_var
},
ActionType
::
NORMAL
);
result
->
refUsed
();
addAction
([
=
]()
{
_emitRecordType
(
type_recorder_var
,
obj_cls_var
);
result
->
bumpUse
();
},
{
type_recorder_var
,
obj_cls_var
,
result
},
ActionType
::
NORMAL
);
emitPendingCallsCheck
();
return
std
::
make_pair
(
result
,
call_action
);
...
...
@@ -1025,7 +989,7 @@ void JitFragmentWriter::_emitGetLocal(RewriterVar* val_var, const char* name) {
assembler
::
Register
var_reg
=
val_var
->
getInReg
();
assembler
->
test
(
var_reg
,
var_reg
);
_setupCall
(
false
,
RewriterVar
::
SmallVector
(),
RewriterVar
::
SmallVector
()
);
_setupCall
(
false
,
{}
);
{
assembler
::
ForwardJump
jnz
(
*
assembler
,
assembler
::
COND_NOT_ZERO
);
assembler
->
mov
(
assembler
::
Immediate
((
uint64_t
)
name
),
assembler
::
RDI
);
...
...
@@ -1100,7 +1064,8 @@ void JitFragmentWriter::_emitOSRPoint() {
}
void
JitFragmentWriter
::
_emitPPCall
(
RewriterVar
*
result
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
,
AST
*
ast_node
)
{
int
num_slots
,
int
slot_size
,
AST
*
ast_node
,
llvm
::
ArrayRef
<
RewriterVar
*>
vars_to_bump
)
{
assembler
::
Register
r
=
allocReg
(
assembler
::
R11
);
if
(
args
.
size
()
>
6
)
{
// only 6 args can get passed in registers.
...
...
@@ -1109,11 +1074,9 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::
assembler
::
Register
reg
=
args
[
i
]
->
getInReg
(
Location
::
any
(),
true
);
assembler
->
mov
(
reg
,
assembler
::
Indirect
(
assembler
::
RSP
,
sizeof
(
void
*
)
*
(
i
-
6
)));
}
RewriterVar
::
SmallVector
reg_args
(
args
.
begin
(),
args
.
begin
()
+
6
);
assert
(
reg_args
.
size
()
==
6
);
_setupCall
(
false
,
reg_args
,
RewriterVar
::
SmallVector
());
_setupCall
(
false
,
args
.
slice
(
0
,
6
),
{},
Location
::
any
(),
vars_to_bump
);
}
else
_setupCall
(
false
,
args
,
RewriterVar
::
SmallVector
()
);
_setupCall
(
false
,
args
,
{},
Location
::
any
(),
vars_to_bump
);
if
(
failed
)
return
;
...
...
@@ -1158,15 +1121,8 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::
result
->
releaseIfNoUses
();
// TODO: it would be nice to be able to bumpUse on these earlier so that we could potentially avoid spilling
// the args across the call if we don't need to.
// This had to get moved to the very end of this function due to the fact that bumpUse can cause refcounting
// operations to happen.
// I'm not sure though that just moving this earlier is good enough though -- we also might need to teach setupCall
// that the args might not be needed afterwards?
// Anyway this feels like micro-optimizations at the moment and we can figure it out later.
for
(
RewriterVar
*
arg
:
args
)
{
arg
->
bumpUse
();
for
(
RewriterVar
*
use
:
vars_to_bump
)
{
use
->
bumpUseLateIfNecessary
();
}
}
...
...
src/codegen/baseline_jit.h
View file @
229fb465
...
...
@@ -316,8 +316,9 @@ private:
RewriterVar
*
emitCallWithAllocatedArgs
(
void
*
func_addr
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
const
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
);
std
::
pair
<
RewriterVar
*
,
RewriterAction
*>
emitPPCall
(
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
,
AST
*
ast_node
=
NULL
,
TypeRecorder
*
type_recorder
=
NULL
);
unsigned
char
num_slots
,
unsigned
short
slot_size
,
AST
*
ast_node
=
NULL
,
TypeRecorder
*
type_recorder
=
NULL
,
llvm
::
ArrayRef
<
RewriterVar
*>
additional_uses
=
{});
static
void
assertNameDefinedHelper
(
const
char
*
id
);
static
Box
*
callattrHelper
(
Box
*
obj
,
BoxedString
*
attr
,
CallattrFlags
flags
,
TypeRecorder
*
type_recorder
,
...
...
@@ -337,7 +338,7 @@ private:
void
_emitJump
(
CFGBlock
*
b
,
RewriterVar
*
block_next
,
ExitInfo
&
exit_info
);
void
_emitOSRPoint
();
void
_emitPPCall
(
RewriterVar
*
result
,
void
*
func_addr
,
llvm
::
ArrayRef
<
RewriterVar
*>
args
,
int
num_slots
,
int
slot_size
,
AST
*
ast_node
);
int
slot_size
,
AST
*
ast_node
,
llvm
::
ArrayRef
<
RewriterVar
*>
vars_to_bump
);
void
_emitRecordType
(
RewriterVar
*
type_recorder_var
,
RewriterVar
*
obj_cls_var
);
void
_emitReturn
(
RewriterVar
*
v
);
void
_emitSideExit
(
STOLEN
(
RewriterVar
*
)
var
,
RewriterVar
*
val_constant
,
CFGBlock
*
next_block
,
...
...
src/runtime/objmodel.cpp
View file @
229fb465
...
...
@@ -4870,32 +4870,32 @@ Box* callCLFunc(FunctionMetadata* md, CallRewriteArgs* rewrite_args, int num_out
}
else
{
// Hacky workaround: the rewriter can only pass arguments in registers, so use this helper function
// to unpack some of the additional arguments:
llvm
::
SmallVector
<
RewriterVar
*
,
4
>
additional_uses
;
RewriterVar
*
arg_array
=
rewrite_args
->
rewriter
->
allocate
(
4
);
arg_vec
.
push_back
(
arg_array
);
if
(
num_output_args
>=
1
)
if
(
num_output_args
>=
1
)
{
arg_array
->
setAttr
(
0
,
rewrite_args
->
arg1
,
RewriterVar
::
SetattrType
::
REF_USED
);
if
(
num_output_args
>=
2
)
additional_uses
.
push_back
(
rewrite_args
->
arg1
);
}
if
(
num_output_args
>=
2
)
{
arg_array
->
setAttr
(
8
,
rewrite_args
->
arg2
,
RewriterVar
::
SetattrType
::
REF_USED
);
if
(
num_output_args
>=
3
)
additional_uses
.
push_back
(
rewrite_args
->
arg2
);
}
if
(
num_output_args
>=
3
)
{
arg_array
->
setAttr
(
16
,
rewrite_args
->
arg3
,
RewriterVar
::
SetattrType
::
REF_USED
);
if
(
num_output_args
>=
4
)
additional_uses
.
push_back
(
rewrite_args
->
arg3
);
}
if
(
num_output_args
>=
4
)
{
arg_array
->
setAttr
(
24
,
rewrite_args
->
args
,
RewriterVar
::
SetattrType
::
REF_USED
);
additional_uses
.
push_back
(
rewrite_args
->
args
);
}
if
(
S
==
CXX
)
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
astInterpretHelper
,
arg_vec
)
->
setType
(
RefType
::
OWNED
);
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
astInterpretHelper
,
arg_vec
,
{},
additional_uses
)
->
setType
(
RefType
::
OWNED
);
else
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
astInterpretHelperCapi
,
arg_vec
)
->
setType
(
RefType
::
OWNED
);
if
(
num_output_args
>=
1
)
rewrite_args
->
arg1
->
refUsed
();
if
(
num_output_args
>=
2
)
rewrite_args
->
arg2
->
refUsed
();
if
(
num_output_args
>=
3
)
rewrite_args
->
arg3
->
refUsed
();
if
(
num_output_args
>=
4
)
rewrite_args
->
args
->
refUsed
();
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
astInterpretHelperCapi
,
arg_vec
,
{},
additional_uses
)
->
setType
(
RefType
::
OWNED
);
}
rewrite_args
->
out_success
=
true
;
...
...
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