Skip to content

Commit a899f38

Browse files
committed
[GR-40690] Bytecode instrumentation
PullRequest: graalpython/2426
2 parents fde7545 + 9e780ce commit a899f38

File tree

130 files changed

+4801
-3461
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+4801
-3461
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ language runtime. The main focus is on user-observable behavior of the engine.
55

66
## Version 22.3.0
77
* Rename GraalPython to GraalPy. This change also updates the launchers we ship to include symlinks from `python` and `python3` to `graalpy`, for better integration with other tools.
8-
* New interpreter backend based on interpreting bytecode. This change should bring better startup performance and memory footprint while retaining good JIT-compiled performance. There is no support for GraalVM instrumentation tools on the bytecode backend yet, so using one of the instrumentation options (e.g. `--inspect`) falls back on the AST backend.
8+
* New interpreter backend based on interpreting bytecode. This change should bring better startup performance and memory footprint while retaining good JIT-compiled performance.
99
* New parser generated from CPython's new PEG grammar definition. It brings better compatibility and enables us to implement the `ast` module.
1010
* Added support for tracing API (`sys.settrace`) which makes `pdb` and related tools work on GraalPy.
1111
* Updated our pip support to automatically choose the best version for known packages. You can use `pip install pandas`, and pip will select the versions of pandas and numpy that we test in the GraalPy CI.

graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ public static void main(String[] args) {
104104

105105
boolean useASTInterpreter = false;
106106

107-
private String toolInstrumentWarning = null;
108-
109107
protected static void setStartupTime() {
110108
if (GraalPythonMain.startupNanoTime == -1) {
111109
GraalPythonMain.startupNanoTime = System.nanoTime();
@@ -201,11 +199,7 @@ protected List<String> preprocessArguments(List<String> givenArgs, Map<String, S
201199
useASTInterpreter = true;
202200
continue;
203201
default:
204-
if (argStartsWith(arg, "--agentscript", "--coverage", "--cpusampler", "--cputracer", "--dap",
205-
"--heap.", "--heapmonitor", "--insight", "--inspect", "--lsp", "--memtracer", "--sandbox.")) {
206-
useASTInterpreter = true;
207-
toolInstrumentWarning = "WARNING: Switching to AST interpreter due to instruments option " + arg;
208-
} else if (arg.startsWith("--llvm.") ||
202+
if (arg.startsWith("--llvm.") ||
209203
matchesPythonOption(arg, "CoreHome") ||
210204
matchesPythonOption(arg, "StdLibHome") ||
211205
matchesPythonOption(arg, "CAPI") ||
@@ -597,6 +591,7 @@ protected void launch(Builder contextBuilder) {
597591
contextBuilder.option("python.VerboseFlag", Boolean.toString(verboseFlag));
598592
contextBuilder.option("python.IsolateFlag", Boolean.toString(isolateFlag));
599593
contextBuilder.option("python.WarnOptions", warnOptions);
594+
contextBuilder.option("python.DontWriteBytecodeFlag", Boolean.toString(dontWriteBytecode));
600595
if (verboseFlag) {
601596
contextBuilder.option("log.python.level", "FINE");
602597
}
@@ -627,10 +622,6 @@ protected void launch(Builder contextBuilder) {
627622
contextBuilder.option("python.PyCachePrefix", "/dev/null");
628623
contextBuilder.option("python.EnableBytecodeInterpreter", "false");
629624
contextBuilder.option("python.DisableFrozenModules", "true");
630-
if (toolInstrumentWarning != null) {
631-
System.out.println(toolInstrumentWarning);
632-
toolInstrumentWarning = null;
633-
}
634625
} else {
635626
contextBuilder.option("python.DontWriteBytecodeFlag", Boolean.toString(dontWriteBytecode));
636627
if (cachePrefix != null) {
@@ -690,15 +681,6 @@ private static boolean matchesPythonOption(String arg, String key) {
690681
return arg.startsWith("--python." + key) || arg.startsWith("--" + key);
691682
}
692683

693-
private static boolean argStartsWith(String arg, String... tools) {
694-
for (String t : tools) {
695-
if (arg.startsWith(t)) {
696-
return true;
697-
}
698-
}
699-
return false;
700-
}
701-
702684
private String getContextOptionIfSetViaCommandLine(String key) {
703685
if (System.getProperty("polyglot.python." + key) != null) {
704686
return System.getProperty("polyglot.python." + key);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.test.compiler;
42+
43+
import java.util.Arrays;
44+
45+
import org.junit.Assert;
46+
import org.junit.Test;
47+
48+
import com.oracle.graal.python.compiler.OpCodes;
49+
import com.oracle.graal.python.compiler.SourceMap;
50+
51+
public class SourceMapTests {
52+
@Test
53+
public void testRoundTrip() {
54+
int[] startLines = new int[]{50, 50, 51, 51, 56, 256};
55+
int[] startColumns = new int[]{0, 128, 0, 129, 5, 597};
56+
int[] endLines = new int[]{50, 51, 51, 53, 59, 350};
57+
int[] endColumns = new int[]{10, 129, 1024, 130, 134, 598};
58+
int startLine = 49;
59+
int startColumn = 0;
60+
SourceMap.Builder builder = new SourceMap.Builder(startLine, startColumn);
61+
byte[] code = new byte[6];
62+
Arrays.fill(code, (byte) OpCodes.NOP.ordinal());
63+
for (int i = 0; i < code.length; i++) {
64+
builder.appendLocation(startLines[i], startColumns[i], endLines[i], endColumns[i]);
65+
}
66+
byte[] table = builder.build();
67+
SourceMap map = new SourceMap(code, table, startLine, startColumn);
68+
Assert.assertArrayEquals(startLines, map.startLineMap);
69+
Assert.assertArrayEquals(startColumns, map.startColumnMap);
70+
Assert.assertArrayEquals(endLines, map.endLineMap);
71+
Assert.assertArrayEquals(endColumns, map.endColumnMap);
72+
}
73+
}

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/debug/PythonDebugTest.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public void before() {
8383
newBuilder.allowAllAccess(true);
8484
PythonTests.closeContext();
8585
tester = new DebuggerTester(newBuilder);
86-
PythonTests.skipOnBytecodeInterpreter();
8786
}
8887

8988
@After
@@ -183,6 +182,29 @@ public void testSteppingAsExpected() throws Throwable {
183182
}
184183
}
185184

185+
@Test
186+
public void testException() throws Throwable {
187+
final Source source = Source.newBuilder("python", "" +
188+
"try:\n" +
189+
" 1 / 0\n" +
190+
"except BaseException as e:\n" +
191+
" str(e)\n" +
192+
"1", "test_exception.py").buildLiteral();
193+
194+
try (DebuggerSession session = tester.startSession()) {
195+
session.install(Breakpoint.newExceptionBuilder(true, true).build());
196+
tester.startEval(source);
197+
198+
expectSuspended((SuspendedEvent event) -> {
199+
DebugStackFrame frame = event.getTopStackFrame();
200+
assertEquals(2, frame.getSourceSection().getStartLine());
201+
assertNotNull(event.getException());
202+
event.prepareContinue();
203+
});
204+
assertEquals("1", tester.expectDone());
205+
}
206+
}
207+
186208
@Test
187209
public void testInlineEvaluation() throws Throwable {
188210
final Source source = Source.newBuilder("python", "" +
@@ -216,6 +238,28 @@ public void testInlineEvaluation() throws Throwable {
216238
}
217239
}
218240

241+
@Test
242+
@SuppressWarnings("try")
243+
public void testBreakpointBuiltin() throws Throwable {
244+
final Source source = Source.newBuilder("python", "" +
245+
"def foo():\n" +
246+
" a = 1\n" +
247+
" breakpoint()\n" +
248+
" return 1\n" +
249+
"foo()\n", "test_breakpoint_builtin.py").buildLiteral();
250+
251+
try (DebuggerSession session = tester.startSession()) {
252+
tester.startEval(source);
253+
254+
expectSuspended((SuspendedEvent event) -> {
255+
DebugStackFrame frame = event.getTopStackFrame();
256+
assertEquals(3, frame.getSourceSection().getStartLine());
257+
event.prepareContinue();
258+
});
259+
assertEquals("1", tester.expectDone());
260+
}
261+
}
262+
219263
@Test
220264
public void testConditionalBreakpointInFunction() throws Throwable {
221265
final Source source = Source.newBuilder("python", "" +

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_multiprocessing_main_handling.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,3 @@
1111
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.ForkServerCmdLineTest.test_script_compiled
1212
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.ForkServerCmdLineTest.test_zipfile
1313
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.ForkServerCmdLineTest.test_zipfile_compiled
14-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_basic_script
15-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_basic_script_no_suffix
16-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_directory
17-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_directory_compiled
18-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_ipython_workaround
19-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_module_in_package_in_zipfile
20-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_package
21-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_package_compiled
22-
*graalpython.lib-python.3.test.test_multiprocessing_main_handling.SpawnCmdLineTest.test_zipfile
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Disassembly of <module>:
2-
000000 0 SETUP_ANNOTATIONS
3-
000009 1 LOAD_BYTE_O 12
4-
000000 3 STORE_NAME 0 (a)
5-
000003 5 LOAD_NAME 1 (int)
6-
000000 7 LOAD_NAME 2 (__annotations__)
7-
000000 9 LOAD_STRING 0 ('a')
8-
000000 11 STORE_SUBSCR
9-
000000 12 LOAD_NONE
10-
000000 13 RETURN_VALUE
2+
1:0 - 1:11 0 SETUP_ANNOTATIONS
3+
1:9 - 1:11 1 LOAD_BYTE_O 12
4+
1:0 - 1:1 3 STORE_NAME 0 (a)
5+
1:3 - 1:6 5 LOAD_NAME 1 (int)
6+
1:0 - 1:11 7 LOAD_NAME 2 (__annotations__)
7+
1:0 - 1:11 9 LOAD_STRING 0 ('a')
8+
1:0 - 1:11 11 STORE_SUBSCR
9+
1:0 - 1:11 12 LOAD_NONE
10+
1:0 - 1:11 13 RETURN_VALUE
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
Disassembly of <module>:
2-
000000 0 COLLECTION_FROM_STACK 0 (PKeyword[])
3-
000000 2 LOAD_STRING 0 ('b')
4-
000018 4 LOAD_BYTE_O 2
5-
000000 6 LOAD_STRING 1 ('a')
6-
000010 8 LOAD_BYTE_O 1
7-
000000 10 LOAD_STRING 2 ('c')
8-
000024 12 LOAD_BYTE_O 3
9-
000000 14 LOAD_STRING 3 ('d')
10-
000029 16 LOAD_BYTE_O 4
11-
000000 18 LOAD_STRING 4 ('e')
12-
000036 20 LOAD_BYTE_O 5
13-
000000 22 COLLECTION_FROM_STACK 10 (dict)
14-
000000 24 MAKE_FUNCTION 6 (foo)
15-
000000 27 STORE_NAME 0 (foo)
16-
000000 29 LOAD_NONE
17-
000000 30 RETURN_VALUE
2+
1:0 - 2:22 0 COLLECTION_FROM_STACK 0 (PKeyword[])
3+
1:0 - 2:22 2 LOAD_STRING 0 ('b')
4+
1:18 - 1:19 4 LOAD_BYTE_O 2
5+
1:0 - 2:22 6 LOAD_STRING 1 ('a')
6+
1:10 - 1:11 8 LOAD_BYTE_O 1
7+
1:0 - 2:22 10 LOAD_STRING 2 ('c')
8+
1:24 - 1:25 12 LOAD_BYTE_O 3
9+
1:0 - 2:22 14 LOAD_STRING 3 ('d')
10+
1:29 - 1:30 16 LOAD_BYTE_O 4
11+
1:0 - 2:22 18 LOAD_STRING 4 ('e')
12+
1:36 - 1:37 20 LOAD_BYTE_O 5
13+
1:0 - 2:22 22 COLLECTION_FROM_STACK 10 (dict)
14+
1:0 - 2:22 24 MAKE_FUNCTION 6 (foo)
15+
1:0 - 2:22 27 STORE_NAME 0 (foo)
16+
1:0 - 2:22 29 LOAD_NONE
17+
1:0 - 2:22 30 RETURN_VALUE
1818

1919
Disassembly of foo:
20-
000042 0 LOAD_GLOBAL 0 (print)
21-
000048 2 LOAD_FAST 0 (a)
22-
000051 4 LOAD_FAST 1 (b)
23-
000054 6 LOAD_FAST 3 (c)
24-
000057 8 LOAD_FAST 2 (d)
25-
000060 10 LOAD_FAST 4 (e)
26-
000042 12 COLLECTION_FROM_STACK 5 (Object[])
27-
000042 14 CALL_FUNCTION_VARARGS
28-
000042 15 POP_TOP
29-
000042 16 LOAD_NONE
30-
000042 17 RETURN_VALUE
20+
2:2 - 2:7 0 LOAD_GLOBAL 0 (print)
21+
2:8 - 2:9 2 LOAD_FAST 0 (a)
22+
2:11 - 2:12 4 LOAD_FAST 1 (b)
23+
2:14 - 2:15 6 LOAD_FAST 3 (c)
24+
2:17 - 2:18 8 LOAD_FAST 2 (d)
25+
2:20 - 2:21 10 LOAD_FAST 4 (e)
26+
2:2 - 2:22 12 COLLECTION_FROM_STACK 5 (Object[])
27+
2:2 - 2:22 14 CALL_FUNCTION_VARARGS
28+
2:2 - 2:22 15 POP_TOP
29+
2:2 - 2:22 16 LOAD_NONE
30+
2:2 - 2:22 17 RETURN_VALUE
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
Disassembly of <module>:
2-
000000 0 COLLECTION_FROM_STACK 0 (PKeyword[])
3-
000000 2 MAKE_FUNCTION 2 (foo)
4-
000000 5 STORE_NAME 0 (foo)
5-
000000 7 LOAD_NONE
6-
000000 8 RETURN_VALUE
2+
1:0 - 2:22 0 COLLECTION_FROM_STACK 0 (PKeyword[])
3+
1:0 - 2:22 2 MAKE_FUNCTION 2 (foo)
4+
1:0 - 2:22 5 STORE_NAME 0 (foo)
5+
1:0 - 2:22 7 LOAD_NONE
6+
1:0 - 2:22 8 RETURN_VALUE
77

88
Disassembly of foo:
9-
000032 0 LOAD_GLOBAL 0 (print)
10-
000038 2 LOAD_FAST 0 (a)
11-
000041 4 LOAD_FAST 1 (b)
12-
000044 6 LOAD_FAST 3 (c)
13-
000047 8 LOAD_FAST 2 (d)
14-
000050 10 LOAD_FAST 4 (e)
15-
000032 12 COLLECTION_FROM_STACK 5 (Object[])
16-
000032 14 CALL_FUNCTION_VARARGS
17-
000032 15 POP_TOP
18-
000032 16 LOAD_NONE
19-
000032 17 RETURN_VALUE
9+
2:2 - 2:7 0 LOAD_GLOBAL 0 (print)
10+
2:8 - 2:9 2 LOAD_FAST 0 (a)
11+
2:11 - 2:12 4 LOAD_FAST 1 (b)
12+
2:14 - 2:15 6 LOAD_FAST 3 (c)
13+
2:17 - 2:18 8 LOAD_FAST 2 (d)
14+
2:20 - 2:21 10 LOAD_FAST 4 (e)
15+
2:2 - 2:22 12 COLLECTION_FROM_STACK 5 (Object[])
16+
2:2 - 2:22 14 CALL_FUNCTION_VARARGS
17+
2:2 - 2:22 15 POP_TOP
18+
2:2 - 2:22 16 LOAD_NONE
19+
2:2 - 2:22 17 RETURN_VALUE
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Disassembly of <module>:
2-
000004 0 LOAD_BYTE_O 12
3-
000000 2 STORE_NAME 0 (a)
4-
000000 4 LOAD_NONE
5-
000000 5 RETURN_VALUE
2+
1:4 - 1:6 0 LOAD_BYTE_O 12
3+
1:0 - 1:1 2 STORE_NAME 0 (a)
4+
1:0 - 1:6 4 LOAD_NONE
5+
1:0 - 1:6 5 RETURN_VALUE
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Disassembly of <module>:
2-
000000 0 LOAD_NAME 0 (a)
3-
000005 2 LOAD_DOUBLE_O 0 (12.0)
4-
000000 4 BINARY_OP 1 (INPLACE_ADD)
5-
000000 6 STORE_NAME 0 (a)
6-
000000 8 LOAD_NONE
7-
000000 9 RETURN_VALUE
2+
1:0 - 1:1 0 LOAD_NAME 0 (a)
3+
1:5 - 1:9 2 LOAD_DOUBLE_O 0 (12.0)
4+
1:0 - 1:9 4 BINARY_OP 1 (INPLACE_ADD)
5+
1:0 - 1:1 6 STORE_NAME 0 (a)
6+
1:0 - 1:9 8 LOAD_NONE
7+
1:0 - 1:9 9 RETURN_VALUE

0 commit comments

Comments
 (0)