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
6f34e11b
Commit
6f34e11b
authored
Aug 03, 2016
by
Marius Wachtler
Committed by
GitHub
Aug 03, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1316 from undingen/smaller_scopenameusage
ScopeNameUsage merge dicts into a single big one
parents
e21a0dce
75f70a65
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
85 additions
and
49 deletions
+85
-49
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+85
-49
No files found.
src/analysis/scoping_analysis.cpp
View file @
6f34e11b
...
@@ -203,23 +203,37 @@ public:
...
@@ -203,23 +203,37 @@ public:
InternedString
internString
(
llvm
::
StringRef
s
)
override
{
abort
();
}
InternedString
internString
(
llvm
::
StringRef
s
)
override
{
abort
();
}
};
};
struct
ScopeNameUsageEntry
{
// Properties determined from crawling the scope:
unsigned
char
read
:
1
;
unsigned
char
written
:
1
;
unsigned
char
forced_globals
:
1
;
unsigned
char
params
:
1
;
// Properties determined by looking at other scopes as well:
unsigned
char
referenced_from_nested
:
1
;
unsigned
char
got_from_closure
:
1
;
unsigned
char
passthrough_accesses
:
1
;
// what names a child scope accesses a name from a parent scope
ScopeNameUsageEntry
()
:
read
(
0
),
written
(
0
),
forced_globals
(
0
),
params
(
0
),
referenced_from_nested
(
0
),
got_from_closure
(
0
),
passthrough_accesses
(
0
)
{}
};
struct
ScopingAnalysis
::
ScopeNameUsage
{
struct
ScopingAnalysis
::
ScopeNameUsage
{
AST
*
node
;
AST
*
node
;
ScopeNameUsage
*
parent
;
ScopeNameUsage
*
parent
;
llvm
::
StringRef
private_name
;
llvm
::
StringRef
private_name
;
ScopingAnalysis
*
scoping
;
ScopingAnalysis
*
scoping
;
// Properties determined from crawling the scope:
std
::
unordered_map
<
InternedString
,
ScopeNameUsageEntry
>
results
;
StrSet
read
;
StrSet
written
;
StrSet
forced_globals
;
StrSet
params
;
std
::
vector
<
AST_Name
*>
del_name_nodes
;
// Properties determined by looking at other scopes as well:
std
::
vector
<
AST_Name
*>
del_name_nodes
;
StrSet
referenced_from_nested
;
StrSet
got_from_closure
;
StrSet
passthrough_accesses
;
// what names a child scope accesses a name from a parent scope
// `import *` and `exec` both force the scope to use the NAME lookup
// `import *` and `exec` both force the scope to use the NAME lookup
// However, this is not allowed to happen (a SyntaxError) if the scope has
// However, this is not allowed to happen (a SyntaxError) if the scope has
...
@@ -251,12 +265,12 @@ struct ScopingAnalysis::ScopeNameUsage {
...
@@ -251,12 +265,12 @@ struct ScopingAnalysis::ScopeNameUsage {
AST_ClassDef
*
classdef
=
ast_cast
<
AST_ClassDef
>
(
node
);
AST_ClassDef
*
classdef
=
ast_cast
<
AST_ClassDef
>
(
node
);
// classes have an implicit write to "__module__"
// classes have an implicit write to "__module__"
written
.
insert
(
scoping
->
getInternedStrings
().
get
(
"__module__"
))
;
results
[
scoping
->
getInternedStrings
().
get
(
"__module__"
)].
written
=
1
;
if
(
classdef
->
body
.
size
()
&&
classdef
->
body
[
0
]
->
type
==
AST_TYPE
::
Expr
)
{
if
(
classdef
->
body
.
size
()
&&
classdef
->
body
[
0
]
->
type
==
AST_TYPE
::
Expr
)
{
AST_Expr
*
first_expr
=
ast_cast
<
AST_Expr
>
(
classdef
->
body
[
0
]);
AST_Expr
*
first_expr
=
ast_cast
<
AST_Expr
>
(
classdef
->
body
[
0
]);
if
(
first_expr
->
value
->
type
==
AST_TYPE
::
Str
)
{
if
(
first_expr
->
value
->
type
==
AST_TYPE
::
Str
)
{
written
.
insert
(
scoping
->
getInternedStrings
().
get
(
"__doc__"
))
;
results
[
scoping
->
getInternedStrings
().
get
(
"__doc__"
)].
written
=
1
;
}
}
}
}
}
}
...
@@ -273,8 +287,10 @@ struct ScopingAnalysis::ScopeNameUsage {
...
@@ -273,8 +287,10 @@ struct ScopingAnalysis::ScopeNameUsage {
void
dump
()
{
void
dump
()
{
#define DUMP(n) \
#define DUMP(n) \
printf(STRINGIFY(n) ":\n"); \
printf(STRINGIFY(n) ":\n"); \
for (auto s : n) { \
for (auto s : results) { \
printf("%s\n", s.c_str()); \
if (!s.second.n) \
continue; \
printf("%s\n", s.first.c_str()); \
}
}
DUMP
(
read
);
DUMP
(
read
);
...
@@ -300,6 +316,8 @@ private:
...
@@ -300,6 +316,8 @@ private:
bool
allDerefVarsAndInfoCached
;
bool
allDerefVarsAndInfoCached
;
bool
globals_from_module
;
bool
globals_from_module
;
bool
takes_closure
=
false
;
bool
passthrough_accesses
=
false
;
public:
public:
ScopeInfoBase
(
ScopeInfo
*
parent
,
ScopingAnalysis
::
ScopeNameUsage
*
usage
,
AST
*
ast
,
bool
usesNameLookup
,
ScopeInfoBase
(
ScopeInfo
*
parent
,
ScopingAnalysis
::
ScopeNameUsage
*
usage
,
AST
*
ast
,
bool
usesNameLookup
,
...
@@ -313,45 +331,57 @@ public:
...
@@ -313,45 +331,57 @@ public:
assert
(
usage
);
assert
(
usage
);
assert
(
ast
);
assert
(
ast
);
bool
got_from_closure
=
false
;
std
::
vector
<
InternedString
>
referenced_from_nested_sorted
;
for
(
auto
&&
r
:
usage
->
results
)
{
if
(
r
.
second
.
referenced_from_nested
)
referenced_from_nested_sorted
.
push_back
(
r
.
first
);
got_from_closure
=
got_from_closure
||
r
.
second
.
got_from_closure
;
passthrough_accesses
=
passthrough_accesses
||
r
.
second
.
passthrough_accesses
;
}
// Sort the entries by name to make the order deterministic.
// Sort the entries by name to make the order deterministic.
std
::
vector
<
InternedString
>
referenced_from_nested_sorted
(
usage
->
referenced_from_nested
.
begin
(),
usage
->
referenced_from_nested
.
end
());
std
::
sort
(
referenced_from_nested_sorted
.
begin
(),
referenced_from_nested_sorted
.
end
());
std
::
sort
(
referenced_from_nested_sorted
.
begin
(),
referenced_from_nested_sorted
.
end
());
int
i
=
0
;
int
i
=
0
;
for
(
auto
&
p
:
referenced_from_nested_sorted
)
{
for
(
auto
&
p
:
referenced_from_nested_sorted
)
{
closure_offsets
[
p
]
=
i
;
closure_offsets
[
p
]
=
i
;
i
++
;
i
++
;
}
}
takes_closure
=
got_from_closure
||
passthrough_accesses
;
}
}
~
ScopeInfoBase
()
override
{
delete
this
->
usage
;
}
~
ScopeInfoBase
()
override
{
delete
this
->
usage
;
}
ScopeInfo
*
getParent
()
override
{
return
parent
;
}
ScopeInfo
*
getParent
()
override
{
return
parent
;
}
bool
createsClosure
()
override
{
return
usage
->
referenced_from_nested
.
size
()
>
0
;
}
bool
createsClosure
()
override
{
return
closure_offsets
.
size
()
>
0
;
}
bool
takesClosure
()
override
{
bool
takesClosure
()
override
{
return
takes_closure
;
}
return
usage
->
got_from_closure
.
size
()
>
0
||
usage
->
passthrough_accesses
.
size
()
>
0
;
}
bool
passesThroughClosure
()
override
{
return
usage
->
passthrough_accesses
.
size
()
>
0
&&
!
createsClosure
();
}
bool
passesThroughClosure
()
override
{
return
passthrough_accesses
&&
!
createsClosure
();
}
VarScopeType
getScopeTypeOfName
(
InternedString
name
)
override
{
VarScopeType
getScopeTypeOfName
(
InternedString
name
)
override
{
if
(
name
.
isCompilerCreatedName
())
if
(
name
.
isCompilerCreatedName
())
return
VarScopeType
::
FAST
;
return
VarScopeType
::
FAST
;
if
(
usage
->
forced_globals
.
count
(
name
)
>
0
)
ScopeNameUsageEntry
r
;
auto
it
=
usage
->
results
.
find
(
name
);
if
(
it
!=
usage
->
results
.
end
())
r
=
it
->
second
;
if
(
r
.
forced_globals
)
return
VarScopeType
::
GLOBAL
;
return
VarScopeType
::
GLOBAL
;
if
(
usage
->
got_from_closure
.
count
(
name
)
>
0
)
if
(
r
.
got_from_closure
)
return
VarScopeType
::
DEREF
;
return
VarScopeType
::
DEREF
;
if
(
usesNameLookup_
)
{
if
(
usesNameLookup_
)
{
return
VarScopeType
::
NAME
;
return
VarScopeType
::
NAME
;
}
else
{
}
else
{
if
(
usage
->
written
.
count
(
name
)
==
0
)
if
(
!
r
.
written
)
return
VarScopeType
::
GLOBAL
;
return
VarScopeType
::
GLOBAL
;
else
if
(
usage
->
referenced_from_nested
.
count
(
name
)
>
0
)
else
if
(
r
.
referenced_from_nested
)
return
VarScopeType
::
CLOSURE
;
return
VarScopeType
::
CLOSURE
;
else
else
return
VarScopeType
::
FAST
;
return
VarScopeType
::
FAST
;
...
@@ -409,19 +439,17 @@ public:
...
@@ -409,19 +439,17 @@ public:
// Get all the variables that we need to return: any variable from the
// Get all the variables that we need to return: any variable from the
// passed-in closure that is accessed in this scope or in a child scope.
// passed-in closure that is accessed in this scope or in a child scope.
StrSet
allDerefs
=
usage
->
got_from_closure
;
for
(
auto
&&
r
:
usage
->
results
)
{
for
(
InternedString
name
:
usage
->
passthrough_accesses
)
{
if
(
!
r
.
second
.
got_from_closure
)
if
(
allDerefs
.
find
(
name
)
!=
allDerefs
.
end
())
{
continue
;
allDerefs
.
insert
(
name
);
}
}
// Call `getDerefInfo` on all of these variables and put the results in
auto
&&
name
=
r
.
first
;
// `allDerefVarsAndInfo`
// Call `getDerefInfo` on all of these variables and put the results in
for
(
InternedString
name
:
allDerefs
)
{
// `allDerefVarsAndInfo`
allDerefVarsAndInfo
.
push_back
({
name
,
getDerefInfo
(
name
)
});
allDerefVarsAndInfo
.
push_back
({
name
,
getDerefInfo
(
name
)
});
}
}
// Sort in order of `num_parents_from_passed_closure`
// Sort in order of `num_parents_from_passed_closure`
std
::
sort
(
std
::
sort
(
allDerefVarsAndInfo
.
begin
(),
allDerefVarsAndInfo
.
end
(),
allDerefVarsAndInfo
.
begin
(),
allDerefVarsAndInfo
.
end
(),
...
@@ -459,16 +487,17 @@ private:
...
@@ -459,16 +487,17 @@ private:
public:
public:
void
doWrite
(
InternedString
name
)
{
void
doWrite
(
InternedString
name
)
{
assert
(
name
==
mangleName
(
name
,
cur
->
private_name
,
scoping
->
getInternedStrings
()));
assert
(
name
==
mangleName
(
name
,
cur
->
private_name
,
scoping
->
getInternedStrings
()));
cur
->
read
.
insert
(
name
);
auto
&
r
=
cur
->
results
[
name
];
cur
->
written
.
insert
(
name
);
r
.
read
=
1
;
r
.
written
=
1
;
if
(
this
->
currently_visiting_functiondef_args
)
{
if
(
this
->
currently_visiting_functiondef_args
)
{
cur
->
params
.
insert
(
name
)
;
r
.
params
=
1
;
}
}
}
}
void
doRead
(
InternedString
name
)
{
void
doRead
(
InternedString
name
)
{
assert
(
name
==
mangleName
(
name
,
cur
->
private_name
,
scoping
->
getInternedStrings
()));
assert
(
name
==
mangleName
(
name
,
cur
->
private_name
,
scoping
->
getInternedStrings
()));
cur
->
re
ad
.
insert
(
name
)
;
cur
->
re
sults
[
name
].
read
=
1
;
}
}
void
doDel
(
AST_Name
*
node
)
{
cur
->
del_name_nodes
.
push_back
(
node
);
}
void
doDel
(
AST_Name
*
node
)
{
cur
->
del_name_nodes
.
push_back
(
node
);
}
...
@@ -557,11 +586,12 @@ public:
...
@@ -557,11 +586,12 @@ public:
bool
visit_global
(
AST_Global
*
node
)
override
{
bool
visit_global
(
AST_Global
*
node
)
override
{
for
(
int
i
=
0
;
i
<
node
->
names
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
node
->
names
.
size
();
i
++
)
{
mangleNameInPlace
(
node
->
names
[
i
],
cur
->
private_name
,
scoping
->
getInternedStrings
());
mangleNameInPlace
(
node
->
names
[
i
],
cur
->
private_name
,
scoping
->
getInternedStrings
());
if
(
cur
->
params
.
find
(
node
->
names
[
i
])
!=
cur
->
params
.
end
())
{
auto
&
r
=
cur
->
results
[
node
->
names
[
i
]];
if
(
r
.
params
)
{
// Throw an exception if a name is both declared global and a parameter
// Throw an exception if a name is both declared global and a parameter
raiseGlobalAndLocalException
(
node
->
names
[
i
],
this
->
orig_node
);
raiseGlobalAndLocalException
(
node
->
names
[
i
],
this
->
orig_node
);
}
}
cur
->
forced_globals
.
insert
(
node
->
names
[
i
])
;
r
.
forced_globals
=
1
;
}
}
return
true
;
return
true
;
}
}
...
@@ -788,11 +818,15 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
...
@@ -788,11 +818,15 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
bool
is_any_name_free
=
false
;
bool
is_any_name_free
=
false
;
for
(
const
auto
&
name
:
usage
->
read
)
{
for
(
auto
&&
r
:
usage
->
results
)
{
if
(
usage
->
forced_globals
.
count
(
name
)
)
if
(
!
r
.
second
.
read
)
continue
;
continue
;
if
(
usage
->
written
.
count
(
name
)
)
if
(
r
.
second
.
forced_globals
)
continue
;
continue
;
if
(
r
.
second
.
written
)
continue
;
auto
&&
name
=
r
.
first
;
bool
is_name_free
=
true
;
bool
is_name_free
=
true
;
...
@@ -800,18 +834,20 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
...
@@ -800,18 +834,20 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
ScopeNameUsage
*
parent
=
usage
->
parent
;
ScopeNameUsage
*
parent
=
usage
->
parent
;
while
(
parent
)
{
while
(
parent
)
{
auto
parent_result
=
parent
->
results
.
find
(
name
);
bool
found_parent
=
parent_result
!=
parent
->
results
.
end
();
if
(
parent
->
node
->
type
==
AST_TYPE
::
ClassDef
)
{
if
(
parent
->
node
->
type
==
AST_TYPE
::
ClassDef
)
{
intermediate_parents
.
push_back
(
parent
);
intermediate_parents
.
push_back
(
parent
);
parent
=
parent
->
parent
;
parent
=
parent
->
parent
;
}
else
if
(
parent
->
forced_globals
.
count
(
name
)
)
{
}
else
if
(
found_parent
&&
parent_result
->
second
.
forced_globals
)
{
is_name_free
=
false
;
is_name_free
=
false
;
break
;
break
;
}
else
if
(
parent
->
written
.
count
(
name
)
)
{
}
else
if
(
found_parent
&&
parent_result
->
second
.
written
)
{
usage
->
got_from_closure
.
insert
(
name
)
;
r
.
second
.
got_from_closure
=
1
;
parent
->
referenced_from_nested
.
insert
(
name
)
;
parent
_result
->
second
.
referenced_from_nested
=
1
;
for
(
ScopeNameUsage
*
iparent
:
intermediate_parents
)
{
for
(
ScopeNameUsage
*
iparent
:
intermediate_parents
)
{
iparent
->
passthrough_accesses
.
insert
(
name
)
;
iparent
->
results
[
name
].
passthrough_accesses
=
1
;
}
}
break
;
break
;
...
@@ -853,7 +889,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
...
@@ -853,7 +889,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
// `del` for closure variables. But it is, so, there you go:
// `del` for closure variables. But it is, so, there you go:
for
(
AST_Name
*
name_node
:
usage
->
del_name_nodes
)
{
for
(
AST_Name
*
name_node
:
usage
->
del_name_nodes
)
{
InternedString
name
=
name_node
->
id
;
InternedString
name
=
name_node
->
id
;
if
(
usage
->
re
ferenced_from_nested
.
count
(
name
)
>
0
)
{
if
(
usage
->
re
sults
.
count
(
name
)
&&
usage
->
results
[
name
].
referenced_from_nested
)
{
char
buf
[
1024
];
char
buf
[
1024
];
snprintf
(
buf
,
sizeof
(
buf
),
"can not delete variable '%s' referenced in nested scope"
,
name
.
c_str
());
snprintf
(
buf
,
sizeof
(
buf
),
"can not delete variable '%s' referenced in nested scope"
,
name
.
c_str
());
assert
(
usage
->
node
->
type
==
AST_TYPE
::
FunctionDef
);
assert
(
usage
->
node
->
type
==
AST_TYPE
::
FunctionDef
);
...
...
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