@Override public int nodeSourcePositionBCI(NodeSourcePosition pos) { return pos.getBCI(); }
/** * This method returns a unique key for the given node. Unless the node comes from a * substitution, the unique key is the BCI of the node. Every * newinstance/newarray/newmultiarray/instanceof/checkcast node coming from a substitution * method cannot have a BCI. If one substitution has multiple nodes of the same type, then the * BCI would not be unique. In the later case the key is a unique object. */ protected static Object uniqueKey(Node node) { NodeSourcePosition position = node.getNodeSourcePosition(); // If the 'position' has a 'caller' then it is inlined, case in which the BCI is // probably not unique. if (position != null && position.getCaller() == null) { if (position.getBCI() >= 0) { return position.getBCI(); } } return new Object(); }
private static void format(StringBuilder sb, NodeSourcePosition pos) { MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI()); if (pos.marker != None) { sb.append(" " + pos.marker); } if (SOURCE_POSITION_BYTECODES) { String disassembly = BytecodeDisassembler.disassembleOne(pos.getMethod(), pos.getBCI()); if (disassembly != null && disassembly.length() > 0) { sb.append(" // "); sb.append(disassembly); } } }
public InlineCacheGuardPosition(NodeSourcePosition callStack, ResolvedJavaType dispatchedType, ResolvedJavaMethod targetMethod) { super(callStack.getCaller(), callStack.getMethod(), callStack.getBCI()); this.concreteMethod = targetMethod; this.dispatchedType = dispatchedType; this.hashCode = super.hashCode() + 7 * ((dispatchedType == null) ? 0 : dispatchedType.hashCode()) + 31 * targetMethod.hashCode(); }
@Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && getClass() == obj.getClass()) { NodeSourcePosition that = (NodeSourcePosition) obj; if (hashCode != that.hashCode) { return false; } if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) && Objects.equals(this.sourceLanguagePosition, that.sourceLanguagePosition)) { return true; } } return false; }
private void verifySourcePosition(NodeSourcePosition originalPosition, NodeSourcePosition decodedSourcePosition) { if (originalPosition == null) { assert decodedSourcePosition == null; return; } assert originalPosition.getBCI() == decodedSourcePosition.getBCI(); assert originalPosition.getMethod().equals(decodedSourcePosition.getMethod()); verifySourcePosition(originalPosition.getCaller(), decodedSourcePosition.getCaller()); } }
/** * Look through the graph of the corresponding HostedMethod to see if it allocates. */ private StackTraceElement getViolatingStackTraceElement(AnalysisMethod method, Access access) { final HostedMethod hostedMethod = universe.optionalLookup(method); if (hostedMethod != null) { final StructuredGraph graph = hostedMethod.compilationInfo.getGraph(); Node node = checkViolatingNode(graph, access); if (node != null) { final NodeSourcePosition sourcePosition = node.getNodeSourcePosition(); if (sourcePosition != null && sourcePosition.getBCI() != -1) { return method.asStackTraceElement(sourcePosition.getBCI()); } } } return null; } }
private static String filterAndEncode(MethodFilter[] methodFilter, Node node, InstrumentPhase phase) { NodeSourcePosition pos = node.getNodeSourcePosition(); if (pos != null) { if (!MethodFilter.matches(methodFilter, pos.getMethod())) { return null; } if (phase.instrumentPerInlineSite(node.getOptions())) { StringBuilder sb = new StringBuilder(); while (pos != null) { MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI()); pos = pos.getCaller(); if (pos != null) { sb.append(CodeUtil.NEW_LINE); } } return sb.toString(); } else { return MetaUtil.appendLocation(new StringBuilder(), pos.getMethod(), pos.getBCI()).toString(); } } else { // IfNode has no position information, and is probably synthetic, so we do not // instrument it. return null; } }
default void addCallerToNoDeoptSuccessorPosition(NodeSourcePosition caller) { NodeSourcePosition noDeoptSuccessorPosition = getNoDeoptSuccessorPosition(); if (noDeoptSuccessorPosition == null) { return; } setNoDeoptSuccessorPosition(new NodeSourcePosition(caller, noDeoptSuccessorPosition.getMethod(), noDeoptSuccessorPosition.getBCI())); } }
@Override public TypeState filter(BigBang bb, TypeState newState) { /* Check if the type is allowed to be used for synchronization. */ int bci = source.getNodeSourcePosition() != null ? source.getNodeSourcePosition().getBCI() : 0; for (AnalysisType type : newState.types()) { bb.checkUnsupportedSynchronization(method, bci, type); } return newState; }
assertTrue(falseSuccessorPosition != null, "missing IfNode false successor source position"); int bci = sourcePosition.getBCI(); ResolvedJavaMethod method = sourcePosition.getMethod(); int bytecode = BytecodeDisassembler.getBytecodeAt(method, bci); if (trueSuccessorPosition.getBCI() == nextBCI || trueSuccessorPosition.getBCI() == targetBCI) { assertTrue(compareCallContext(trueSuccessorPosition), "call context different from IfNode in trueSuccessor"); matchingSuccessorFound = true; if (falseSuccessorPosition.getBCI() == nextBCI || falseSuccessorPosition.getBCI() == targetBCI) { assertTrue(compareCallContext(falseSuccessorPosition), "call context different from IfNode in falseSuccessor"); matchingSuccessorFound = true; assertTrue(trueSuccessorPosition.getBCI() != falseSuccessorPosition.getBCI(), "successor positions same in IfNode");
public void reportIllegalUnknownUse(AnalysisMethod method, Node source, String message) { String trace = "Location: " + (source.getNodeSourcePosition() == null ? "[unknown]" : method.asStackTraceElement(source.getNodeSourcePosition().getBCI()).toString()) + "\n"; trace += "Call path:"; getUnsupportedFeatures().addMessage(method.format("%H.%n(%p)"), method, message, trace); }
@Override public boolean isCallAllowed(BigBang bb, AnalysisMethod caller, AnalysisMethod callee, NodeSourcePosition srcPosition) { String calleeName = callee.format("%H.%n"); if (illegalCalleesPattern.matcher(calleeName).find()) { String callerName = caller.format("%H.%n"); if (targetCallersPattern.matcher(callerName).find()) { SuppressSVMWarnings suppress = caller.getAnnotation(SuppressSVMWarnings.class); AnalysisType callerType = caller.getDeclaringClass(); while (suppress == null && callerType != null) { suppress = callerType.getAnnotation(SuppressSVMWarnings.class); callerType = callerType.getEnclosingType(); } if (suppress != null) { String[] reasons = suppress.value(); for (String r : reasons) { if (r.equals("AllowUseOfStreamAPI")) { return true; } } } String message = "Illegal: Graal/Truffle use of Stream API: " + calleeName; int bci = srcPosition.getBCI(); String trace = caller.asStackTraceElement(bci).toString(); bb.getUnsupportedFeatures().addMessage(callerName, caller, message, trace); return false; } } return true; }
private static boolean verifyCaller(NodeSourcePosition current, NodeSourcePosition caller) { if (!STRICT_SOURCE_POSITION) { return true; } if (BytecodeFrame.isPlaceholderBci(caller.getBCI())) { return true; } int opcode = BytecodeDisassembler.getBytecodeAt(caller.getMethod(), caller.getBCI()); JavaMethod method = BytecodeDisassembler.getInvokedMethodAt(caller.getMethod(), caller.getBCI()); /* * It's not really possible to match the declaring classes since this might be an interface * invoke. Matching name and signature probably provides enough accuracy. */ assert method == null || (method.getName().equals(current.getMethod().getName()) && method.getSignature().equals(current.getMethod().getSignature())) || caller.getMethod().getName().equals("linkToTargetMethod") || opcode == Bytecodes.INVOKEDYNAMIC || caller.getMethod().getDeclaringClass().getName().startsWith("Ljava/lang/invoke/LambdaForm$") || current.getMethod().getName().equals("callInlined") : "expected " + method + " but found " + current.getMethod(); return true; } }
public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link, boolean isSubstitution) { if (getCaller() == null) { if (isPlaceholder()) { return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), 0); } assert link == null || isSubstitution || verifyCaller(this, link) : link; assert !isSubstitution || marker == None; return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI(), isSubstitution ? Substitution : None); } else { return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI(), marker); } }
protected void raiseInvalidFrameStateError(FrameState state) throws GraalGraphError { // This is a hard error since an incorrect state could crash hotspot NodeSourcePosition sourcePosition = state.getNodeSourcePosition(); List<String> context = new ArrayList<>(); ResolvedJavaMethod replacementMethodWithProblematicSideEffect = null; if (sourcePosition != null) { NodeSourcePosition pos = sourcePosition; while (pos != null) { StringBuilder sb = new StringBuilder("parsing "); ResolvedJavaMethod method = pos.getMethod(); MetaUtil.appendLocation(sb, method, pos.getBCI()); if (method.getAnnotation(MethodSubstitution.class) != null || method.getAnnotation(Snippet.class) != null) { replacementMethodWithProblematicSideEffect = method; } context.add(sb.toString()); pos = pos.getCaller(); } } String message = "Invalid frame state " + state; if (replacementMethodWithProblematicSideEffect != null) { message += " associated with a side effect in " + replacementMethodWithProblematicSideEffect.format("%H.%n(%p)") + " at a position that cannot be deoptimized to"; } GraalGraphError error = new GraalGraphError(message); for (String c : context) { error.addContext(c); } throw error; } }
private static String formatSource(TypeFlow<?> flow) { Object source = flow.getSource(); if (source instanceof ValueNode) { ValueNode node = (ValueNode) source; NodeSourcePosition nodeSource = node.getNodeSourcePosition(); if (nodeSource != null) { return formatMethod(nodeSource.getMethod()) + ":" + nodeSource.getBCI(); } else if (flow.graphRef() != null) { return formatMethod(flow.graphRef().getMethod()); } else { return "<unknown-source>"; } } else if (source instanceof AnalysisType) { return formatType((AnalysisType) source); } else if (source instanceof AnalysisField) { return formatField((AnalysisField) source); } else if (source == null) { return "<no-source>"; } else { return source.getClass().getSimpleName(); } }
@Override public NodeSourcePosition getCallerBytecodePosition(NodeSourcePosition position) { if (caller == null) { return position; } if (callerBytecodePosition == null) { NodeSourcePosition invokePosition = invokeData.invoke.asNode().getNodeSourcePosition(); if (invokePosition == null) { assert position == null : "should only happen when tracking is disabled"; return null; } callerBytecodePosition = invokePosition; } if (position != null) { return position.addCaller(caller.resolveSourceLanguagePosition(), callerBytecodePosition); } final SourceLanguagePosition pos = caller.resolveSourceLanguagePosition(); if (pos != null && callerBytecodePosition != null) { return new NodeSourcePosition(pos, callerBytecodePosition.getCaller(), callerBytecodePosition.getMethod(), callerBytecodePosition.getBCI()); } return callerBytecodePosition; }
public static void addCounterArgs(Arguments args, ValueNode node, ResolvedJavaType type) { AllocationCounter counter = null; if (AllocationSite.Options.AllocationProfiling.getValue()) { String siteName = "[others]"; if (node.getNodeSourcePosition() != null) { siteName = node.getNodeSourcePosition().getMethod().asStackTraceElement(node.getNodeSourcePosition().getBCI()).toString(); } String className = "[dynamic]"; if (type != null) { className = type.toJavaName(true); } AllocationSite allocationSite = AllocationSite.lookup(siteName, className); String counterName = node.graph().name; if (counterName == null) { counterName = node.graph().method().format("%H.%n(%p)"); } counter = allocationSite.createCounter(counterName); } args.add("counter", counter); }
private long encodeSourcePositions(NodeSourcePosition sourcePosition, EconomicMap<NodeSourcePosition, Long> sourcePositionStartOffsets, UnsafeArrayTypeWriter encodingBuffer) { Long existingAbsoluteOffset = sourcePositionStartOffsets.get(sourcePosition); if (existingAbsoluteOffset != null) { return existingAbsoluteOffset; } long callerAbsoluteOffset = -1; if (sourcePosition.getCaller() != null) { callerAbsoluteOffset = encodeSourcePositions(sourcePosition.getCaller(), sourcePositionStartOffsets, encodingBuffer); } long startAbsoluteOffset = encodingBuffer.getBytesWritten(); long callerRelativeOffset = DeoptimizationSourcePositionDecoder.NO_CALLER; if (sourcePosition.getCaller() != null) { callerRelativeOffset = startAbsoluteOffset - callerAbsoluteOffset; assert callerRelativeOffset > DeoptimizationSourcePositionDecoder.NO_CALLER; } encodingBuffer.putUV(callerRelativeOffset); encodingBuffer.putSV(sourcePosition.getBCI()); encodingBuffer.putUV(objectConstants.getIndex(sourcePosition.getMethod())); sourcePositionStartOffsets.put(sourcePosition, startAbsoluteOffset); return startAbsoluteOffset; }