Skip to content

Commit 97e3670

Browse files
committed
Forward instrumentation materialization calls from TopLevelExceptionHandler
1 parent 36f948e commit 97e3670

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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.nodes.bytecode;
42+
43+
import java.util.Set;
44+
45+
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
46+
import com.oracle.truffle.api.instrumentation.ProbeNode;
47+
import com.oracle.truffle.api.instrumentation.Tag;
48+
import com.oracle.truffle.api.nodes.Node;
49+
50+
class InstrumentationMaterializationForwarder extends Node implements InstrumentableNode {
51+
private final InstrumentableNode delegate;
52+
53+
InstrumentationMaterializationForwarder(InstrumentableNode delegate) {
54+
this.delegate = delegate;
55+
}
56+
57+
@Override
58+
public boolean isInstrumentable() {
59+
return true;
60+
}
61+
62+
@Override
63+
public WrapperNode createWrapper(ProbeNode probe) {
64+
return new Wrapper(this, probe);
65+
}
66+
67+
@Override
68+
public InstrumentableNode materializeInstrumentableNodes(Set<Class<? extends Tag>> materializedTags) {
69+
delegate.materializeInstrumentableNodes(materializedTags);
70+
return this;
71+
}
72+
73+
private static class Wrapper extends Node implements WrapperNode {
74+
@Child private Node delegateNode;
75+
@Child private ProbeNode probeNode;
76+
77+
Wrapper(Node delegateNode, ProbeNode probeNode) {
78+
this.delegateNode = delegateNode;
79+
this.probeNode = probeNode;
80+
}
81+
82+
@Override
83+
public Node getDelegateNode() {
84+
return delegateNode;
85+
}
86+
87+
@Override
88+
public ProbeNode getProbeNode() {
89+
return probeNode;
90+
}
91+
}
92+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2450,6 +2450,10 @@ public void materializeContainedFunctionsForInstrumentation(Set<Class<? extends
24502450
});
24512451
}
24522452

2453+
public Node createInstrumentationMaterializationForwarder() {
2454+
return new InstrumentationMaterializationForwarder(instrumentationRoot);
2455+
}
2456+
24532457
@InliningCutoff // Used only to print expressions in interactive mode
24542458
private int bytecodePrintExpr(VirtualFrame virtualFrame, boolean useCachedNodes, int stackTop, int bci, Node[] localNodes, int bciSlot, int beginBci) {
24552459
setCurrentBci(virtualFrame, bciSlot, bci);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/TopLevelExceptionHandler.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import com.oracle.graal.python.lib.PyObjectStrAsObjectNode;
5959
import com.oracle.graal.python.nodes.BuiltinNames;
6060
import com.oracle.graal.python.nodes.ErrorMessages;
61+
import com.oracle.graal.python.nodes.bytecode.PBytecodeRootNode;
6162
import com.oracle.graal.python.nodes.object.GetClassNode;
6263
import com.oracle.graal.python.nodes.object.GetDictIfExistsNode;
6364
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
@@ -79,6 +80,7 @@
7980
import com.oracle.truffle.api.interop.ExceptionType;
8081
import com.oracle.truffle.api.interop.InteropLibrary;
8182
import com.oracle.truffle.api.interop.UnsupportedMessageException;
83+
import com.oracle.truffle.api.nodes.Node;
8284
import com.oracle.truffle.api.nodes.RootNode;
8385
import com.oracle.truffle.api.source.Source;
8486
import com.oracle.truffle.api.source.SourceSection;
@@ -91,12 +93,24 @@ public final class TopLevelExceptionHandler extends RootNode {
9193

9294
@Child private GilNode gilNode = GilNode.create();
9395

96+
/*
97+
* Necessary to forward materializeInstrumentableNodes calls to the root node. Truffle assumes
98+
* that all source sections of a source are created when the first call target is initialized.
99+
* That may sometimes happen before the bytecode root's call target is initialized, so we need
100+
* to have a node that will trigger the materialization of all nested functions that haven't
101+
* been created yet at this point.
102+
*/
103+
@Child private Node instrumentationForwarder;
104+
94105
public TopLevelExceptionHandler(PythonLanguage language, RootNode child, Source source) {
95106
super(language);
96107
this.sourceSection = child.getSourceSection();
97108
this.innerCallTarget = PythonUtils.getOrCreateCallTarget(child);
98109
this.exception = null;
99110
this.source = source;
111+
if (child instanceof PBytecodeRootNode) {
112+
instrumentationForwarder = ((PBytecodeRootNode) child).createInstrumentationMaterializationForwarder();
113+
}
100114
}
101115

102116
public TopLevelExceptionHandler(PythonLanguage language, PException exception) {

0 commit comments

Comments
 (0)