src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Jul  7 09:30:32 2017
--- new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Jul  7 09:30:32 2017

*** 25,34 **** --- 25,36 ---- import static java.lang.String.format; import static java.lang.reflect.Modifier.STATIC; import static java.lang.reflect.Modifier.SYNCHRONIZED; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; + import static jdk.vm.ci.meta.DeoptimizationAction.None; + import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException; import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
*** 284,297 **** --- 286,298 ---- import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.debug.Assertions; ! import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; ! import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; ! import org.graalvm.compiler.debug.DebugCounter; ! import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.graph.Node;
*** 450,462 **** --- 451,463 ---- public static final int TRACELEVEL_STATE = 2; /** * Meters the number of actual bytecodes parsed. */ ! public static final DebugCounter BytecodesParsed = Debug.counter("BytecodesParsed"); ! public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed"); ! protected static final DebugCounter EXPLICIT_EXCEPTIONS = Debug.counter("ExplicitExceptions"); ! protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions"); /** * A scoped object for tasks to be performed after parsing an intrinsic such as processing * {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states. */
*** 627,636 **** --- 628,638 ---- } private final GraphBuilderPhase.Instance graphBuilderInstance; protected final StructuredGraph graph; protected final OptionValues options; + protected final DebugContext debug; private BciBlockMapping blockMap; private LocalLiveness liveness; protected final int entryBCI; private final BytecodeParser parent;
*** 661,670 **** --- 663,673 ---- this.code = bytecodeProvider.getBytecode(method); this.method = code.getMethod(); this.graphBuilderInstance = graphBuilderInstance; this.graph = graph; this.options = graph.getOptions(); + this.debug = graph.getDebug(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; this.metaAccess = graphBuilderInstance.metaAccess; this.stampProvider = graphBuilderInstance.stampProvider; this.constantReflection = graphBuilderInstance.constantReflection;
*** 714,732 **** --- 717,735 ---- if (PrintProfilingInformation.getValue(options) && profilingInfo != null) { TTY.println("Profiling info for " + method.format("%H.%n(%p)")); TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } ! try (Indent indent = Debug.logAndIndent("build graph for %s", method)) { ! try (Indent indent = debug.logAndIndent("build graph for %s", method)) { if (bytecodeProvider.shouldRecordMethodDependencies()) { assert getParent() != null || method.equals(graph.method()); // Record method dependency in the graph graph.recordMethod(method); } // compute the block map, setup exception handlers and get the entrypoint(s) ! BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug()); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()]; if (!method.isStatic()) { originalReceiver = startFrameState.loadLocal(0, JavaKind.Object);
*** 736,750 **** --- 739,753 ---- * Configure the assertion checking behavior of the FrameStateBuilder. This needs to be * done only when assertions are enabled, so it is wrapped in an assertion itself. */ assert computeKindVerification(startFrameState); ! try (Scope s = Debug.scope("LivenessAnalysis")) { ! try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) { int maxLocals = method.getMaxLocals(); ! liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); } catch (Throwable e) { ! throw Debug.handle(e); ! throw debug.handle(e); } lastInstr = startInstruction; this.setCurrentFrameState(startFrameState); stream.setBCI(0);
*** 1003,1013 **** --- 1006,1016 ---- append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); } private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; ! Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); ! debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); FrameStateBuilder dispatchState = frameState.copy(); dispatchState.clearStack(); AbstractBeginNode dispatchBegin;
*** 1242,1252 **** --- 1245,1255 ---- append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY)); lastInstr = falseSucc; exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci())); ! EXPLICIT_EXCEPTIONS.increment(debug); return nonNullReceiver; } protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode());
*** 1450,1459 **** --- 1453,1466 ---- } if (invokeKind.hasReceiver()) { args[0] = emitExplicitExceptions(args[0]); } + if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) { + emitCheckForInvokeSuperSpecial(args); + } + InlineInfo inlineInfo = null; try { currentInvoke = new CurrentInvoke(args, invokeKind, returnType); if (tryNodePluginForInvocation(args, targetMethod)) { if (TraceParserPlugins.getValue(options)) {
*** 1533,1542 **** --- 1540,1573 ---- invoke.setUseForInlining(false); } return invoke; } + /** + * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method + * declared in an interface (i.e., a default method) is assignable to the interface. If not, + * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}. + * + * This is a check not performed by the verifier and so must be performed at runtime. + * + * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a + * method in a super class + */ + protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) { + ResolvedJavaType callingClass = method.getDeclaringClass(); + if (callingClass.getHostClass() != null) { + callingClass = callingClass.getHostClass(); + } + if (callingClass.isInterface()) { + ValueNode receiver = args[0]; + TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), callingClass); + LogicNode condition = genUnique(createInstanceOf(checkedType, receiver, null)); + FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, ClassCastException, None, false)); + args[0] = append(PiNode.create(receiver, StampFactory.object(checkedType, true), fixedGuard)); + } + } + protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) { if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { return profilingInfo.getTypeProfile(bci()); } return null;
*** 2093,2105 **** --- 2124,2133 ---- protected void traceWithContext(String format, Object... args) { StackTraceElement where = code.asStackTraceElement(bci()); String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), format(format, args)); if (s.equals("decrypt (CipherBlockChainingSubstitutions.java:117) inlining call to CipherBlockChainingSubstitutions.decrypt(Object, byte[], int, int, byte[], int)")) { System.console(); } TTY.println(s); } protected BytecodeParserError asParserError(Throwable e) { if (e instanceof BytecodeParserError) {
*** 2419,2429 **** --- 2447,2457 ---- } if (firstLoopExit == null) { firstLoopExit = loopExit; } lastLoopExit = loopExit; ! Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); ! debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); newState.clearNonLiveLocals(targetBlock, liveness, true); newState.insertLoopProxies(loopExit, getEntryState(loop)); loopExit.setStateAfter(newState.create(bci, loopExit)); }
*** 2485,2495 **** --- 2513,2523 ---- FixedNode result = target.fixed; FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state; setEntryState(block, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); ! Debug.log("createTarget %s: first visit, result: %s", block, targetNode); ! debug.log("createTarget %s: first visit, result: %s", block, targetNode); return result; } // We already saw this block before, so we have to merge states. if (!getEntryState(block).isCompatibleWith(state)) {
*** 2506,2516 **** --- 2534,2544 ---- LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin)); Target target = checkLoopExit(loopEnd, block, state); FixedNode result = target.fixed; getEntryState(block).merge(loopBegin, target.state); ! Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); ! debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
*** 2547,2557 **** --- 2575,2585 ---- Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; getEntryState(block).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); ! Debug.log("createTarget %s: merging state, result: %s", block, result); ! debug.log("createTarget %s: merging state, result: %s", block, result); return result; } /** * Returns a block begin node with the specified state. If the specified probability is 0, the
*** 2578,2591 **** --- 2606,2619 ---- @SuppressWarnings("try") protected void processBlock(BciBlock block) { // Ignore blocks that have no predecessors by the time their bytecodes are parsed FixedWithNextNode firstInstruction = getFirstInstruction(block); if (firstInstruction == null) { ! Debug.log("Ignoring block %s", block); ! debug.log("Ignoring block %s", block); return; } ! try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { ! try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { lastInstr = firstInstruction; frameState = getEntryState(block); setCurrentFrameState(frameState); currentBlock = block;
*** 2727,2754 **** --- 2755,2782 ---- * We need to preserve the frame state builder of the loop header so that we can merge * values for phi functions, so make a copy of it. */ setEntryState(block, frameState.copy()); ! Debug.log(" created loop header %s", loopBegin); ! debug.log(" created loop header %s", loopBegin); } else if (lastInstr instanceof MergeNode) { /* * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the * phi, so that parsing continues with more precise type information. */ frameState.inferPhiStamps((AbstractMergeNode) lastInstr); } assert lastInstr.next() == null : "instructions already appended at block " + block; ! Debug.log(" frameState: %s", frameState); ! debug.log(" frameState: %s", frameState); lastInstr = finishInstruction(lastInstr, frameState); int endBCI = stream.endBCI(); stream.setBCI(block.startBci); int bci = block.startBci; ! BytecodesParsed.add(debug, block.endBci - bci); /* Reset line number for new block */ if (graphBuilderConfig.insertFullInfopoints()) { previousLineNumber = -1; }
*** 2805,2815 **** --- 2833,2843 ---- } } } private DebugCloseable openNodeContext() { ! if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { ! if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { return graph.withNodeSourcePosition(createBytecodePosition()); } return null; }
*** 2868,2878 **** --- 2896,2906 ---- append(new FullInfopointNode(reason, createFrameState(bci(), null), escapedReturnValue)); } } private boolean traceState() { ! if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE && Debug.isLogEnabled()) { ! if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) { frameState.traceState(); } return true; }
*** 3918,3928 **** --- 3946,3956 ---- private double[] switchProbability(int numberOfCases, int bci) { double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci)); if (prob != null) { assert prob.length == numberOfCases; } else { ! Debug.log("Missing probability (switch) in %s at bci %d", method, bci); ! debug.log("Missing probability (switch) in %s at bci %d", method, bci); prob = new double[numberOfCases]; for (int i = 0; i < numberOfCases; i++) { prob[i] = 1.0d / numberOfCases; } }
*** 4004,4014 **** --- 4032,4042 ---- } assert assertAtIfBytecode(); double probability = profilingInfo.getBranchTakenProbability(bci()); if (probability < 0) { assert probability == -1 : "invalid probability"; ! Debug.log("missing probability in %s at bci %d", code, bci()); ! debug.log("missing probability in %s at bci %d", code, bci()); probability = 0.5; } if (!optimisticOpts.removeNeverExecutedCode(getOptions())) { if (probability == 0) {
*** 4277,4287 **** --- 4305,4315 ---- public FrameStateBuilder getFrameStateBuilder() { return frameState; } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { ! if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { ! if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) { traceInstructionHelper(bci, opcode, blockStart); } return true; }
*** 4298,4308 **** --- 4326,4336 ---- sb.append(' ').append(stream.readUByte(i)); } if (!currentBlock.getJsrScope().isEmpty()) { sb.append(' ').append(currentBlock.getJsrScope()); } ! Debug.log("%s", sb); ! debug.log("%s", sb); } @Override public boolean parsingIntrinsic() { return intrinsicContext != null;

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File