Skip to content

Commit 50c2891

Browse files
committed
CodeObject extract args related stats for creating code objects from a RootNode
1 parent 80f2f16 commit 50c2891

File tree

2 files changed

+91
-44
lines changed

2 files changed

+91
-44
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/code/PCode.java

Lines changed: 87 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,66 +40,77 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.code;
4242

43-
import java.util.ArrayList;
4443
import java.util.Arrays;
4544
import java.util.HashSet;
4645
import java.util.List;
4746
import java.util.Set;
47+
import java.util.stream.Collectors;
4848

4949
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
5050
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5151
import com.oracle.graal.python.nodes.ModuleRootNode;
5252
import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode;
5353
import com.oracle.graal.python.nodes.argument.ReadKeywordNode;
54+
import com.oracle.graal.python.nodes.frame.WriteIdentifierNode;
5455
import com.oracle.graal.python.nodes.function.FunctionRootNode;
5556
import com.oracle.graal.python.nodes.generator.GeneratorFunctionRootNode;
5657
import com.oracle.graal.python.runtime.PythonCore;
5758
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
59+
import com.oracle.truffle.api.nodes.Node;
5860
import com.oracle.truffle.api.nodes.NodeUtil;
5961
import com.oracle.truffle.api.nodes.RootNode;
6062
import com.oracle.truffle.api.source.SourceSection;
6163

6264
public class PCode extends PythonBuiltinObject {
63-
private final RootNode result;
65+
private final RootNode rootNode;
66+
// number of arguments (not including keyword only arguments, * or ** args)
6467
private final int argcount;
68+
// number of keyword only arguments (not including ** arg)
6569
private final int kwonlyargcount;
70+
// number of local variables
6671
private final int nlocals;
72+
// virtual machine stack space required
6773
private final int stacksize;
74+
// bitmap of CO_* flags, read more
75+
// (https://docs.python.org/3/library/inspect.html#inspect-module-co-flags)
6876
private final int flags;
77+
// string of raw compiled bytecode
6978
private final String codestring;
79+
// tuple of constants used in the bytecode
7080
private final Object constants;
81+
// tuple of names of local variables
7182
private final Object names;
83+
// tuple of names of arguments and local variables
7284
private final Object[] varnames;
85+
// name of file in which this code object was created
7386
private final String filename;
87+
// name with which this code object was defined
7488
private final String name;
89+
// number of first line in Python source code
7590
private final int firstlineno;
91+
// encoded mapping of line numbers to bytecode indices
7692
private final Object lnotab;
93+
// tuple of names of free variables (referenced via a function’s closure)
7794
private final Object[] freevars;
95+
// tuple of names of cell variables (referenced by containing scopes)
7896
private final Object[] cellvars;
7997

8098
@TruffleBoundary
81-
public PCode(PythonClass cls, RootNode result, PythonCore core) {
99+
public PCode(PythonClass cls, RootNode rootNode, PythonCore core) {
82100
super(cls);
83-
this.result = result;
101+
this.rootNode = rootNode;
84102
// file stats
85-
this.filename = getFileName(this.result);
86-
this.name = getName(this.result);
87-
this.firstlineno = getFirstLineno(this.result);
103+
this.filename = getFileName(this.rootNode);
104+
this.name = getName(this.rootNode);
105+
this.firstlineno = getFirstLineno(this.rootNode);
88106
// arg stats
89-
ArgStats argStats = getArgStats(this.result);
107+
ArgStats argStats = getArgStats(this.rootNode, core);
90108
this.argcount = argStats.argCnt;
91109
this.kwonlyargcount = argStats.kwOnlyArgCnt;
92-
// var stats
93-
String[] freevars = getFreeVars(this.result);
94-
String[] cellvars = getCellVars(this.result);
95-
Set<String> freeVarsSet = asSet(freevars);
96-
Set<String> cellVarsSet = asSet(cellvars);
97-
ArrayList<String> varNames = getVarNames(this.result, freeVarsSet, cellVarsSet, core);
98-
99-
this.freevars = freevars;
100-
this.cellvars = cellvars;
101-
this.varnames = varNames.toArray();
102-
this.nlocals = this.varnames.length;
110+
this.freevars = argStats.freeVars;
111+
this.cellvars = argStats.cellVars;
112+
this.varnames = argStats.varNames;
113+
this.nlocals = argStats.nLocals;
103114

104115
this.stacksize = -1;
105116
this.flags = -1;
@@ -114,7 +125,7 @@ public PCode(PythonClass cls, int argcount, int kwonlyargcount, int nlocals, int
114125
String filename, String name, int firstlineno, Object lnotab, Object[] freevars,
115126
Object[] cellvars) {
116127
super(cls);
117-
this.result = null;
128+
this.rootNode = null;
118129
this.argcount = argcount;
119130
this.kwonlyargcount = kwonlyargcount;
120131
this.nlocals = nlocals;
@@ -169,11 +180,7 @@ private static String getFileName(RootNode rootNode) {
169180

170181
private static int getFirstLineno(RootNode rootNode) {
171182
SourceSection sourceSection = rootNode.getSourceSection();
172-
if (sourceSection == null) {
173-
return 1;
174-
} else {
175-
return sourceSection.getStartLine();
176-
}
183+
return (sourceSection != null) ? sourceSection.getStartLine() : 1;
177184
}
178185

179186
private static String getName(RootNode rootNode) {
@@ -188,46 +195,82 @@ private static String getName(RootNode rootNode) {
188195
return name;
189196
}
190197

191-
private static ArrayList<String> getVarNames(RootNode rootNode, Set<String> freeVarsSet, Set<String> cellVarsSet, PythonCore core) {
192-
// tuple of names of arguments and local variables
193-
ArrayList<String> variableNames = new ArrayList<>();
194-
for (Object identifier : rootNode.getFrameDescriptor().getIdentifiers()) {
195-
if (identifier instanceof String) {
196-
String varName = (String) identifier;
197-
if (core.getParser().isIdentifier(core, varName) && !freeVarsSet.contains(varName) && !cellVarsSet.contains(varName)) {
198-
variableNames.add(varName);
198+
private static Set<String> getArgumentNames(List<ReadIndexedArgumentNode> readIndexedArgumentNodes) {
199+
Set<String> argNames = new HashSet<>();
200+
for (ReadIndexedArgumentNode node : readIndexedArgumentNodes) {
201+
Node parent = node.getParent();
202+
if (parent instanceof WriteIdentifierNode) {
203+
Object identifier = ((WriteIdentifierNode) parent).getIdentifier();
204+
if (identifier instanceof String) {
205+
argNames.add((String) identifier);
199206
}
200207
}
201208
}
202-
return variableNames;
209+
return argNames;
203210
}
204211

205212
private final static class ArgStats {
206213
public final int argCnt;
207214
private final int kwOnlyArgCnt;
215+
private final Object[] varNames;
216+
private final Object[] freeVars;
217+
private final Object[] cellVars;
218+
private final int nLocals;
208219

209-
private ArgStats(int argCnt, int kwOnlyArgCnt) {
220+
private ArgStats(int argCnt, int kwOnlyArgCnt, Object[] varNames, Object[] freeVars, Object[] cellVars) {
210221
this.argCnt = argCnt;
211222
this.kwOnlyArgCnt = kwOnlyArgCnt;
223+
this.varNames = varNames;
224+
this.freeVars = freeVars;
225+
this.cellVars = cellVars;
226+
this.nLocals = varNames.length;
212227
}
213228
}
214229

215-
private static ArgStats getArgStats(RootNode rootNode) {
216-
int argC = NodeUtil.findAllNodeInstances(rootNode, ReadIndexedArgumentNode.class).size();
230+
private static ArgStats getArgStats(RootNode rootNode, PythonCore core) {
231+
String[] freeVars = getFreeVars(rootNode);
232+
String[] cellVars = getCellVars(rootNode);
233+
Set<String> freeVarsSet = asSet(freeVars);
234+
Set<String> cellVarsSet = asSet(cellVars);
235+
236+
List<ReadKeywordNode> readKeywordNodes = NodeUtil.findAllNodeInstances(rootNode, ReadKeywordNode.class);
237+
List<ReadIndexedArgumentNode> readIndexedArgumentNodes = NodeUtil.findAllNodeInstances(rootNode, ReadIndexedArgumentNode.class);
238+
239+
Set<String> kwNames = readKeywordNodes.stream().map(ReadKeywordNode::getName).collect(Collectors.toSet());
240+
Set<String> argNames = getArgumentNames(readIndexedArgumentNodes);
241+
242+
Set<String> allArgNames = new HashSet<>();
243+
allArgNames.addAll(kwNames);
244+
allArgNames.addAll(argNames);
245+
246+
int argC = readIndexedArgumentNodes.size();
217247
int kwOnlyArgC = 0;
218-
List<ReadKeywordNode> kwNodes = NodeUtil.findAllNodeInstances(rootNode, ReadKeywordNode.class);
219-
for (ReadKeywordNode kwNode : kwNodes) {
220-
if (kwNode.canBePositional()) {
221-
argC++;
222-
} else {
248+
249+
for (ReadKeywordNode kwNode : readKeywordNodes) {
250+
if (!kwNode.canBePositional()) {
223251
kwOnlyArgC++;
224252
}
225253
}
226-
return new ArgStats(argC, kwOnlyArgC);
254+
255+
Set<String> varNames = new HashSet<>();
256+
for (Object identifier : rootNode.getFrameDescriptor().getIdentifiers()) {
257+
if (identifier instanceof String) {
258+
String varName = (String) identifier;
259+
260+
if (core.getParser().isIdentifier(core, varName)) {
261+
if (allArgNames.contains(varName)) {
262+
varNames.add(varName);
263+
} else if (!freeVarsSet.contains(varName) && !cellVarsSet.contains(varName)) {
264+
varNames.add(varName);
265+
}
266+
}
267+
}
268+
}
269+
return new ArgStats(argC, kwOnlyArgC, varNames.toArray(), freeVars, cellVars);
227270
}
228271

229272
public RootNode getRootNode() {
230-
return result;
273+
return rootNode;
231274
}
232275

233276
public Object[] getFreeVars() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/ReadKeywordNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,8 @@ private Object determineKeyword(VirtualFrame frame, PKeyword keyword) {
137137
return profile.profile(keyword.getValue());
138138
}
139139
}
140+
141+
public String getName() {
142+
return name;
143+
}
140144
}

0 commit comments

Comments
 (0)