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
caa84b81
Commit
caa84b81
authored
Jul 12, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #684 from kmod/tiering2
tiering refactoring
parents
0915db4e
a87e2eaf
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
331 additions
and
396 deletions
+331
-396
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+83
-57
src/codegen/ast_interpreter.h
src/codegen/ast_interpreter.h
+6
-6
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+22
-0
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+15
-31
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+6
-12
src/codegen/irgen.h
src/codegen/irgen.h
+3
-3
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+31
-91
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+35
-56
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+5
-1
src/codegen/osrentry.h
src/codegen/osrentry.h
+5
-6
src/codegen/patchpoints.cpp
src/codegen/patchpoints.cpp
+0
-9
src/codegen/patchpoints.h
src/codegen/patchpoints.h
+4
-0
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+65
-42
src/codegen/unwinding.h
src/codegen/unwinding.h
+10
-7
src/core/cfg.cpp
src/core/cfg.cpp
+2
-0
src/core/types.h
src/core/types.h
+14
-25
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+1
-1
src/runtime/frame.cpp
src/runtime/frame.cpp
+4
-4
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+20
-45
No files found.
src/codegen/ast_interpreter.cpp
View file @
caa84b81
This diff is collapsed.
Click to expand it.
src/codegen/ast_interpreter.h
View file @
caa84b81
...
...
@@ -29,7 +29,7 @@ class AST_Jump;
class
Box
;
class
BoxedClosure
;
class
BoxedDict
;
struct
C
ompiled
Function
;
struct
C
L
Function
;
struct
LineInfo
;
extern
const
void
*
interpreter_instr_addr
;
...
...
@@ -72,15 +72,15 @@ struct Value {
};
void
setupInterpreter
();
Box
*
astInterpretFunction
(
C
ompiledFunction
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg
2
,
Box
*
arg
3
,
Box
**
args
);
Box
*
astInterpretFunctionEval
(
C
ompiled
Function
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
);
Box
*
astInterpretFrom
(
C
ompiled
Function
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpretFunction
(
C
LFunction
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
Box
*
astInterpretFunctionEval
(
C
L
Function
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
);
Box
*
astInterpretFrom
(
C
L
Function
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
);
AST_stmt
*
getCurrentStatementForInterpretedFrame
(
void
*
frame_ptr
);
Box
*
getGlobalsForInterpretedFrame
(
void
*
frame_ptr
);
C
ompiledFunction
*
getCF
ForInterpretedFrame
(
void
*
frame_ptr
);
C
LFunction
*
getCL
ForInterpretedFrame
(
void
*
frame_ptr
);
struct
FrameInfo
;
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
);
BoxedClosure
*
passedClosureForInterpretedFrame
(
void
*
frame_ptr
);
...
...
src/codegen/codegen.cpp
View file @
caa84b81
...
...
@@ -27,6 +27,7 @@
#include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h"
#include "codegen/baseline_jit.h"
#include "codegen/compvars.h"
#include "core/ast.h"
#include "core/util.h"
...
...
@@ -35,6 +36,27 @@ namespace pyston {
DS_DEFINE_RWLOCK
(
codegen_rwlock
);
CLFunction
::
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
std
::
unique_ptr
<
SourceInfo
>
source
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
std
::
move
(
source
)),
param_names
(
this
->
source
->
ast
,
this
->
source
->
getInternedStrings
()),
always_use_version
(
NULL
),
code_obj
(
NULL
),
times_interpreted
(
0
)
{
assert
(
num_args
>=
num_defaults
);
}
CLFunction
::
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
nullptr
),
param_names
(
param_names
),
always_use_version
(
NULL
),
code_obj
(
NULL
),
times_interpreted
(
0
)
{
assert
(
num_args
>=
num_defaults
);
}
SourceInfo
::
SourceInfo
(
BoxedModule
*
m
,
ScopingAnalysis
*
scoping
,
FutureFlags
future_flags
,
AST
*
ast
,
std
::
vector
<
AST_stmt
*>
body
,
std
::
string
fn
)
:
parent_module
(
m
),
...
...
src/codegen/compvars.cpp
View file @
caa84b81
...
...
@@ -249,7 +249,7 @@ public:
// var->getValue()->dump(); llvm::errs() << '\n';
// ptr->dump(); llvm::errs() << '\n';
// converted->getValue()->dump(); llvm::errs() << '\n';
bool
do_patchpoint
=
ENABLE_ICSETATTRS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICSETATTRS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createSetattrIC
(
info
.
getTypeRecorder
());
...
...
@@ -269,7 +269,7 @@ public:
llvm
::
Constant
*
ptr
=
embedRelocatablePtr
(
attr
,
g
.
llvm_boxedstring_type_ptr
);
// TODO
// bool do_patchpoint = ENABLE_ICDELATTRS
&& !info.isInterpreted()
;
// bool do_patchpoint = ENABLE_ICDELATTRS;
bool
do_patchpoint
=
false
;
if
(
do_patchpoint
)
{
...
...
@@ -317,7 +317,7 @@ public:
}
ConcreteCompilerVariable
*
len
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
override
{
bool
do_patchpoint
=
ENABLE_ICGENERICS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGENERICS
;
llvm
::
Value
*
rtn
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGenericIC
(
info
.
getTypeRecorder
(),
true
,
256
);
...
...
@@ -337,7 +337,7 @@ public:
CompilerVariable
*
slice
)
override
{
ConcreteCompilerVariable
*
converted_slice
=
slice
->
makeConverted
(
emitter
,
slice
->
getBoxType
());
bool
do_patchpoint
=
ENABLE_ICGETITEMS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGETITEMS
;
llvm
::
Value
*
rtn
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetitemIC
(
info
.
getTypeRecorder
());
...
...
@@ -414,7 +414,7 @@ public:
ConcreteCompilerVariable
*
converted_rhs
=
rhs
->
makeConverted
(
emitter
,
rhs
->
getBoxType
());
llvm
::
Value
*
rtn
;
bool
do_patchpoint
=
ENABLE_ICBINEXPS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICBINEXPS
;
llvm
::
Value
*
rt_func
;
void
*
rt_func_addr
;
...
...
@@ -495,7 +495,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
raw_func
=
(
void
*
)
pyston
::
getattr
;
}
bool
do_patchpoint
=
ENABLE_ICGETATTRS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGETATTRS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetattrIC
(
info
.
getTypeRecorder
());
...
...
@@ -551,19 +551,13 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
if
(
args
.
size
()
>=
4
)
{
llvm
::
Value
*
arg_array
;
if
(
info
.
isInterpreted
())
{
llvm
::
Value
*
n_bytes
=
getConstantInt
((
args
.
size
()
-
3
)
*
sizeof
(
Box
*
),
g
.
i64
);
mallocsave
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
malloc
,
n_bytes
);
arg_array
=
emitter
.
getBuilder
()
->
CreateBitCast
(
mallocsave
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
}
else
{
llvm
::
Value
*
n_varargs
=
getConstantInt
(
args
.
size
()
-
3
,
g
.
i64
);
llvm
::
Value
*
n_varargs
=
getConstantInt
(
args
.
size
()
-
3
,
g
.
i64
);
// Don't use the IRBuilder since we want to specifically put this in the entry block so it only gets called
// once.
// TODO we could take this further and use the same alloca for all function calls?
llvm
::
Instruction
*
insertion_point
=
emitter
.
currentFunction
()
->
func
->
getEntryBlock
().
getFirstInsertionPt
();
arg_array
=
new
llvm
::
AllocaInst
(
g
.
llvm_value_type_ptr
,
n_varargs
,
"arg_scratch"
,
insertion_point
);
}
// Don't use the IRBuilder since we want to specifically put this in the entry block so it only gets called
// once.
// TODO we could take this further and use the same alloca for all function calls?
llvm
::
Instruction
*
insertion_point
=
emitter
.
currentFunction
()
->
func
->
getEntryBlock
().
getFirstInsertionPt
();
arg_array
=
new
llvm
::
AllocaInst
(
g
.
llvm_value_type_ptr
,
n_varargs
,
"arg_scratch"
,
insertion_point
);
for
(
int
i
=
3
;
i
<
args
.
size
();
i
++
)
{
llvm
::
Value
*
ptr
=
emitter
.
getBuilder
()
->
CreateConstGEP1_32
(
arg_array
,
i
-
3
);
...
...
@@ -590,8 +584,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// for (auto a : llvm_args)
// a->dump();
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
!
info
.
isInterpreted
()
&&
(
func_addr
==
runtimeCall
||
func_addr
==
pyston
::
callattr
);
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
(
func_addr
==
runtimeCall
||
func_addr
==
pyston
::
callattr
);
if
(
do_patchpoint
)
{
assert
(
func_addr
);
...
...
@@ -685,7 +678,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
}
ConcreteCompilerVariable
*
UnknownType
::
nonzero
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
{
bool
do_patchpoint
=
ENABLE_ICNONZEROS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICNONZEROS
;
llvm
::
Value
*
rtn_val
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createNonzeroIC
(
info
.
getTypeRecorder
());
...
...
@@ -702,7 +695,7 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
}
ConcreteCompilerVariable
*
UnknownType
::
hasnext
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
{
bool
do_patchpoint
=
ENABLE_ICS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICS
;
do_patchpoint
=
false
;
// we are currently using runtime ics for this
llvm
::
Value
*
rtn_val
;
if
(
do_patchpoint
)
{
...
...
@@ -1573,7 +1566,6 @@ public:
}
assert
(
found
);
assert
(
!
cf
->
is_interpreted
);
assert
(
cf
->
code
);
std
::
vector
<
llvm
::
Type
*>
arg_types
;
...
...
@@ -1965,14 +1957,6 @@ CompilerVariable* makeStr(BoxedString* s) {
return
new
ValuedCompilerVariable
<
BoxedString
*>
(
STR_CONSTANT
,
s
,
true
);
}
class
VoidType
:
public
ConcreteCompilerType
{
public:
llvm
::
Type
*
llvmType
()
override
{
return
g
.
void_
;
}
Box
*
deserializeFromFrame
(
const
FrameVals
&
vals
)
override
{
abort
();
}
};
ConcreteCompilerType
*
VOID
=
new
VoidType
();
ConcreteCompilerType
*
typeFromClass
(
BoxedClass
*
c
)
{
assert
(
c
);
return
NormalObjectType
::
fromClass
(
c
);
...
...
src/codegen/irgen.cpp
View file @
caa84b81
...
...
@@ -579,11 +579,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// printf("%ld\n", args.size());
llvm
::
CallInst
*
postcall
=
emitter
->
getBuilder
()
->
CreateCall
(
bitcast_r
,
args
);
postcall
->
setTailCall
(
true
);
if
(
rtn_type
==
VOID
)
{
emitter
->
getBuilder
()
->
CreateRetVoid
();
}
else
{
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
}
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
}
...
...
@@ -941,16 +937,15 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel eff
os
<<
"_e"
<<
(
int
)
effort
;
if
(
entry
)
{
os
<<
"_osr"
<<
entry
->
backedge
->
target
->
idx
;
if
(
entry
->
cf
->
func
)
os
<<
"_from_"
<<
entry
->
cf
->
func
->
getName
().
data
();
}
os
<<
'_'
<<
num_functions
;
num_functions
++
;
return
os
.
str
();
}
CompiledFunction
*
doCompile
(
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
)
{
CompiledFunction
*
doCompile
(
CLFunction
*
clfunc
,
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
)
{
Timer
_t
(
"in doCompile"
);
Timer
_t2
;
long
irgen_us
=
0
;
...
...
@@ -1014,8 +1009,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
}
CompiledFunction
*
cf
=
new
CompiledFunction
(
NULL
,
spec
,
(
effort
==
EffortLevel
::
INTERPRETED
),
NULL
,
effort
,
entry_descriptor
);
CompiledFunction
*
cf
=
new
CompiledFunction
(
NULL
,
spec
,
NULL
,
effort
,
entry_descriptor
);
// Make sure that the instruction memory keeps the module object alive.
// TODO: implement this for real
...
...
@@ -1065,7 +1059,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
else
phis
=
computeRequiredPhis
(
*
param_names
,
source
->
cfg
,
liveness
,
source
->
getScopeInfo
());
IRGenState
irstate
(
cf
,
source
,
std
::
move
(
phis
),
param_names
,
getGCBuilder
(),
dbg_funcinfo
);
IRGenState
irstate
(
c
lfunc
,
c
f
,
source
,
std
::
move
(
phis
),
param_names
,
getGCBuilder
(),
dbg_funcinfo
);
emitBBs
(
&
irstate
,
types
,
entry_descriptor
,
blocks
);
...
...
src/codegen/irgen.h
View file @
caa84b81
...
...
@@ -100,8 +100,9 @@ extern const std::string PASSED_GENERATOR_NAME;
InternedString
getIsDefinedName
(
InternedString
name
,
InternedStringPool
&
interned_strings
);
bool
isIsDefinedName
(
llvm
::
StringRef
name
);
CompiledFunction
*
doCompile
(
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
);
CompiledFunction
*
doCompile
(
CLFunction
*
clfunc
,
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
);
// A common pattern is to branch based off whether a variable is defined but only if it is
// potentially-undefined. If it is potentially-undefined, we have to generate control-flow
...
...
@@ -134,7 +135,6 @@ public:
OpInfo
(
EffortLevel
effort
,
TypeRecorder
*
type_recorder
,
UnwindInfo
unw_info
)
:
effort
(
effort
),
type_recorder
(
type_recorder
),
unw_info
(
unw_info
)
{}
bool
isInterpreted
()
const
{
return
effort
==
EffortLevel
::
INTERPRETED
;
}
TypeRecorder
*
getTypeRecorder
()
const
{
return
type_recorder
;
}
};
}
...
...
src/codegen/irgen/hooks.cpp
View file @
caa84b81
This diff is collapsed.
Click to expand it.
src/codegen/irgen/irgenerator.cpp
View file @
caa84b81
...
...
@@ -42,9 +42,11 @@ extern "C" void dumpLLVM(llvm::Value* v) {
v
->
dump
();
}
IRGenState
::
IRGenState
(
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
)
:
cf
(
cf
),
IRGenState
::
IRGenState
(
CLFunction
*
clfunc
,
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
)
:
clfunc
(
clfunc
),
cf
(
cf
),
source_info
(
source_info
),
phis
(
std
::
move
(
phis
)),
param_names
(
param_names
),
...
...
@@ -402,8 +404,6 @@ public:
llvm
::
Value
*
createIC
(
const
ICSetupInfo
*
pp
,
void
*
func_addr
,
const
std
::
vector
<
llvm
::
Value
*>&
args
,
UnwindInfo
unw_info
)
override
{
assert
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
);
std
::
vector
<
llvm
::
Value
*>
stackmap_args
;
llvm
::
CallSite
rtn
...
...
@@ -493,7 +493,7 @@ private:
assert
(
ast
);
EffortLevel
effort
=
irstate
->
getEffortLevel
();
bool
record_types
=
(
effort
!=
EffortLevel
::
INTERPRETED
&&
effort
!=
EffortLevel
::
MAXIMAL
)
;
bool
record_types
=
effort
!=
EffortLevel
::
MAXIMAL
;
TypeRecorder
*
type_recorder
;
if
(
record_types
)
{
...
...
@@ -531,10 +531,7 @@ private:
emitter
.
getBuilder
()
->
SetInsertPoint
(
curblock
);
llvm
::
Value
*
v
=
emitter
.
createCall2
(
UnwindInfo
(
current_statement
,
NULL
),
g
.
funcs
.
deopt
,
embedRelocatablePtr
(
node
,
g
.
llvm_aststmt_type_ptr
),
node_value
);
if
(
irstate
->
getReturnType
()
==
VOID
)
emitter
.
getBuilder
()
->
CreateRetVoid
();
else
emitter
.
getBuilder
()
->
CreateRet
(
v
);
emitter
.
getBuilder
()
->
CreateRet
(
v
);
curblock
=
success_bb
;
emitter
.
getBuilder
()
->
SetInsertPoint
(
curblock
);
...
...
@@ -594,38 +591,29 @@ private:
llvm
::
Value
*
cxaexc_pointer
=
emitter
.
getBuilder
()
->
CreateExtractValue
(
landing_pad
,
{
0
});
if
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
{
llvm
::
Function
*
std_module_catch
=
g
.
stdlib_module
->
getFunction
(
"__cxa_begin_catch"
);
auto
begin_catch_func
=
g
.
cur_module
->
getOrInsertFunction
(
std_module_catch
->
getName
(),
std_module_catch
->
getFunctionType
());
assert
(
begin_catch_func
);
llvm
::
Value
*
excinfo_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
begin_catch_func
,
cxaexc_pointer
);
llvm
::
Value
*
excinfo_pointer_casted
=
emitter
.
getBuilder
()
->
CreateBitCast
(
excinfo_pointer
,
g
.
llvm_excinfo_type
->
getPointerTo
());
auto
*
builder
=
emitter
.
getBuilder
();
llvm
::
Value
*
exc_type
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
0
));
llvm
::
Value
*
exc_value
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
1
));
llvm
::
Value
*
exc_traceback
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
2
));
assert
(
exc_type
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_value
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_traceback
->
getType
()
==
g
.
llvm_value_type_ptr
);
return
makeTuple
({
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_type
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_value
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_traceback
,
true
)
});
}
else
{
// TODO This doesn't get hit, right?
abort
();
llvm
::
Function
*
std_module_catch
=
g
.
stdlib_module
->
getFunction
(
"__cxa_begin_catch"
);
auto
begin_catch_func
=
g
.
cur_module
->
getOrInsertFunction
(
std_module_catch
->
getName
(),
std_module_catch
->
getFunctionType
());
assert
(
begin_catch_func
);
// The interpreter can't really support the full C++ exception handling model since it's
// itself written in C++. Let's make it easier for the interpreter and use a simpler interface:
llvm
::
Value
*
exc_obj
=
emitter
.
getBuilder
()
->
CreateBitCast
(
cxaexc_pointer
,
g
.
llvm_value_type_ptr
);
}
llvm
::
Value
*
excinfo_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
begin_catch_func
,
cxaexc_pointer
);
llvm
::
Value
*
excinfo_pointer_casted
=
emitter
.
getBuilder
()
->
CreateBitCast
(
excinfo_pointer
,
g
.
llvm_excinfo_type
->
getPointerTo
());
auto
*
builder
=
emitter
.
getBuilder
();
llvm
::
Value
*
exc_type
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
0
));
llvm
::
Value
*
exc_value
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
1
));
llvm
::
Value
*
exc_traceback
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
2
));
assert
(
exc_type
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_value
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_traceback
->
getType
()
==
g
.
llvm_value_type_ptr
);
return
makeTuple
({
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_type
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_value
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_traceback
,
true
)
});
}
case
AST_LangPrimitive
:
:
LOCALS
:
{
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
irstate
->
getBoxedLocalsVar
(),
true
);
...
...
@@ -986,7 +974,7 @@ private:
if
(
node
->
id
.
s
()
==
"None"
)
return
getNone
();
bool
do_patchpoint
=
ENABLE_ICGETGLOBALS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICGETGLOBALS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetGlobalIC
(
getOpInfoForNode
(
node
,
unw_info
).
getTypeRecorder
());
...
...
@@ -1657,7 +1645,7 @@ private:
// TODO add a CompilerVariable::setattr, which can (similar to getitem)
// statically-resolve the function if possible, and only fall back to
// patchpoints if it couldn't.
bool
do_patchpoint
=
ENABLE_ICSETITEMS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICSETITEMS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createSetitemIC
(
getEmptyOpInfo
(
unw_info
).
getTypeRecorder
());
...
...
@@ -1783,7 +1771,7 @@ private:
tget
->
decvref
(
emitter
);
slice
->
decvref
(
emitter
);
bool
do_patchpoint
=
ENABLE_ICDELITEMS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICDELITEMS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createDelitemIC
(
getEmptyOpInfo
(
unw_info
).
getTypeRecorder
());
...
...
@@ -1955,12 +1943,6 @@ private:
CompilerVariable
*
val
;
if
(
node
->
value
==
NULL
)
{
if
(
irstate
->
getReturnType
()
==
VOID
)
{
endBlock
(
DEAD
);
emitter
.
getBuilder
()
->
CreateRetVoid
();
return
;
}
val
=
getNone
();
}
else
{
val
=
evalExpr
(
node
->
value
,
unw_info
);
...
...
@@ -2051,8 +2033,8 @@ private:
// Emitting the actual OSR:
emitter
.
getBuilder
()
->
SetInsertPoint
(
onramp
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
irstate
->
getC
urFunction
(),
osr_key
);
OSRExit
*
exit
=
new
OSRExit
(
irstate
->
getCurFunction
(),
entry
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
irstate
->
getC
L
(),
osr_key
);
OSRExit
*
exit
=
new
OSRExit
(
entry
);
llvm
::
Value
*
partial_func
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
compilePartialFunc
,
embedRelocatablePtr
(
exit
,
g
.
i8
->
getPointerTo
()));
...
...
@@ -2185,10 +2167,7 @@ private:
converted_args
[
i
]
->
decvref
(
emitter
);
}
if
(
irstate
->
getReturnType
()
==
VOID
)
emitter
.
getBuilder
()
->
CreateRetVoid
();
else
emitter
.
getBuilder
()
->
CreateRet
(
rtn
);
emitter
.
getBuilder
()
->
CreateRet
(
rtn
);
emitter
.
getBuilder
()
->
SetInsertPoint
(
starting_block
);
}
...
...
src/codegen/irgen/irgenerator.h
View file @
caa84b81
...
...
@@ -54,6 +54,9 @@ extern const std::string FRAME_INFO_PTR_NAME;
// TODO this probably shouldn't be here
class
IRGenState
{
private:
// Note: due to some not-yet-fixed behavior, cf->clfunc is NULL will only get set to point
// to clfunc at the end of irgen.
CLFunction
*
clfunc
;
CompiledFunction
*
cf
;
SourceInfo
*
source_info
;
std
::
unique_ptr
<
PhiAnalysis
>
phis
;
...
...
@@ -69,11 +72,12 @@ private:
public:
IRGenState
(
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
IRGenState
(
C
LFunction
*
clfunc
,
C
ompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
);
~
IRGenState
();
CompiledFunction
*
getCurFunction
()
{
return
cf
;
}
CLFunction
*
getCL
()
{
return
clfunc
;
}
llvm
::
Function
*
getLLVMFunction
()
{
return
cf
->
func
;
}
...
...
src/codegen/osrentry.h
View file @
caa84b81
...
...
@@ -31,26 +31,25 @@ struct StackMap;
class
OSREntryDescriptor
{
private:
OSREntryDescriptor
(
C
ompiledFunction
*
from_cf
,
AST_Jump
*
backedge
)
:
cf
(
from_cf
),
backedge
(
backedge
)
{
}
OSREntryDescriptor
(
C
LFunction
*
clfunc
,
AST_Jump
*
backedge
)
:
clfunc
(
clfunc
),
backedge
(
backedge
)
{
assert
(
clfunc
);
}
public:
C
ompiledFunction
*
const
cf
;
C
LFunction
*
clfunc
;
AST_Jump
*
const
backedge
;
typedef
std
::
map
<
InternedString
,
ConcreteCompilerType
*>
ArgMap
;
ArgMap
args
;
static
OSREntryDescriptor
*
create
(
C
ompiledFunction
*
from_cf
,
AST_Jump
*
backedge
)
{
return
new
OSREntryDescriptor
(
from_cf
,
backedge
);
static
OSREntryDescriptor
*
create
(
C
LFunction
*
clfunc
,
AST_Jump
*
backedge
)
{
return
new
OSREntryDescriptor
(
clfunc
,
backedge
);
}
};
class
OSRExit
{
private:
public:
CompiledFunction
*
const
parent_cf
;
const
OSREntryDescriptor
*
entry
;
OSRExit
(
CompiledFunction
*
parent_cf
,
const
OSREntryDescriptor
*
entry
)
:
parent_cf
(
parent_cf
),
entry
(
entry
)
{}
OSRExit
(
const
OSREntryDescriptor
*
entry
)
:
entry
(
entry
)
{}
};
}
...
...
src/codegen/patchpoints.cpp
View file @
caa84b81
...
...
@@ -143,15 +143,6 @@ static std::unordered_set<int> extractLiveOuts(StackMap::Record* r, llvm::Callin
}
void
processStackmap
(
CompiledFunction
*
cf
,
StackMap
*
stackmap
)
{
// FIXME: this is pretty hacky, that we don't delete the patchpoints here.
// We need them currently for the llvm interpreter.
// Eventually we'll get rid of that and use an AST interpreter, and then we won't need this hack.
if
(
cf
->
effort
==
EffortLevel
::
INTERPRETED
)
{
assert
(
!
stackmap
);
new_patchpoints
.
clear
();
return
;
}
int
nrecords
=
stackmap
?
stackmap
->
records
.
size
()
:
0
;
assert
(
cf
->
location_map
==
NULL
);
...
...
src/codegen/patchpoints.h
View file @
caa84b81
...
...
@@ -135,10 +135,14 @@ public:
bool
hasReturnValue
()
const
{
return
has_return_value
;
}
llvm
::
CallingConv
::
ID
getCallingConvention
()
const
{
// FIXME: we currently have some issues with using PreserveAll (the rewriter currently
// does not completely preserve live outs), so disable it temporarily.
#if 0
// The plan is to switch probably everything over to PreseveAll (and potentially AnyReg),
// but for only switch Getattr so the testing can be localized:
if (type == Getattr || type == Setattr)
return llvm::CallingConv::PreserveAll;
#endif
return
llvm
::
CallingConv
::
C
;
}
...
...
src/codegen/unwinding.cpp
View file @
caa84b81
...
...
@@ -276,6 +276,9 @@ struct PythonFrameId {
class
PythonFrameIteratorImpl
{
public:
PythonFrameId
id
;
CLFunction
*
cl
;
// always exists
// These only exist if id.type==COMPILED:
CompiledFunction
*
cf
;
// We have to save a copy of the regs since it's very difficult to keep the unw_context_t
// structure valid.
...
...
@@ -284,15 +287,26 @@ public:
PythonFrameIteratorImpl
()
:
regs_valid
(
0
)
{}
PythonFrameIteratorImpl
(
PythonFrameId
::
FrameType
type
,
uint64_t
ip
,
uint64_t
bp
,
CompiledFunction
*
cf
)
:
id
(
PythonFrameId
(
type
,
ip
,
bp
)),
cf
(
cf
),
regs_valid
(
0
)
{}
PythonFrameIteratorImpl
(
PythonFrameId
::
FrameType
type
,
uint64_t
ip
,
uint64_t
bp
,
CLFunction
*
cl
,
CompiledFunction
*
cf
)
:
id
(
PythonFrameId
(
type
,
ip
,
bp
)),
cl
(
cl
),
cf
(
cf
),
regs_valid
(
0
)
{
assert
(
cl
);
assert
((
type
==
PythonFrameId
::
COMPILED
)
==
(
cf
!=
NULL
));
}
CompiledFunction
*
getCF
()
const
{
assert
(
cf
);
return
cf
;
}
CLFunction
*
getCL
()
const
{
assert
(
cl
);
return
cl
;
}
uint64_t
readLocation
(
const
StackMap
::
Record
::
Location
&
loc
)
{
assert
(
id
.
type
==
PythonFrameId
::
COMPILED
);
if
(
loc
.
type
==
StackMap
::
Record
::
Location
::
LocationType
::
Register
)
{
// TODO: need to make sure we deal with patchpoints appropriately
return
getReg
(
loc
.
regnum
);
...
...
@@ -412,6 +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
inline
unw_word_t
get_cursor_reg
(
unw_cursor_t
*
cursor
,
int
reg
)
{
unw_word_t
v
;
...
...
@@ -430,18 +449,16 @@ static inline unw_word_t get_cursor_bp(unw_cursor_t* cursor) {
// frame information through the PythonFrameIteratorImpl* info arg.
bool
frameIsPythonFrame
(
unw_word_t
ip
,
unw_word_t
bp
,
unw_cursor_t
*
cursor
,
PythonFrameIteratorImpl
*
info
)
{
CompiledFunction
*
cf
=
getCFForAddress
(
ip
);
CLFunction
*
cl
=
cf
?
cf
->
clfunc
:
NULL
;
bool
jitted
=
cf
!=
NULL
;
if
(
!
cf
)
{
if
(
inASTInterpreterExecuteInner
(
ip
))
{
cf
=
getCFForInterpretedFrame
((
void
*
)
bp
);
assert
(
cf
);
}
}
bool
interpreted
=
!
jitted
&&
inASTInterpreterExecuteInner
(
ip
);
if
(
interpreted
)
cl
=
getCLForInterpretedFrame
((
void
*
)
bp
);
if
(
!
cf
)
if
(
!
jitted
&&
!
interpreted
)
return
false
;
*
info
=
PythonFrameIteratorImpl
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
cf
);
*
info
=
PythonFrameIteratorImpl
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
c
l
,
c
f
);
if
(
jitted
)
{
// Try getting all the callee-save registers, and save the ones we were able to get.
// Some of them may be inaccessible, I think because they weren't defined by that
...
...
@@ -576,10 +593,10 @@ void throwingException(PythonUnwindSession* unwind) {
static
const
LineInfo
lineInfoForFrame
(
PythonFrameIteratorImpl
*
frame_it
)
{
AST_stmt
*
current_stmt
=
frame_it
->
getCurrentStatement
();
auto
*
c
f
=
frame_it
->
getCF
();
assert
(
c
f
);
auto
*
c
l
=
frame_it
->
getCL
();
assert
(
c
l
);
auto
source
=
c
f
->
clfunc
->
source
.
get
();
auto
source
=
c
l
->
source
.
get
();
return
LineInfo
(
current_stmt
->
lineno
,
current_stmt
->
col_offset
,
source
->
fn
,
source
->
getName
());
}
...
...
@@ -609,12 +626,16 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
unw_word_t
bp
=
get_cursor_bp
(
cursor
);
PythonFrameIteratorImpl
frame_iter
;
if
(
frameIsPythonFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
if
(
inDeopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
if
(
!
unwind_session
->
shouldSkipFrame
())
unwind_session
->
addTraceback
(
lineInfoForFrame
(
&
frame_iter
));
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
unwind_session
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
);
bool
was_osr
=
(
frame_iter
.
getId
().
type
==
PythonFrameId
::
COMPILED
)
&&
(
frame_iter
.
cf
->
entry_descriptor
);
unwind_session
->
setShouldSkipNextFrame
(
was_osr
);
}
}
...
...
@@ -641,16 +662,21 @@ template <typename Func> void unwindPythonStack(Func func) {
unw_word_t
ip
=
get_cursor_ip
(
&
cursor
);
unw_word_t
bp
=
get_cursor_bp
(
&
cursor
);
// TODO: this should probably just call unwindingThroughFrame?
bool
stop_unwinding
=
false
;
PythonFrameIteratorImpl
frame_iter
;
if
(
frameIsPythonFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
if
(
inDeopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
if
(
!
unwind_session
->
shouldSkipFrame
())
stop_unwinding
=
func
(
&
frame_iter
);
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
unwind_session
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
);
bool
was_osr
=
(
frame_iter
.
getId
().
type
==
PythonFrameId
::
COMPILED
)
&&
(
frame_iter
.
cf
->
entry_descriptor
);
unwind_session
->
setShouldSkipNextFrame
(
was_osr
);
}
if
(
stop_unwinding
)
...
...
@@ -791,11 +817,11 @@ ExcInfo* getFrameExcInfo() {
return
cur_exc
;
}
C
ompiledFunction
*
getTopCompiled
Function
()
{
C
LFunction
*
getTopPython
Function
()
{
auto
rtn
=
getTopPythonFrame
();
if
(
!
rtn
)
return
NULL
;
return
getTopPythonFrame
()
->
getC
F
();
return
getTopPythonFrame
()
->
getC
L
();
}
Box
*
getGlobals
()
{
...
...
@@ -810,10 +836,10 @@ Box* getGlobalsDict() {
}
BoxedModule
*
getCurrentModule
()
{
C
ompiledFunction
*
compiledFunction
=
getTopCompiled
Function
();
if
(
!
c
ompiledFunction
)
C
LFunction
*
clfunc
=
getTopPython
Function
();
if
(
!
c
lfunc
)
return
NULL
;
return
c
ompiledFunction
->
c
lfunc
->
source
->
parent_module
;
return
clfunc
->
source
->
parent_module
;
}
PythonFrameIterator
getPythonFrame
(
int
depth
)
{
...
...
@@ -844,11 +870,11 @@ PythonFrameIterator::PythonFrameIterator(std::unique_ptr<PythonFrameIteratorImpl
std
::
swap
(
this
->
impl
,
impl
);
}
// TODO factor get
StackLocalsIncludingUserHidden
and fastLocalsToBoxedLocals
// TODO factor get
DeoptState
and fastLocalsToBoxedLocals
// because they are pretty ugly but have a pretty repetitive pattern.
FrameStackState
getFrameStack
State
()
{
FrameStackState
rtn
(
NULL
,
NULL
)
;
DeoptState
getDeopt
State
()
{
DeoptState
rtn
;
bool
found
=
false
;
unwindPythonStack
([
&
](
PythonFrameIteratorImpl
*
frame_iter
)
{
BoxedDict
*
d
;
...
...
@@ -917,7 +943,9 @@ FrameStackState getFrameStackState() {
abort
();
}
rtn
=
FrameStackState
(
d
,
frame_iter
->
getFrameInfo
());
rtn
.
frame_state
=
FrameStackState
(
d
,
frame_iter
->
getFrameInfo
());
rtn
.
cf
=
cf
;
rtn
.
current_stmt
=
frame_iter
->
getCurrentStatement
();
found
=
true
;
return
true
;
});
...
...
@@ -937,17 +965,18 @@ Box* PythonFrameIterator::fastLocalsToBoxedLocals() {
BoxedClosure
*
closure
;
FrameInfo
*
frame_info
;
C
ompiledFunction
*
cf
=
impl
->
getCF
();
ScopeInfo
*
scope_info
=
c
f
->
c
lfunc
->
source
->
getScopeInfo
();
C
LFunction
*
clfunc
=
impl
->
getCL
();
ScopeInfo
*
scope_info
=
clfunc
->
source
->
getScopeInfo
();
if
(
scope_info
->
areLocalsFromModule
())
{
// TODO we should cache this in frame_info->locals or something so that locals()
// (and globals() too) will always return the same dict
RELEASE_ASSERT
(
c
f
->
c
lfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
""
);
return
c
f
->
c
lfunc
->
source
->
parent_module
->
getAttrWrapper
();
RELEASE_ASSERT
(
clfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
""
);
return
clfunc
->
source
->
parent_module
->
getAttrWrapper
();
}
if
(
impl
->
getId
().
type
==
PythonFrameId
::
COMPILED
)
{
CompiledFunction
*
cf
=
impl
->
getCF
();
d
=
new
BoxedDict
();
uint64_t
ip
=
impl
->
getId
().
ip
;
...
...
@@ -1081,24 +1110,18 @@ Box* PythonFrameIterator::fastLocalsToBoxedLocals() {
return
frame_info
->
boxedLocals
;
}
ExecutionPoint
getExecutionPoint
()
{
auto
frame
=
getTopPythonFrame
();
auto
cf
=
frame
->
getCF
();
auto
current_stmt
=
frame
->
getCurrentStatement
();
return
ExecutionPoint
({.
cf
=
cf
,
.
current_stmt
=
current_stmt
});
}
std
::
unique_ptr
<
ExecutionPoint
>
PythonFrameIterator
::
getExecutionPoint
()
{
assert
(
impl
.
get
());
auto
cf
=
impl
->
getCF
();
auto
stmt
=
impl
->
getCurrentStatement
();
return
std
::
unique_ptr
<
ExecutionPoint
>
(
new
ExecutionPoint
({.
cf
=
cf
,
.
current_stmt
=
stmt
}));
AST_stmt
*
PythonFrameIterator
::
getCurrentStatement
()
{
return
impl
->
getCurrentStatement
();
}
CompiledFunction
*
PythonFrameIterator
::
getCF
()
{
return
impl
->
getCF
();
}
CLFunction
*
PythonFrameIterator
::
getCL
()
{
return
impl
->
getCL
();
}
Box
*
PythonFrameIterator
::
getGlobalsDict
()
{
return
impl
->
getGlobalsDict
();
}
...
...
src/codegen/unwinding.h
View file @
caa84b81
...
...
@@ -51,11 +51,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
void
exceptionCaughtInInterpreter
(
LineInfo
line_info
,
ExcInfo
*
exc_info
);
struct
ExecutionPoint
{
CompiledFunction
*
cf
;
AST_stmt
*
current_stmt
;
};
ExecutionPoint
getExecutionPoint
();
CLFunction
*
getTopPythonFunction
();
// debugging/stat helper, returns python filename:linenumber, or "unknown:-1" if it fails
std
::
string
getCurrentPythonLine
();
...
...
@@ -73,9 +69,10 @@ private:
public:
CompiledFunction
*
getCF
();
CLFunction
*
getCL
();
FrameInfo
*
getFrameInfo
();
bool
exists
()
{
return
impl
.
get
()
!=
NULL
;
}
std
::
unique_ptr
<
ExecutionPoint
>
getExecutionPoi
nt
();
AST_stmt
*
getCurrentStateme
nt
();
Box
*
fastLocalsToBoxedLocals
();
Box
*
getGlobalsDict
();
...
...
@@ -114,13 +111,19 @@ struct FrameStackState {
// after the frame ends.
FrameInfo
*
frame_info
;
FrameStackState
()
{}
FrameStackState
(
BoxedDict
*
locals
,
FrameInfo
*
frame_info
)
:
locals
(
locals
),
frame_info
(
frame_info
)
{}
};
// Returns all the stack locals, including hidden ones.
FrameStackState
getFrameStackState
();
CompiledFunction
*
getTopCompiledFunction
();
struct
DeoptState
{
FrameStackState
frame_state
;
CompiledFunction
*
cf
;
AST_stmt
*
current_stmt
;
};
DeoptState
getDeoptState
();
}
#endif
src/core/cfg.cpp
View file @
caa84b81
...
...
@@ -2472,6 +2472,8 @@ void CFG::print() {
}
CFG
*
computeCFG
(
SourceInfo
*
source
,
std
::
vector
<
AST_stmt
*>
body
)
{
STAT_TIMER
(
t0
,
"us_timer_computecfg"
,
0
);
CFG
*
rtn
=
new
CFG
();
ScopingAnalysis
*
scoping_analysis
=
source
->
scoping
;
...
...
src/core/types.h
View file @
caa84b81
...
...
@@ -64,7 +64,6 @@ public:
using
gc
::
GCVisitor
;
enum
class
EffortLevel
{
INTERPRETED
=
0
,
MODERATE
=
2
,
MAXIMAL
=
3
,
};
...
...
@@ -74,8 +73,8 @@ template <class V> class ValuedCompilerType;
typedef
ValuedCompilerType
<
llvm
::
Value
*>
ConcreteCompilerType
;
ConcreteCompilerType
*
typeFromClass
(
BoxedClass
*
);
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
LONG
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
VOID
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
FROZENSET
,
*
CLOSURE
,
*
GENERATOR
,
*
BOXED_COMPLEX
,
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
LONG
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
FROZENSET
,
*
CLOSURE
,
*
GENERATOR
,
*
BOXED_COMPLEX
,
*
FRAME_INFO
;
extern
CompilerType
*
UNDEF
;
...
...
@@ -229,7 +228,6 @@ public:
llvm
::
Function
*
func
;
// the llvm IR object
FunctionSpecialization
*
spec
;
const
OSREntryDescriptor
*
entry_descriptor
;
bool
is_interpreted
;
union
{
Box
*
(
*
call
)(
Box
*
,
Box
*
,
Box
*
,
Box
**
);
...
...
@@ -246,13 +244,12 @@ public:
int64_t
times_called
,
times_speculation_failed
;
ICInvalidator
dependent_callsites
;
LocationMap
*
location_map
;
// only meaningful if this is a compiled frame
LocationMap
*
location_map
;
std
::
vector
<
ICInfo
*>
ics
;
std
::
vector
<
std
::
unique_ptr
<
JitCodeBlock
>>
code_blocks
;
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
bool
is_interpreted
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
);
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
);
ConcreteCompilerType
*
getReturnType
();
...
...
@@ -322,6 +319,11 @@ public:
// Please use codeForFunction() to access this:
BoxedCode
*
code_obj
;
// For use by the interpreter/baseline jit:
int
times_interpreted
;
std
::
vector
<
std
::
unique_ptr
<
JitCodeBlock
>>
code_blocks
;
ICInvalidator
dependent_interp_callsites
;
// Functions can provide an "internal" version, which will get called instead
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
...
...
@@ -331,22 +333,9 @@ public:
InternalCallable
internal_callable
=
NULL
;
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
std
::
unique_ptr
<
SourceInfo
>
source
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
std
::
move
(
source
)),
param_names
(
this
->
source
->
ast
,
this
->
source
->
getInternedStrings
()),
always_use_version
(
NULL
),
code_obj
(
NULL
)
{
assert
(
num_args
>=
num_defaults
);
}
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
nullptr
),
param_names
(
param_names
),
always_use_version
(
NULL
),
code_obj
(
NULL
)
{
assert
(
num_args
>=
num_defaults
);
}
std
::
unique_ptr
<
SourceInfo
>
source
);
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
);
~
CLFunction
();
int
numReceivedArgs
()
{
return
paramspec
.
totalReceived
();
}
...
...
@@ -354,7 +343,7 @@ public:
assert
(
compiled
);
assert
((
compiled
->
spec
!=
NULL
)
+
(
compiled
->
entry_descriptor
!=
NULL
)
==
1
);
assert
(
compiled
->
clfunc
==
NULL
);
assert
(
compiled
->
is_interpreted
==
(
compiled
->
code
==
NULL
)
);
assert
(
compiled
->
code
);
compiled
->
clfunc
=
this
;
if
(
compiled
->
entry_descriptor
==
NULL
)
{
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
caa84b81
...
...
@@ -849,7 +849,7 @@ Box* execfile(Box* _fn) {
// Run directly inside the current module:
AST_Module
*
ast
=
caching_parse_file
(
fn
->
data
());
ASSERT
(
get
ExecutionPoint
().
cf
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
"need to pass custom globals in"
);
ASSERT
(
get
TopPythonFunction
()
->
source
->
scoping
->
areGlobalsFromModule
(),
"need to pass custom globals in"
);
compileAndRunModule
(
ast
,
getCurrentModule
());
return
None
;
...
...
src/runtime/frame.cpp
View file @
caa84b81
...
...
@@ -121,8 +121,8 @@ public:
static
Box
*
lineno
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
std
::
unique_ptr
<
ExecutionPoint
>
fr
=
f
->
it
.
getExecutionPoi
nt
();
return
boxInt
(
fr
->
current_
stmt
->
lineno
);
AST_stmt
*
stmt
=
f
->
it
.
getCurrentStateme
nt
();
return
boxInt
(
stmt
->
lineno
);
}
DEFAULT_CLASS
(
frame_cls
);
...
...
@@ -130,11 +130,11 @@ public:
static
Box
*
boxFrame
(
PythonFrameIterator
it
)
{
FrameInfo
*
fi
=
it
.
getFrameInfo
();
if
(
fi
->
frame_obj
==
NULL
)
{
auto
c
f
=
it
.
getCF
();
auto
c
l
=
it
.
getCL
();
Box
*
globals
=
it
.
getGlobalsDict
();
BoxedFrame
*
f
=
fi
->
frame_obj
=
new
BoxedFrame
(
std
::
move
(
it
));
f
->
_globals
=
globals
;
f
->
_code
=
codeForCLFunction
(
c
f
->
clfunc
);
f
->
_code
=
codeForCLFunction
(
c
l
);
}
return
fi
->
frame_obj
;
...
...
src/runtime/objmodel.cpp
View file @
caa84b81
...
...
@@ -162,20 +162,19 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) {
RELEASE_ASSERT
(
0
,
"deopt is currently broken..."
);
FrameStackState
frame_state
=
getFrameStackState
();
auto
execution_point
=
getExecutionPoint
();
auto
deopt_state
=
getDeoptState
();
// Should we only do this selectively?
execution_point
.
cf
->
speculationFailed
();
deopt_state
.
cf
->
speculationFailed
();
// Except of exc.type we skip initializing the exc fields inside the JITed code path (small perf improvement) that's
// why we have todo it now if we didn't set an exception (which sets all fields)
if
(
frame_state
.
frame_info
->
exc
.
type
==
NULL
)
{
frame_state
.
frame_info
->
exc
.
traceback
=
NULL
;
frame_state
.
frame_info
->
exc
.
value
=
NULL
;
if
(
deopt_state
.
frame_state
.
frame_info
->
exc
.
type
==
NULL
)
{
deopt_state
.
frame_state
.
frame_info
->
exc
.
traceback
=
NULL
;
deopt_state
.
frame_state
.
frame_info
->
exc
.
value
=
NULL
;
}
return
astInterpretFrom
(
execution_point
.
cf
,
expr
,
execution_point
.
current_stmt
,
value
,
frame_state
);
return
astInterpretFrom
(
deopt_state
.
cf
->
clfunc
,
expr
,
deopt_state
.
current_stmt
,
value
,
deopt_state
.
frame_state
);
}
extern
"C"
bool
softspace
(
Box
*
b
,
bool
newval
)
{
...
...
@@ -2662,16 +2661,12 @@ extern "C" void dumpEx(void* p, int levels) {
printf
(
"Has %ld function versions
\n
"
,
cl
->
versions
.
size
());
for
(
CompiledFunction
*
cf
:
cl
->
versions
)
{
if
(
cf
->
is_interpreted
)
{
printf
(
"[interpreted]
\n
"
);
}
else
{
bool
got_name
;
std
::
string
name
=
g
.
func_addr_registry
.
getFuncNameAtAddress
(
cf
->
code
,
true
,
&
got_name
);
if
(
got_name
)
printf
(
"%s
\n
"
,
name
.
c_str
());
else
printf
(
"%p
\n
"
,
cf
->
code
);
}
bool
got_name
;
std
::
string
name
=
g
.
func_addr_registry
.
getFuncNameAtAddress
(
cf
->
code
,
true
,
&
got_name
);
if
(
got_name
)
printf
(
"%s
\n
"
,
name
.
c_str
());
else
printf
(
"%p
\n
"
,
cf
->
code
);
}
}
...
...
@@ -2930,26 +2925,7 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
abort
();
}
EffortLevel
new_effort
=
initialEffort
();
// Only the interpreter currently supports non-module-globals:
if
(
!
f
->
source
->
scoping
->
areGlobalsFromModule
())
new_effort
=
EffortLevel
::
INTERPRETED
;
std
::
vector
<
ConcreteCompilerType
*>
arg_types
;
for
(
int
i
=
0
;
i
<
num_output_args
;
i
++
)
{
if
(
new_effort
==
EffortLevel
::
INTERPRETED
)
{
arg_types
.
push_back
(
UNKNOWN
);
}
else
{
Box
*
arg
=
getArg
(
i
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
assert
(
arg
);
// only builtin functions can pass NULL args
arg_types
.
push_back
(
typeFromClass
(
arg
->
cls
));
}
}
FunctionSpecialization
*
spec
=
new
FunctionSpecialization
(
UNKNOWN
,
arg_types
);
// this also pushes the new CompiledVersion to the back of the version list:
return
compileFunction
(
f
,
spec
,
new_effort
,
NULL
);
return
NULL
;
}
static
llvm
::
StringRef
getFunctionName
(
CLFunction
*
f
)
{
...
...
@@ -3500,7 +3476,7 @@ static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, Box
// This function exists for the rewriter: astInterpretFunction takes 9 args, but the rewriter
// only supports calling functions with at most 6 since it can currently only pass arguments
// in registers.
static
Box
*
astInterpretHelper
(
C
ompiled
Function
*
f
,
int
num_args
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
static
Box
*
astInterpretHelper
(
C
L
Function
*
f
,
int
num_args
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
Box
*
globals
,
Box
**
_args
)
{
Box
*
arg1
=
_args
[
0
];
Box
*
arg2
=
_args
[
1
];
...
...
@@ -3514,16 +3490,15 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
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
)
{
if
(
!
chosen_cf
)
{
if
(
rewrite_args
)
{
rewrite_args
->
rewriter
->
addDependenceOn
(
chosen_cf
->
dependent_callsites
);
RewriterVar
::
SmallVector
arg_vec
;
rewrite_args
->
rewriter
->
addDependenceOn
(
f
->
dependent_interp_callsites
);
// TODO this kind of embedded reference needs to be tracked by the GC somehow?
// Or maybe it's ok, since we've guarded on the function object?
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
chosen_c
f
,
Location
::
forArg
(
0
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
f
,
Location
::
forArg
(
0
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
num_output_args
,
Location
::
forArg
(
1
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
closure
,
Location
::
forArg
(
2
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
generator
,
Location
::
forArg
(
3
)));
...
...
@@ -3531,6 +3506,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
// Hacky workaround: the rewriter can only pass arguments in registers, so use this helper function
// to unpack some of the additional arguments:
// TODO if there's only one arg we could just pass it normally
RewriterVar
*
arg_array
=
rewrite_args
->
rewriter
->
allocate
(
4
);
arg_vec
.
push_back
(
arg_array
);
if
(
num_output_args
>=
1
)
...
...
@@ -3546,8 +3522,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
rewrite_args
->
out_success
=
true
;
}
return
astInterpretFunction
(
chosen_cf
,
num_output_args
,
closure
,
generator
,
globals
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
return
astInterpretFunction
(
f
,
num_output_args
,
closure
,
generator
,
globals
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
ASSERT
(
!
globals
,
"need to update the calling conventions if we want to pass globals"
);
...
...
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