# HG changeset patch # User Tom Rodriguez # Date 1397513310 25200 # Node ID 175111728365bf94d031e71e5d9cb464040a9a4c # Parent 9f7eac122d6186e1650e6ace49a34b488bf889b3 improve canBeStaticallyBound diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Apr 14 15:08:30 2014 -0700 @@ -131,16 +131,18 @@ public void canBeStaticallyBoundTest() { for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); - assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey())); } for (Map.Entry, ResolvedJavaMethod> e : constructors.entrySet()) { ResolvedJavaMethod m = e.getValue(); - assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey())); } } - private static boolean canBeStaticallyBound(int modifiers) { - return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers); + private static boolean canBeStaticallyBound(Member method) { + int modifiers = method.getModifiers(); + return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) && + !Modifier.isAbstract(modifiers); } private static String methodWithExceptionHandlers(String p1, Object o2) { diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Apr 14 15:08:30 2014 -0700 @@ -35,10 +35,10 @@ * Returns the bytecode of this method, if the method has code. The returned byte array does not * contain breakpoints or non-Java bytecodes. This may return null if the * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}. - * + * * The contained constant pool indices may not be the ones found in the original class file but * they can be used with the Graal API (e.g. methods in {@link ConstantPool}). - * + * * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the * code is not ready. */ @@ -47,7 +47,7 @@ /** * Returns the size of the bytecode of this method, if the method has code. This is equivalent * to {@link #getCode()}. {@code length} if the method has code. - * + * * @return the size of the bytecode in bytes, or 0 if no bytecode is available */ int getCodeSize(); @@ -84,10 +84,10 @@ /** * Returns {@code true} if this method is a default method; returns {@code false} otherwise. - * + * * A default method is a public non-abstract instance method, that is, a non-static method with * a body, declared in an interface type. - * + * * @return true if and only if this method is a default method as defined by the Java Language * Specification. */ @@ -95,22 +95,22 @@ /** * Checks whether this method is a class initializer. - * + * * @return {@code true} if the method is a class initializer */ boolean isClassInitializer(); /** * Checks whether this method is a constructor. - * + * * @return {@code true} if the method is a constructor */ boolean isConstructor(); /** * Checks whether this method can be statically bound (usually, that means it is final or - * private or static, but not abstract). - * + * private or static, but not abstract, or the declaring class is final) + * * @return {@code true} if this method can be statically bound */ boolean canBeStaticallyBound(); @@ -143,7 +143,7 @@ /** * Returns the annotation for the specified type of this method, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this * method, else {@code null} @@ -153,7 +153,7 @@ /** * Returns an array of arrays that represent the annotations on the formal parameters, in * declaration order, of this method. - * + * * @see Method#getParameterAnnotations() */ Annotation[][] getParameterAnnotations(); @@ -161,7 +161,7 @@ /** * Returns an array of {@link Type} objects that represent the formal parameter types, in * declaration order, of this method. - * + * * @see Method#getGenericParameterTypes() */ Type[] getGenericParameterTypes(); @@ -192,7 +192,7 @@ * Invokes the underlying method represented by this object, on the specified object with the * specified parameters. This method is similar to a reflective method invocation by * {@link Method#invoke}. - * + * * @param receiver The receiver for the invocation, or {@code null} if it is a static method. * @param arguments The arguments for the invocation. * @return The value returned by the method invocation, or {@code null} if the return type is @@ -204,7 +204,7 @@ * Uses the constructor represented by this object to create and initialize a new instance of * the constructor's declaring class, with the specified initialization parameters. This method * is similar to a reflective instantiation by {@link Constructor#newInstance}. - * + * * @param arguments The arguments for the constructor. * @return The newly created and initialized object. */ @@ -212,14 +212,14 @@ /** * Gets the encoding of (that is, a constant representing the value of) this method. - * + * * @return a constant representing a reference to this method */ Constant getEncoding(); /** * Checks if this method is present in the virtual table. - * + * * @return true is this method is present in the virtual table */ boolean isInVirtualMethodTable(); diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 14 15:08:30 2014 -0700 @@ -1056,6 +1056,7 @@ @HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline; @HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline; @HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden; + @HotSpotVMConstant(name = "Method::nonvirtual_vtable_index") @Stable public int nonvirtualVtableIndex; @HotSpotVMConstant(name = "JVM_ACC_MONITOR_MATCH") @Stable public int jvmAccMonitorMatch; @HotSpotVMConstant(name = "JVM_ACC_HAS_MONITOR_BYTECODES") @Stable public int jvmAccHasMonitorBytecodes; diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Apr 14 15:08:30 2014 -0700 @@ -187,7 +187,7 @@ @Override public boolean canBeStaticallyBound() { int modifiers = getModifiers(); - return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers); + return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(holder.getModifiers())) && !Modifier.isAbstract(modifiers); } @Override @@ -616,8 +616,11 @@ * @return virtual table index */ private int getVtableIndex() { + assert !Modifier.isInterface(holder.getModifiers()); HotSpotVMConfig config = runtime().getConfig(); - return unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset); + int result = unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset); + assert result >= config.nonvirtualVtableIndex : "must be linked"; + return result; } public SpeculationLog getSpeculationLog() { diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Apr 14 15:08:30 2014 -0700 @@ -55,7 +55,7 @@ /** * Gets the target method for this invocation instruction. - * + * * @return the target method */ public ResolvedJavaMethod targetMethod() { @@ -76,7 +76,7 @@ /** * Gets the instruction that produces the receiver object for this invocation, if any. - * + * * @return the instruction that produces the receiver object for this invocation if any, * {@code null} if this invocation does not take a receiver object */ @@ -86,7 +86,7 @@ /** * Checks whether this is an invocation of a static method. - * + * * @return {@code true} if the invocation is a static invocation */ public boolean isStatic() { @@ -138,18 +138,17 @@ return this; } - // check if the exact type of the receiver can be determined + assert targetMethod.getDeclaringClass().asExactType() == null : "should have been handled by canBeStaticallyBound"; + + // check if the type of the receiver can narrow the result ValueNode receiver = receiver(); - ResolvedJavaType exact = targetMethod.getDeclaringClass().asExactType(); - if (exact == null && ObjectStamp.isExactType(receiver)) { - exact = ObjectStamp.typeOrNull(receiver); - } - if (exact != null) { + ResolvedJavaType type = ObjectStamp.typeOrNull(receiver); + if (type != null) { // either the holder class is exact, or the receiver object has an exact type - ResolvedJavaMethod exactMethod = exact.resolveMethod(targetMethod); - if (exactMethod != null) { + ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod); + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || ObjectStamp.isExactType(receiver))) { invokeKind = InvokeKind.Special; - targetMethod = exactMethod; + targetMethod = resolvedMethod; return this; } } diff -r 9f7eac122d61 -r 175111728365 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Apr 14 15:07:55 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Apr 14 15:08:30 2014 -0700 @@ -814,7 +814,7 @@ if (!Objects.equals(type, ObjectStamp.typeOrNull(receiver))) { ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); if (method != null) { - if (Modifier.isFinal(method.getModifiers()) || Modifier.isFinal(type.getModifiers())) { + if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { callTarget.setInvokeKind(InvokeKind.Special); callTarget.setTargetMethod(method); } diff -r 9f7eac122d61 -r 175111728365 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Mon Apr 14 15:07:55 2014 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Apr 14 15:08:30 2014 -0700 @@ -2423,6 +2423,7 @@ declare_constant(Method::_force_inline) \ declare_constant(Method::_dont_inline) \ declare_constant(Method::_hidden) \ + declare_constant(Method::nonvirtual_vtable_index) \ \ declare_constant(ConstMethod::_has_linenumber_table) \ declare_constant(ConstMethod::_has_checked_exceptions) \