Skip to content

Commit de611e8

Browse files
committed
ForkExecNode: avoid using internal arrays of sequences and cached nodes behind TB
1 parent 026b210 commit de611e8

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixSubprocessModuleBuiltins.java

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,12 @@
5858
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5959
import com.oracle.graal.python.builtins.PythonBuiltins;
6060
import com.oracle.graal.python.builtins.objects.PNone;
61-
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
6261
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
63-
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
6462
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum;
6563
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum.ErrorAndMessagePair;
6664
import com.oracle.graal.python.builtins.objects.function.PArguments;
6765
import com.oracle.graal.python.builtins.objects.list.PList;
6866
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
69-
import com.oracle.graal.python.builtins.objects.str.PString;
7067
import com.oracle.graal.python.nodes.ErrorMessages;
7168
import com.oracle.graal.python.nodes.PGuards;
7269
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
@@ -86,6 +83,7 @@
8683
import com.oracle.truffle.api.dsl.NodeFactory;
8784
import com.oracle.truffle.api.dsl.Specialization;
8885
import com.oracle.truffle.api.frame.VirtualFrame;
86+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
8987
import com.oracle.truffle.api.library.CachedLibrary;
9088

9189
@CoreFunctions(defineModule = "_posixsubprocess")
@@ -102,21 +100,18 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
102100
abstract static class ForkExecNode extends PythonBuiltinNode {
103101
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(ForkExecNode.class);
104102

105-
@Child private BytesNodes.ToBytesNode toBytes = BytesNodes.ToBytesNode.create();
106-
107103
@Specialization
108104
int forkExec(VirtualFrame frame, PList args, @SuppressWarnings("unused") PList execList, @SuppressWarnings("unused") boolean closeFds,
109105
@SuppressWarnings("unused") PList fdsToKeep, String cwd, PList env,
110106
int p2cread, int p2cwrite, int c2pread, int c2pwrite,
111107
int errread, int errwrite, @SuppressWarnings("unused") int errpipe_read, int errpipe_write,
112-
@SuppressWarnings("unused") boolean restore_signals, @SuppressWarnings("unused") boolean call_setsid, @SuppressWarnings("unused") PNone preexec_fn,
113-
@Cached SequenceStorageNodes.CopyInternalArrayNode copy) {
108+
@SuppressWarnings("unused") boolean restore_signals, @SuppressWarnings("unused") boolean call_setsid, @SuppressWarnings("unused") PNone preexec_fn) {
114109

115110
PythonContext context = getContext();
116111
Object state = IndirectCallContext.enter(frame, context, this);
117112
try {
118113
return forkExec(args, execList, closeFds, fdsToKeep, cwd, env, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, call_setsid,
119-
preexec_fn, copy);
114+
preexec_fn);
120115
} finally {
121116
IndirectCallContext.exit(frame, context, state);
122117
}
@@ -127,22 +122,20 @@ private synchronized int forkExec(PList args, PList execList, @SuppressWarnings(
127122
@SuppressWarnings("unused") PList fdsToKeep, String cwd, PList env,
128123
int p2cread, int p2cwrite, int c2pread, int c2pwrite,
129124
int errread, int errwrite, @SuppressWarnings("unused") int errpipe_read, int errpipe_write,
130-
@SuppressWarnings("unused") boolean restore_signals, @SuppressWarnings("unused") boolean call_setsid, @SuppressWarnings("unused") PNone preexec_fn,
131-
@Cached SequenceStorageNodes.CopyInternalArrayNode copy) {
125+
@SuppressWarnings("unused") boolean restore_signals, @SuppressWarnings("unused") boolean call_setsid, @SuppressWarnings("unused") PNone preexec_fn) {
132126
PythonContext context = getContext();
133127
PosixResources resources = context.getResources();
134128
if (!context.isExecutableAccessAllowed()) {
135129
return -1;
136130
}
137131

138-
ArrayList<String> argStrings = new ArrayList<>();
139-
Object[] copyOfInternalArray = copy.execute(args.getSequenceStorage());
140-
for (Object o : copyOfInternalArray) {
141-
if (o instanceof String) {
142-
argStrings.add((String) o);
143-
} else if (o instanceof PString) {
144-
argStrings.add(((PString) o).getValue());
145-
} else {
132+
SequenceStorage argsStorage = args.getSequenceStorage();
133+
ArrayList<String> argStrings = new ArrayList<>(argsStorage.length());
134+
CastToJavaStringNode castToStringNode = CastToJavaStringNode.getUncached();
135+
for (int i = 0; i < argsStorage.length(); i++) {
136+
try {
137+
argStrings.add(castToStringNode.execute(argsStorage.getItemNormalized(i)));
138+
} catch (CannotCastException ex) {
146139
throw raise(PythonBuiltinClassType.OSError, ErrorMessages.ILLEGAL_ARG);
147140
}
148141
}
@@ -158,16 +151,19 @@ private synchronized int forkExec(PList args, PList execList, @SuppressWarnings(
158151
throw raise(PythonBuiltinClassType.OSError, e);
159152
}
160153

161-
HashMap<String, String> envMap = new HashMap<>(env.getSequenceStorage().length());
162-
for (Object keyValue : env.getSequenceStorage().getInternalArray()) {
163-
if (keyValue instanceof PBytes) {
164-
// NOTE: passing 'null' frame means we took care of the global state in the
165-
// callers
166-
String str = checkNullBytesAndEncode(toBytes.execute(null, keyValue));
167-
String[] strings = str.split("=", 2);
168-
if (strings.length == 2) {
169-
envMap.put(strings[0], strings[1]);
170-
}
154+
SequenceStorage envStorage = env.getSequenceStorage();
155+
HashMap<String, String> envMap = new HashMap<>(envStorage.length());
156+
PythonObjectLibrary pyLib = PythonObjectLibrary.getUncached();
157+
for (int i = 0; i < envStorage.length(); i++) {
158+
Object keyValue = envStorage.getItemNormalized(i);
159+
if (!(keyValue instanceof PBytes)) {
160+
continue;
161+
}
162+
// NOTE: passing 'null' frame means we took care of the global state in the callers
163+
String str = checkNullBytesAndEncode(pyLib, (PBytes) keyValue);
164+
String[] strings = str.split("=", 2);
165+
if (strings.length == 2) {
166+
envMap.put(strings[0], strings[1]);
171167
}
172168
}
173169

@@ -198,7 +194,7 @@ private synchronized int forkExec(PList args, PList execList, @SuppressWarnings(
198194
if (!(item instanceof PBytes)) {
199195
throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.EXPECTED_BYTES_P_FOUND, item);
200196
}
201-
String path = checkNullBytesAndEncode(toBytes.execute(null, item));
197+
String path = checkNullBytesAndEncode(pyLib, (PBytes) item);
202198
int executableListLen = 0;
203199
if (path.equals(context.getOption(PythonOptions.Executable))) {
204200
// In case someone passed to us sys.executable that happens to be java command
@@ -289,7 +285,13 @@ private int exec(ArrayList<String> argStrings, File cwd, Map<String, String> env
289285
return resources.registerChild(process);
290286
}
291287

292-
private String checkNullBytesAndEncode(byte[] bytes) {
288+
private String checkNullBytesAndEncode(PythonObjectLibrary pyLib, PBytes bytesObj) {
289+
byte[] bytes;
290+
try {
291+
bytes = pyLib.getBufferBytes(bytesObj);
292+
} catch (UnsupportedMessageException e) {
293+
throw new AssertionError(); // should not happen
294+
}
293295
for (byte b : bytes) {
294296
if (b == 0) {
295297
throw raise(PythonBuiltinClassType.ValueError, ErrorMessages.EMBEDDED_NULL_BYTE);
@@ -329,7 +331,6 @@ int forkExecDefault(VirtualFrame frame, Object args, Object executable_list, Obj
329331
@Cached CastToListNode castFdsToKeep,
330332
@Cached CastToJavaStringNode castCwd,
331333
@Cached CastToListNode castEnv,
332-
@Cached SequenceStorageNodes.CopyInternalArrayNode copy,
333334
@CachedLibrary(limit = "3") PythonObjectLibrary lib) {
334335
String actualCwd;
335336
if (cwd instanceof PNone) {
@@ -367,7 +368,7 @@ int forkExecDefault(VirtualFrame frame, Object args, Object executable_list, Obj
367368
lib.asSizeWithState(errpipe_read, PArguments.getThreadState(frame)),
368369
lib.asSizeWithState(errpipe_write, PArguments.getThreadState(frame)),
369370
lib.isTrueWithState(restore_signals, PArguments.getThreadState(frame)),
370-
lib.isTrueWithState(call_setsid, PArguments.getThreadState(frame)), PNone.NO_VALUE, copy);
371+
lib.isTrueWithState(call_setsid, PArguments.getThreadState(frame)), PNone.NO_VALUE);
371372
}
372373

373374
}

0 commit comments

Comments
 (0)