< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java

Print this page
rev 52509 : [mq]: graal2

@@ -422,10 +422,11 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.util.ValueMergeUtil;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.CodeUtil;

@@ -1035,10 +1036,19 @@
         DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
         deopt.updateNodeSourcePosition(() -> createBytecodePosition());
     }
 
     /**
+     * @param type the type being instantiated
+     */
+    protected void handleIllegalNewInstance(JavaType type) {
+        assert !graphBuilderConfig.unresolvedIsError();
+        DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
+        deopt.updateNodeSourcePosition(() -> createBytecodePosition());
+    }
+
+    /**
      * @param type the type of the array being instantiated
      * @param length the length of the array
      */
     protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) {
         assert !graphBuilderConfig.unresolvedIsError();

@@ -1416,10 +1426,18 @@
             return resolvedType.isInterface() || resolvedType.isLinked();
         }
         return false;
     }
 
+    /**
+     * Check if a type is resolved. Can be overwritten by sub-classes to implement different type
+     * resolution rules.
+     */
+    protected boolean typeIsResolved(JavaType type) {
+        return type instanceof ResolvedJavaType;
+    }
+
     protected void genInvokeStatic(int cpi, int opcode) {
         JavaMethod target = lookupMethod(cpi, opcode);
         assert !uninitializedIsError ||
                         (target instanceof ResolvedJavaMethod && ((ResolvedJavaMethod) target).getDeclaringClass().isInitialized()) : target;
         genInvokeStatic(target);

@@ -1475,11 +1493,32 @@
         }
     }
 
     protected void genInvokeVirtual(int cpi, int opcode) {
         JavaMethod target = lookupMethod(cpi, opcode);
-        genInvokeVirtual(target);
+        if (callTargetIsResolved(target)) {
+            genInvokeVirtual((ResolvedJavaMethod) target);
+        } else {
+            handleUnresolvedInvoke(target, InvokeKind.Virtual);
+        }
+    }
+
+    protected void genInvokeVirtual(ResolvedJavaMethod resolvedTarget) {
+        int cpi = stream.readCPI();
+
+        /*
+         * Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) or
+         * MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
+         * https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic
+         */
+
+        if (genDynamicInvokeHelper(resolvedTarget, cpi, INVOKEVIRTUAL)) {
+            return;
+        }
+
+        ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterCount(true));
+        appendInvoke(InvokeKind.Virtual, resolvedTarget, args);
     }
 
     private boolean genDynamicInvokeHelper(ResolvedJavaMethod target, int cpi, int opcode) {
         assert opcode == INVOKEDYNAMIC || opcode == INVOKEVIRTUAL;
 

@@ -1528,40 +1567,10 @@
         }
 
         return true;
     }
 
-    void genInvokeVirtual(JavaMethod target) {
-        if (!genInvokeVirtualHelper(target)) {
-            handleUnresolvedInvoke(target, InvokeKind.Virtual);
-        }
-    }
-
-    private boolean genInvokeVirtualHelper(JavaMethod target) {
-        if (!callTargetIsResolved(target)) {
-            return false;
-        }
-
-        ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target;
-        int cpi = stream.readCPI();
-
-        /*
-         * Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) or
-         * MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
-         * https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic
-         */
-
-        if (genDynamicInvokeHelper(resolvedTarget, cpi, INVOKEVIRTUAL)) {
-            return true;
-        }
-
-        ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true));
-        appendInvoke(InvokeKind.Virtual, (ResolvedJavaMethod) target, args);
-
-        return true;
-    }
-
     protected void genInvokeSpecial(int cpi, int opcode) {
         JavaMethod target = lookupMethod(cpi, opcode);
         genInvokeSpecial(target);
     }
 

@@ -3016,11 +3025,11 @@
 
             JavaType catchType = block.handler.getCatchType();
             if (graphBuilderConfig.eagerResolving()) {
                 catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
             }
-            if (catchType instanceof ResolvedJavaType) {
+            if (typeIsResolved(catchType)) {
                 TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
 
                 if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
                     for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
                         if (skippedType.isAssignableFrom(checkedCatchType.getType())) {

@@ -3665,11 +3674,11 @@
         Object con = lookupConstant(cpi, opcode);
 
         if (con instanceof JavaType) {
             // this is a load of class constant which might be unresolved
             JavaType type = (JavaType) con;
-            if (type instanceof ResolvedJavaType) {
+            if (typeIsResolved(type)) {
                 frameState.push(JavaKind.Object, appendConstant(getConstantReflection().asJavaClass((ResolvedJavaType) type)));
             } else {
                 handleUnresolvedLoadConstant(type);
             }
         } else if (con instanceof JavaConstant) {

@@ -3921,20 +3930,60 @@
         JavaType result = constantPool.lookupType(cpi, bytecode);
         assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType;
         return result;
     }
 
+    private String unresolvedMethodAssertionMessage(JavaMethod result) {
+        String message = result.format("%H.%n(%P)%R");
+        if (GraalServices.Java8OrEarlier) {
+            JavaType declaringClass = result.getDeclaringClass();
+            String className = declaringClass.getName();
+            switch (className) {
+                case "Ljava/nio/ByteBuffer;":
+                case "Ljava/nio/ShortBuffer;":
+                case "Ljava/nio/CharBuffer;":
+                case "Ljava/nio/IntBuffer;":
+                case "Ljava/nio/LongBuffer;":
+                case "Ljava/nio/FloatBuffer;":
+                case "Ljava/nio/DoubleBuffer;":
+                case "Ljava/nio/MappedByteBuffer;": {
+                    switch (result.getName()) {
+                        case "position":
+                        case "limit":
+                        case "mark":
+                        case "reset":
+                        case "clear":
+                        case "flip":
+                        case "rewind": {
+                            String returnType = result.getSignature().getReturnType(null).toJavaName();
+                            if (returnType.equals(declaringClass.toJavaName())) {
+                                message += String.format(" [Probably cause: %s was compiled with javac from JDK 9+ using " +
+                                                "`-target 8` and `-source 8` options. See https://bugs.openjdk.java.net/browse/JDK-4774077 for details.]", method.getDeclaringClass().toClassName());
+                            }
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+        return message;
+    }
+
     private JavaMethod lookupMethod(int cpi, int opcode) {
         maybeEagerlyResolve(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaMethod : result;
+        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaMethod : unresolvedMethodAssertionMessage(result);
         return result;
     }
 
     protected JavaField lookupField(int cpi, int opcode) {
         maybeEagerlyResolve(cpi, opcode);
         JavaField result = constantPool.lookupField(cpi, method, opcode);
+        return lookupField(result);
+    }
+
+    protected JavaField lookupField(JavaField result) {
         assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaField : "Not resolved: " + result;
         if (parsingIntrinsic() || eagerInitializing) {
             if (result instanceof ResolvedJavaField) {
                 ResolvedJavaType declaringClass = ((ResolvedJavaField) result).getDeclaringClass();
                 if (!declaringClass.isInitialized()) {

@@ -3982,20 +4031,26 @@
         } else {
             return profilingInfo.getTypeProfile(bci());
         }
     }
 
-    private void genCheckCast() {
-        int cpi = getStream().readCPI();
+    private void genCheckCast(int cpi) {
         JavaType type = lookupType(cpi, CHECKCAST);
         ValueNode object = frameState.pop(JavaKind.Object);
+        genCheckCast(type, object);
+    }
 
-        if (!(type instanceof ResolvedJavaType)) {
+    protected void genCheckCast(JavaType type, ValueNode object) {
+        if (typeIsResolved(type)) {
+            genCheckCast((ResolvedJavaType) type, object);
+        } else {
             handleUnresolvedCheckCast(type, object);
-            return;
         }
-        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+    }
+
+    protected void genCheckCast(ResolvedJavaType resolvedType, ValueNode objectIn) {
+        ValueNode object = objectIn;
         TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), resolvedType);
         JavaTypeProfile profile = getProfileForTypeCheck(checkedType);
 
         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
             if (plugin.handleCheckCast(this, object, checkedType.getType(), profile)) {

@@ -4039,24 +4094,31 @@
             }
         }
         frameState.push(JavaKind.Object, castNode);
     }
 
-    private void genInstanceOf() {
-        int cpi = getStream().readCPI();
+    private void genInstanceOf(int cpi) {
         JavaType type = lookupType(cpi, INSTANCEOF);
         ValueNode object = frameState.pop(JavaKind.Object);
+        genInstanceOf(type, object);
+    }
 
-        if (!(type instanceof ResolvedJavaType)) {
+    protected void genInstanceOf(JavaType type, ValueNode object) {
+        if (typeIsResolved(type)) {
+            genInstanceOf((ResolvedJavaType) type, object);
+        } else {
             handleUnresolvedInstanceOf(type, object);
-            return;
         }
-        TypeReference resolvedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
-        JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
+    }
+
+    protected void genInstanceOf(ResolvedJavaType resolvedType, ValueNode objectIn) {
+        ValueNode object = objectIn;
+        TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), resolvedType);
+        JavaTypeProfile profile = getProfileForTypeCheck(checkedType);
 
         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
-            if (plugin.handleInstanceOf(this, object, resolvedType.getType(), profile)) {
+            if (plugin.handleInstanceOf(this, object, checkedType.getType(), profile)) {
                 return;
             }
         }
 
         LogicNode instanceOfNode = null;

@@ -4067,16 +4129,16 @@
                 if (singleType != null) {
                     LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
                     if (!typeCheck.isTautology()) {
                         append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
                     }
-                    instanceOfNode = LogicConstantNode.forBoolean(resolvedType.getType().isAssignableFrom(singleType));
+                    instanceOfNode = LogicConstantNode.forBoolean(checkedType.getType().isAssignableFrom(singleType));
                 }
             }
         }
         if (instanceOfNode == null) {
-            instanceOfNode = createInstanceOf(resolvedType, object, null);
+            instanceOfNode = createInstanceOf(checkedType, object, null);
         }
         LogicNode logicNode = genUnique(instanceOfNode);
 
         int next = getStream().nextBCI();
         int value = getStream().readUByte(next);

@@ -4104,24 +4166,27 @@
     protected void genNewInstance(int cpi) {
         JavaType type = lookupType(cpi, NEW);
         genNewInstance(type);
     }
 
-    void genNewInstance(JavaType type) {
-        if (!(type instanceof ResolvedJavaType)) {
+    protected void genNewInstance(JavaType type) {
+        if (typeIsResolved(type)) {
+            genNewInstance((ResolvedJavaType) type);
+        } else {
             handleUnresolvedNewInstance(type);
-            return;
         }
-        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+    }
+
+    protected void genNewInstance(ResolvedJavaType resolvedType) {
         if (resolvedType.isAbstract() || resolvedType.isInterface()) {
-            handleUnresolvedNewInstance(type);
+            handleIllegalNewInstance(resolvedType);
             return;
         }
 
         ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
         if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
-            handleUnresolvedNewInstance(type);
+            handleIllegalNewInstance(resolvedType);
             return;
         }
 
         ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
         if (skippedExceptionTypes != null) {

@@ -4190,18 +4255,23 @@
         frameState.push(JavaKind.Object, append(createNewArray(elementType, length, true)));
     }
 
     private void genNewObjectArray(int cpi) {
         JavaType type = lookupType(cpi, ANEWARRAY);
+        genNewObjectArray(type);
+    }
 
-        if (!(type instanceof ResolvedJavaType)) {
+    private void genNewObjectArray(JavaType type) {
+        if (typeIsResolved(type)) {
+            genNewObjectArray((ResolvedJavaType) type);
+        } else {
             ValueNode length = frameState.pop(JavaKind.Int);
             handleUnresolvedNewObjectArray(type, length);
-            return;
+        }
         }
 
-        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+    private void genNewObjectArray(ResolvedJavaType resolvedType) {
 
         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) {
             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
             classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore);

@@ -4219,19 +4289,25 @@
 
     private void genNewMultiArray(int cpi) {
         JavaType type = lookupType(cpi, MULTIANEWARRAY);
         int rank = getStream().readUByte(bci() + 3);
         ValueNode[] dims = new ValueNode[rank];
+        genNewMultiArray(type, rank, dims);
+    }
 
-        if (!(type instanceof ResolvedJavaType)) {
+    private void genNewMultiArray(JavaType type, int rank, ValueNode[] dims) {
+        if (typeIsResolved(type)) {
+            genNewMultiArray((ResolvedJavaType) type, rank, dims);
+        } else {
             for (int i = rank - 1; i >= 0; i--) {
                 dims[i] = frameState.pop(JavaKind.Int);
             }
             handleUnresolvedNewMultiArray(type, dims);
-            return;
         }
-        ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+    }
+
+    private void genNewMultiArray(ResolvedJavaType resolvedType, int rank, ValueNode[] dims) {
 
         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) {
             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
             classInitializationPlugin.apply(this, resolvedType, stateBefore);

@@ -4258,16 +4334,16 @@
         JavaField field = lookupField(cpi, opcode);
         genGetField(field, receiverInput);
     }
 
     private void genGetField(JavaField field, ValueNode receiverInput) {
-        ValueNode receiver = maybeEmitExplicitNullCheck(receiverInput);
         if (field instanceof ResolvedJavaField) {
+            ValueNode receiver = maybeEmitExplicitNullCheck(receiverInput);
             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
             genGetField(resolvedField, receiver);
         } else {
-            handleUnresolvedLoadField(field, receiver);
+            handleUnresolvedLoadField(field, receiverInput);
         }
     }
 
     private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) {
         if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {

@@ -4368,13 +4444,14 @@
     protected void genPutField(JavaField field) {
         genPutField(field, frameState.pop(field.getJavaKind()));
     }
 
     private void genPutField(JavaField field, ValueNode value) {
-        ValueNode receiver = maybeEmitExplicitNullCheck(frameState.pop(JavaKind.Object));
+        ValueNode receiverInput = frameState.pop(JavaKind.Object);
 
         if (field instanceof ResolvedJavaField) {
+            ValueNode receiver = maybeEmitExplicitNullCheck(receiverInput);
             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
 
             if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) {
                 graph.recordField(resolvedField);
             }

@@ -4388,11 +4465,11 @@
             if (resolvedField.isFinal() && method.isConstructor()) {
                 finalBarrierRequired = true;
             }
             genStoreField(receiver, resolvedField, value);
         } else {
-            handleUnresolvedStoreField(field, value, receiver);
+            handleUnresolvedStoreField(field, value, receiverInput);
         }
     }
 
     protected void genGetStatic(int cpi, int opcode) {
         JavaField field = lookupField(cpi, opcode);

@@ -4482,10 +4559,11 @@
         JavaField field = lookupField(cpi, opcode);
         genPutStatic(field);
     }
 
     protected void genPutStatic(JavaField field) {
+        int stackSizeBefore = frameState.stackSize();
         ValueNode value = frameState.pop(field.getJavaKind());
         ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value);
         if (resolvedField == null) {
             return;
         }

@@ -4494,11 +4572,14 @@
             graph.recordField(resolvedField);
         }
 
         ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin();
         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedField.getDeclaringClass())) {
-            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
+            JavaKind[] pushedSlotKinds = {field.getJavaKind()};
+            ValueNode[] pushedValues = {value};
+            FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, pushedSlotKinds, pushedValues);
+            assert stackSizeBefore == stateBefore.stackSize();
             classInitializationPlugin.apply(this, resolvedField.getDeclaringClass(), stateBefore);
         }
 
         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
             if (plugin.handleStoreStaticField(this, resolvedField, value)) {

@@ -4867,12 +4948,12 @@
             case NEW            : genNewInstance(stream.readCPI()); break;
             case NEWARRAY       : genNewPrimitiveArray(stream.readLocalIndex()); break;
             case ANEWARRAY      : genNewObjectArray(stream.readCPI()); break;
             case ARRAYLENGTH    : genArrayLength(); break;
             case ATHROW         : genThrow(); break;
-            case CHECKCAST      : genCheckCast(); break;
-            case INSTANCEOF     : genInstanceOf(); break;
+            case CHECKCAST      : genCheckCast(stream.readCPI()); break;
+            case INSTANCEOF     : genInstanceOf(stream.readCPI()); break;
             case MONITORENTER   : genMonitorEnter(frameState.pop(JavaKind.Object), stream.nextBCI()); break;
             case MONITOREXIT    : genMonitorExit(frameState.pop(JavaKind.Object), null, stream.nextBCI()); break;
             case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break;
             case IFNULL         : genIfNull(Condition.EQ); break;
             case IFNONNULL      : genIfNull(Condition.NE); break;
< prev index next >