hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
changeset 46640 70bdce04c59b
parent 46566 231c681fa946
child 46680 2894e4262fd6
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Jul 07 10:37:52 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Jul 07 09:40:47 2017 -0700
@@ -27,6 +27,8 @@
 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;
@@ -286,10 +288,9 @@
 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;
@@ -452,9 +453,9 @@
     /**
      * Meters the number of actual bytecodes parsed.
      */
-    public static final DebugCounter BytecodesParsed = Debug.counter("BytecodesParsed");
-
-    protected static final DebugCounter EXPLICIT_EXCEPTIONS = Debug.counter("ExplicitExceptions");
+    public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed");
+
+    protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions");
 
     /**
      * A scoped object for tasks to be performed after parsing an intrinsic such as processing
@@ -629,6 +630,7 @@
     private final GraphBuilderPhase.Instance graphBuilderInstance;
     protected final StructuredGraph graph;
     protected final OptionValues options;
+    protected final DebugContext debug;
 
     private BciBlockMapping blockMap;
     private LocalLiveness liveness;
@@ -663,6 +665,7 @@
         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;
@@ -716,7 +719,7 @@
             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
@@ -724,7 +727,7 @@
             }
 
             // compute the block map, setup exception handlers and get the entrypoint(s)
-            BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options);
+            BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug());
             this.blockMap = newMapping;
             this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()];
             this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()];
@@ -738,11 +741,11 @@
              */
             assert computeKindVerification(startFrameState);
 
-            try (Scope s = Debug.scope("LivenessAnalysis")) {
+            try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) {
                 int maxLocals = method.getMaxLocals();
-                liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
+                liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
             } catch (Throwable e) {
-                throw Debug.handle(e);
+                throw debug.handle(e);
             }
 
             lastInstr = startInstruction;
@@ -1005,7 +1008,7 @@
 
     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();
@@ -1244,7 +1247,7 @@
 
         exception.setStateAfter(createFrameState(bci(), exception));
         exception.setNext(handleException(exception, bci()));
-        EXPLICIT_EXCEPTIONS.increment();
+        EXPLICIT_EXCEPTIONS.increment(debug);
         return nonNullReceiver;
     }
 
@@ -1452,6 +1455,10 @@
             args[0] = emitExplicitExceptions(args[0]);
         }
 
+        if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) {
+            emitCheckForInvokeSuperSpecial(args);
+        }
+
         InlineInfo inlineInfo = null;
         try {
             currentInvoke = new CurrentInvoke(args, invokeKind, returnType);
@@ -1535,6 +1542,30 @@
         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());
@@ -2095,9 +2126,6 @@
         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);
     }
 
@@ -2421,7 +2449,7 @@
                         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));
@@ -2487,7 +2515,7 @@
             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;
         }
 
@@ -2508,7 +2536,7 @@
             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";
@@ -2549,7 +2577,7 @@
         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;
     }
 
@@ -2580,10 +2608,10 @@
         // 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);
@@ -2729,7 +2757,7 @@
              */
             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
@@ -2738,7 +2766,7 @@
             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);
 
@@ -2746,7 +2774,7 @@
 
         stream.setBCI(block.startBci);
         int bci = block.startBci;
-        BytecodesParsed.add(block.endBci - bci);
+        BytecodesParsed.add(debug, block.endBci - bci);
 
         /* Reset line number for new block */
         if (graphBuilderConfig.insertFullInfopoints()) {
@@ -2807,7 +2835,7 @@
     }
 
     private DebugCloseable openNodeContext() {
-        if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
+        if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
             return graph.withNodeSourcePosition(createBytecodePosition());
         }
         return null;
@@ -2870,7 +2898,7 @@
     }
 
     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;
@@ -3920,7 +3948,7 @@
         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;
@@ -4006,7 +4034,7 @@
         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;
         }
 
@@ -4279,7 +4307,7 @@
     }
 
     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;
@@ -4300,7 +4328,7 @@
         if (!currentBlock.getJsrScope().isEmpty()) {
             sb.append(' ').append(currentBlock.getJsrScope());
         }
-        Debug.log("%s", sb);
+        debug.log("%s", sb);
     }
 
     @Override