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
b1927655
Commit
b1927655
authored
May 28, 2016
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DefinednessAnalysis uses vectors internally now
parent
742dc66c
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
130 additions
and
59 deletions
+130
-59
Makefile
Makefile
+1
-1
src/analysis/fpc.h
src/analysis/fpc.h
+16
-17
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+36
-33
src/analysis/function_analysis.h
src/analysis/function_analysis.h
+44
-6
src/core/ast.h
src/core/ast.h
+2
-0
src/core/cfg.cpp
src/core/cfg.cpp
+14
-2
test/tests/name_scopes.py
test/tests/name_scopes.py
+17
-0
No files found.
Makefile
View file @
b1927655
...
...
@@ -337,7 +337,7 @@ STDOBJECT_SRCS := \
iterobject.c
\
bufferobject.c
\
cobject.c
\
d
ictproxy
.c
\
d
escrobject
.c
\
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS
:=
\
...
...
src/analysis/fpc.h
View file @
b1927655
...
...
@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "analysis/function_analysis.h"
#include "core/cfg.h"
#include "core/common.h"
#include "core/options.h"
...
...
@@ -29,7 +30,7 @@ namespace pyston {
template
<
typename
T
>
class
BBAnalyzer
{
public:
typedef
llvm
::
DenseMap
<
InternedString
,
T
>
Map
;
typedef
VRegMap
<
T
>
Map
;
typedef
llvm
::
DenseMap
<
CFGBlock
*
,
Map
>
AllMap
;
virtual
~
BBAnalyzer
()
{}
...
...
@@ -56,10 +57,12 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
assert
(
!
starting_states
.
size
());
assert
(
!
ending_states
.
size
());
int
num_vregs
=
initial_map
.
numVregs
();
llvm
::
SmallPtrSet
<
CFGBlock
*
,
32
>
in_queue
;
std
::
priority_queue
<
CFGBlock
*
,
llvm
::
SmallVector
<
CFGBlock
*
,
32
>
,
CFGBlockMinIndex
>
q
;
starting_states
.
insert
(
make_pair
(
initial_block
,
std
::
move
(
initial_map
)));
starting_states
.
insert
(
std
::
make_pair
(
initial_block
,
std
::
move
(
initial_map
)));
q
.
push
(
initial_block
);
in_queue
.
insert
(
initial_block
);
...
...
@@ -70,9 +73,10 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
q
.
pop
();
in_queue
.
erase
(
block
);
Map
&
initial
=
starting_states
[
block
];
assert
(
starting_states
.
count
(
block
));
Map
&
initial
=
starting_states
.
find
(
block
)
->
second
;
if
(
VERBOSITY
(
"analysis"
)
>=
2
)
printf
(
"fpc on block %d - %d entries
\n
"
,
block
->
idx
,
initial
.
size
());
printf
(
"fpc on block %d - %d entries
\n
"
,
block
->
idx
,
initial
.
numVregs
());
Map
ending
=
Map
(
initial
);
...
...
@@ -87,20 +91,17 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
initial
=
true
;
}
Map
&
next
=
starting_states
[
next_block
];
auto
it
=
starting_states
.
find
(
next_block
);
if
(
it
==
starting_states
.
end
())
it
=
starting_states
.
insert
(
std
::
make_pair
(
next_block
,
Map
(
num_vregs
))).
first
;
Map
&
next
=
it
->
second
;
// merge ending->next
for
(
const
auto
&
p
:
ending
)
{
bool
existed
=
next
.
count
(
p
.
first
);
T
&
next_elt
=
next
[
p
.
first
];
T
new_elt
=
analyzer
.
merge
(
p
.
second
,
next_elt
);
if
(
!
existed
)
{
assert
(
new_elt
!=
next_elt
);
if
(
initial
)
assert
(
new_elt
==
p
.
second
);
}
if
(
next_elt
!=
new_elt
)
{
next_elt
=
new_elt
;
changed
=
true
;
...
...
@@ -108,10 +109,7 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
}
#ifndef NDEBUG
for
(
const
auto
&
p
:
next
)
{
assert
(
ending
.
count
(
p
.
first
));
}
assert
(
next
.
size
()
==
ending
.
size
());
assert
(
next
.
numVregs
()
==
ending
.
numVregs
());
#endif
if
(
changed
&&
in_queue
.
insert
(
next_block
).
second
)
{
...
...
@@ -119,7 +117,8 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
}
}
ending_states
[
block
]
=
std
::
move
(
ending
);
ending_states
.
erase
(
block
);
ending_states
.
insert
(
std
::
make_pair
(
block
,
std
::
move
(
ending
)));
}
if
(
VERBOSITY
(
"analysis"
))
{
...
...
src/analysis/function_analysis.cpp
View file @
b1927655
...
...
@@ -243,9 +243,9 @@ private:
typedef
DefinednessBBAnalyzer
::
Map
Map
;
Map
&
state
;
void
_doSet
(
InternedString
s
)
{
ASSERT
(
state
.
count
(
s
),
"%s"
,
s
.
c_str
());
state
[
s
]
=
DefinednessAnalysis
::
Defined
;
void
_doSet
(
int
vreg
)
{
assert
(
vreg
>=
0
&&
vreg
<
state
.
numVregs
());
state
[
vreg
]
=
DefinednessAnalysis
::
Defined
;
}
void
_doSet
(
AST
*
t
)
{
...
...
@@ -258,12 +258,10 @@ private:
if
(
name
->
lookup_type
==
ScopeInfo
::
VarScopeType
::
FAST
||
name
->
lookup_type
==
ScopeInfo
::
VarScopeType
::
CLOSURE
)
{
assert
(
name
->
vreg
!=
-
1
);
assert
(
state
.
count
(
name
->
id
));
_doSet
(
name
->
id
);
_doSet
(
name
->
vreg
);
}
else
if
(
name
->
lookup_type
==
ScopeInfo
::
VarScopeType
::
GLOBAL
||
name
->
lookup_type
==
ScopeInfo
::
VarScopeType
::
NAME
)
{
assert
(
name
->
vreg
==
-
1
);
assert
(
!
state
.
count
(
name
->
id
));
// skip
}
else
{
RELEASE_ASSERT
(
0
,
"%d"
,
name
->
lookup_type
);
...
...
@@ -304,8 +302,8 @@ public:
AST_Name
*
name
=
ast_cast
<
AST_Name
>
(
t
);
if
(
name
->
lookup_type
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
&&
name
->
lookup_type
!=
ScopeInfo
::
VarScopeType
::
NAME
)
{
ASSERT
(
state
.
count
(
name
->
id
),
"%s"
,
name
->
id
.
c_str
()
);
state
[
name
->
id
]
=
DefinednessAnalysis
::
Undefined
;
assert
(
name
->
vreg
!=
-
1
);
state
[
name
->
vreg
]
=
DefinednessAnalysis
::
Undefined
;
}
}
else
{
// The CFG pass should reduce all deletes to the "basic" deletes on names/attributes/subscripts.
...
...
@@ -318,21 +316,23 @@ public:
}
virtual
bool
visit_classdef
(
AST_ClassDef
*
node
)
{
_doSet
(
node
->
name
);
assert
(
0
&&
"I think this isn't needed"
);
//_doSet(node->name);
return
true
;
}
virtual
bool
visit_functiondef
(
AST_FunctionDef
*
node
)
{
_doSet
(
node
->
name
);
assert
(
0
&&
"I think this isn't needed"
);
//_doSet(node->name);
return
true
;
}
virtual
bool
visit_alias
(
AST_alias
*
node
)
{
InternedString
name
=
node
->
name
;
int
vreg
=
node
->
name_vreg
;
if
(
node
->
asname
.
s
().
size
())
name
=
node
->
asname
;
vreg
=
node
->
asname_vreg
;
_doSet
(
name
);
_doSet
(
vreg
);
return
true
;
}
virtual
bool
visit_import
(
AST_Import
*
node
)
{
return
false
;
}
...
...
@@ -347,9 +347,9 @@ public:
virtual
bool
visit_arguments
(
AST_arguments
*
node
)
{
if
(
node
->
kwarg
.
s
().
size
())
_doSet
(
node
->
kwarg
);
_doSet
(
node
->
kwarg
_vreg
);
if
(
node
->
vararg
.
s
().
size
())
_doSet
(
node
->
vararg
);
_doSet
(
node
->
vararg
_vreg
);
for
(
int
i
=
0
;
i
<
node
->
args
.
size
();
i
++
)
{
_doSet
(
node
->
args
[
i
]);
}
...
...
@@ -371,7 +371,8 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
if
(
VERBOSITY
(
"analysis"
)
>=
3
)
{
printf
(
"At end of block %d:
\n
"
,
block
->
idx
);
for
(
const
auto
&
p
:
starting
)
{
printf
(
"%s: %d
\n
"
,
p
.
first
.
c_str
(),
p
.
second
);
if
(
p
.
second
!=
DefinednessAnalysis
::
Undefined
)
printf
(
"%s: %d
\n
"
,
block
->
cfg
->
getVRegInfo
().
getName
(
p
.
first
).
c_str
(),
p
.
second
);
}
}
}
...
...
@@ -388,33 +389,33 @@ void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
int
nvregs
=
vreg_info
.
getTotalNumOfVRegs
();
ASSERT
(
nvregs
==
initial_map
.
size
(),
"%d %d"
,
nvregs
,
initial_map
.
size
());
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
real_initial_map
(
nvregs
);
for
(
auto
&&
p
:
initial_map
)
{
// Run it through getVReg to make sure that the vreg exists
ASSERT
(
vreg_info
.
getVReg
(
p
.
first
)
>=
0
,
"%s"
,
p
.
first
.
c_str
());
real_initial_map
[
vreg_info
.
getVReg
(
p
.
first
)]
=
p
.
second
;
}
computeFixedPoint
(
std
::
move
(
initial_map
),
initial_block
,
DefinednessBBAnalyzer
(
scope_info
),
false
,
computeFixedPoint
(
std
::
move
(
real_
initial_map
),
initial_block
,
DefinednessBBAnalyzer
(
scope_info
),
false
,
defined_at_beginning
,
defined_at_end
);
for
(
const
auto
&
p
:
defined_at_end
)
{
assert
(
p
.
second
.
size
()
==
nvregs
);
assert
(
p
.
second
.
numVregs
()
==
nvregs
);
assert
(
!
defined_at_end_sets
.
count
(
p
.
first
));
RequiredSet
&
required
=
defined_at_end_sets
.
insert
(
std
::
make_pair
(
p
.
first
,
RequiredSet
(
nvregs
))).
first
->
second
;
//required.resize(nvregs, /* value= */ false);
//
required.resize(nvregs, /* value= */ false);
for
(
int
vreg
=
0
;
vreg
<
nvregs
;
vreg
++
)
{
// TODO shouldn't have to use name at all
InternedString
name
=
vreg_info
.
getName
(
vreg
);
#ifndef NDEBUG
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
name
);
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
&&
vst
!=
ScopeInfo
::
VarScopeType
::
NAME
);
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
vreg_info
.
getName
(
vreg
));
ASSERT
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
&&
vst
!=
ScopeInfo
::
VarScopeType
::
NAME
,
"%s"
,
vreg_info
.
getName
(
vreg
).
c_str
());
#endif
assert
(
p
.
second
.
count
(
name
));
auto
status
=
p
.
second
.
find
(
name
)
->
second
;
auto
status
=
p
.
second
[
vreg
];
// assert(p.second.count(name));
// auto status = p.second.find(name)->second;
assert
(
status
!=
DefinednessAnalysis
::
Unknown
);
if
(
status
!=
DefinednessAnalysis
::
Undefined
)
required
.
set
(
vreg
);
...
...
@@ -427,10 +428,9 @@ void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis
DefinednessAnalysis
::
DefinitionLevel
DefinednessAnalysis
::
isDefinedAtEnd
(
InternedString
name
,
CFGBlock
*
block
)
{
assert
(
defined_at_end
.
count
(
block
));
auto
&
map
=
defined_at_end
[
block
];
if
(
map
.
count
(
name
)
==
0
)
return
Undefined
;
return
map
[
name
];
auto
&&
map
=
defined_at_end
.
find
(
block
)
->
second
;
auto
cfg
=
block
->
cfg
;
return
map
[
cfg
->
getVRegInfo
().
getVReg
(
name
)];
}
const
DefinednessAnalysis
::
RequiredSet
&
DefinednessAnalysis
::
getDefinedNamesAtEnd
(
CFGBlock
*
block
)
{
...
...
@@ -528,8 +528,11 @@ bool PhiAnalysis::isPotentiallyUndefinedAfter(InternedString name, CFGBlock* blo
bool
PhiAnalysis
::
isPotentiallyUndefinedAt
(
InternedString
name
,
CFGBlock
*
block
)
{
assert
(
!
startswith
(
name
.
s
(),
"!"
));
auto
cfg
=
block
->
cfg
;
int
vreg
=
cfg
->
getVRegInfo
().
getVReg
(
name
);
assert
(
definedness
.
defined_at_beginning
.
count
(
block
));
return
definedness
.
defined_at_beginning
[
block
][
name
]
!=
DefinednessAnalysis
::
Defined
;
return
definedness
.
defined_at_beginning
.
find
(
block
)
->
second
[
vreg
]
!=
DefinednessAnalysis
::
Defined
;
}
std
::
unique_ptr
<
LivenessAnalysis
>
computeLivenessInfo
(
CFG
*
cfg
)
{
...
...
src/analysis/function_analysis.h
View file @
b1927655
...
...
@@ -81,9 +81,7 @@ public:
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
i
==
rhs
.
i
;
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
int
operator
*
()
{
return
i
;
}
int
operator
*
()
{
return
i
;
}
};
iterator
begin
()
const
{
...
...
@@ -94,9 +92,49 @@ public:
return
iterator
(
*
this
,
this
->
v
.
size
());
}
iterator
end
()
const
{
return
iterator
(
*
this
,
this
->
v
.
size
());
iterator
end
()
const
{
return
iterator
(
*
this
,
this
->
v
.
size
());
}
};
template
<
typename
T
>
class
VRegMap
{
private:
// TODO: switch just to a T*
std
::
vector
<
T
>
v
;
public:
VRegMap
(
int
num_vregs
)
:
v
(
num_vregs
)
{}
T
&
operator
[](
int
vreg
)
{
assert
(
vreg
>=
0
&&
vreg
<
v
.
size
());
return
v
[
vreg
];
}
const
T
&
operator
[](
int
vreg
)
const
{
assert
(
vreg
>=
0
&&
vreg
<
v
.
size
());
return
v
[
vreg
];
}
class
iterator
{
public:
const
VRegMap
<
T
>&
map
;
int
i
;
iterator
(
const
VRegMap
<
T
>&
map
,
int
i
)
:
map
(
map
),
i
(
i
)
{}
iterator
&
operator
++
()
{
i
++
;
return
*
this
;
}
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
i
==
rhs
.
i
;
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
std
::
pair
<
int
,
const
T
&>
operator
*
()
{
return
std
::
pair
<
int
,
const
T
&>
(
i
,
map
[
i
]);
}
};
int
numVregs
()
const
{
return
v
.
size
();
}
iterator
begin
()
const
{
return
iterator
(
*
this
,
0
);
}
iterator
end
()
const
{
return
iterator
(
*
this
,
this
->
v
.
size
());
}
};
class
DefinednessAnalysis
{
...
...
@@ -110,7 +148,7 @@ public:
typedef
VRegSet
RequiredSet
;
private:
llvm
::
DenseMap
<
CFGBlock
*
,
llvm
::
DenseMap
<
InternedString
,
DefinitionLevel
>>
defined_at_beginning
,
defined_at_end
;
llvm
::
DenseMap
<
CFGBlock
*
,
VRegMap
<
DefinitionLevel
>>
defined_at_beginning
,
defined_at_end
;
llvm
::
DenseMap
<
CFGBlock
*
,
RequiredSet
>
defined_at_end_sets
;
public:
...
...
src/core/ast.h
View file @
b1927655
...
...
@@ -217,6 +217,7 @@ public:
class
AST_alias
:
public
AST
{
public:
InternedString
name
,
asname
;
int
name_vreg
=
-
1
,
asname_vreg
=
-
1
;
virtual
void
accept
(
ASTVisitor
*
v
);
...
...
@@ -233,6 +234,7 @@ public:
// These are represented as strings, not names; not sure why.
// If they don't exist, the string is empty.
InternedString
kwarg
,
vararg
;
int
kwarg_vreg
=
-
1
,
vararg_vreg
=
-
1
;
virtual
void
accept
(
ASTVisitor
*
v
);
...
...
src/core/cfg.cpp
View file @
b1927655
...
...
@@ -1613,7 +1613,6 @@ public:
auto
tmp
=
nodeName
();
pushAssign
(
tmp
,
new
AST_MakeClass
(
def
));
// is this name mangling correct?
pushAssign
(
source
->
mangleName
(
def
->
name
),
makeName
(
tmp
,
AST_TYPE
::
Load
,
node
->
lineno
,
0
,
true
));
return
true
;
...
...
@@ -1635,7 +1634,6 @@ public:
auto
tmp
=
nodeName
();
pushAssign
(
tmp
,
new
AST_MakeFunction
(
def
));
// is this name mangling correct?
pushAssign
(
source
->
mangleName
(
def
->
name
),
makeName
(
tmp
,
AST_TYPE
::
Load
,
node
->
lineno
,
node
->
col_offset
,
true
));
return
true
;
...
...
@@ -2687,9 +2685,21 @@ public:
AssignVRegsVisitor
(
ScopeInfo
*
scope_info
)
:
scope_info
(
scope_info
),
current_block
(
0
),
next_vreg
(
0
)
{}
bool
visit_alias
(
AST_alias
*
node
)
override
{
if
(
node
->
asname
.
s
().
size
())
node
->
asname_vreg
=
assignVReg
(
node
->
asname
);
else
node
->
name_vreg
=
assignVReg
(
node
->
name
);
return
true
;
}
bool
visit_arguments
(
AST_arguments
*
node
)
override
{
for
(
AST_expr
*
d
:
node
->
defaults
)
d
->
accept
(
this
);
if
(
node
->
kwarg
.
s
().
size
())
node
->
kwarg_vreg
=
assignVReg
(
node
->
kwarg
);
if
(
node
->
vararg
.
s
().
size
())
node
->
vararg_vreg
=
assignVReg
(
node
->
vararg
);
return
true
;
}
...
...
@@ -2749,6 +2759,8 @@ public:
}
int
assignVReg
(
InternedString
id
)
{
assert
(
id
.
s
().
size
());
auto
it
=
sym_vreg_map
.
find
(
id
);
if
(
sym_vreg_map
.
end
()
==
it
)
{
ASSERT
(
next_vreg
==
sym_vreg_map
.
size
(),
"%d %d"
,
next_vreg
,
sym_vreg_map
.
size
());
...
...
test/tests/name_scopes.py
0 → 100644
View file @
b1927655
# Some corner cases around name scopes
def
f1
():
exec
""
from
os
import
path
as
os_path
print
os_path
.
join
(
"a"
,
"b"
)
f1
()
def
f2
():
exec
""
def
f3
(
*
args
,
**
kw
):
exec
""
print
args
,
kw
f3
(
*
[
1
,
2
],
**
dict
(
a
=
1
,
b
=
2
))
f2
()
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