src/java.base/share/classes/java/lang/invoke/MemberName.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/java.base/share/classes/java/lang/invoke/MemberName.java	Fri Oct 17 13:54:29 2014
--- new/src/java.base/share/classes/java/lang/invoke/MemberName.java	Fri Oct 17 13:54:29 2014

*** 1,7 **** --- 1,7 ---- /* ! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. ! * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 36,47 **** --- 36,49 ---- import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; + import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; + import java.util.Objects; /** * A {@code MemberName} is a compact symbolic datum which fully characterizes * a method or field reference.
*** 67,85 **** --- 69,286 ---- * allows invocation. A MemberName is much lighter than a Method, * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), * and those seven fields omit much of the information in Method. * @author jrose */ /*non-public*/ final class MemberName implements Member, Cloneable { + @SuppressWarnings("rawtypes") //Comparable in next line + /*non-public*/ final class MemberName implements Member, Comparable, Cloneable { private Class<?> clazz; // class in which the method is defined private String name; // may be null if not yet materialized private Object type; // may be null if not yet materialized private int flags; // modifier bits; see reflect.Modifier //@Injected JVM_Method* vmtarget; //@Injected int vmindex; private Object resolution; // if null, this guy is resolved + // bare-bones constructor; the JVM will fill it in + MemberName() { } + + /** Create a name for the given class. The resulting name will be in a resolved state. */ + public MemberName(Class<?> type) { + init(type.getDeclaringClass(), type.getSimpleName(), type, + flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); + initResolved(true); + } + + // Construction from symbolic parts, for queries: + /** Create a field or type name from the given components: + * Declaring class, name, type, reference kind. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { + init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); + initResolved(false); + } + + /** Create a field or type name from the given components: Declaring class, name, type. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The modifier flags default to zero. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) { + this(defClass, name, type, REF_NONE); + initResolved(false); + } + + /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. + * It will be a constructor if and only if the name is {@code "&lt;init&gt;"}. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The last argument is optional, a boolean which requests REF_invokeSpecial. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { + int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); + init(defClass, name, type, flagsMods(initFlags, 0, refKind)); + initResolved(false); + } + + /** Create a method, constructor, or field name from the given components: + * Reference kind, declaring class, name, type. + */ + public MemberName(byte refKind, Class<?> defClass, String name, Object type) { + int kindFlags; + if (MethodHandleNatives.refKindIsField(refKind)) { + kindFlags = IS_FIELD; + if (!(type instanceof Class)) + throw newIllegalArgumentException("not a field type"); + } else if (MethodHandleNatives.refKindIsMethod(refKind)) { + kindFlags = IS_METHOD; + if (!(type instanceof MethodType)) + throw newIllegalArgumentException("not a method type"); + } else if (refKind == REF_newInvokeSpecial) { + kindFlags = IS_CONSTRUCTOR; + if (!(type instanceof MethodType) || + !CONSTRUCTOR_NAME.equals(name)) + throw newIllegalArgumentException("not a constructor type or name"); + } else { + throw newIllegalArgumentException("bad reference kind "+refKind); + } + init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); + initResolved(false); + } + + /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ + public static MemberName make(Method m) { + return make(m, false); + } + + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Method m, boolean wantSpecial) { + m.getClass(); // NPE check + // fill in vmtarget, vmindex while we have m in hand: + MethodHandleNatives.init(this, m); + if (clazz == null) { // MHN.init failed + if (m.getDeclaringClass() == MethodHandle.class && + isMethodHandleInvokeName(m.getName())) { + // The JVM did not reify this signature-polymorphic instance. + // Need a special case here. + // See comments on MethodHandleNatives.linkMethod. + MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); + int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); + init(MethodHandle.class, m.getName(), type, flags); + if (isMethodHandleInvoke()) { + return; + } + } + throw new LinkageError(m.toString()); + } + assert(isResolved() && this.clazz != null); + this.name = m.getName(); + if (this.type == null) { + this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; + } + if (wantSpecial) { + if (isAbstract()) { + throw new AbstractMethodError(this.toString()); + } + if (getReferenceKind() == REF_invokeVirtual) { + changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); + } else if (getReferenceKind() == REF_invokeInterface) { + // invokeSpecial on a default method + changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); + } + } + } + + public static MemberName make(Method m, boolean wantSpecial) { + MemberName tmp = new MemberName(m, wantSpecial); + // Unreflected member names are resolved so intern them here. + return tmp.intern(); + } + + /** + * Create a name for the given reflected constructor. The resulting name + * will be in a resolved state. + */ + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Constructor<?> ctor) { + ctor.getClass(); // NPE check + // fill in vmtarget, vmindex while we have ctor in hand: + MethodHandleNatives.init(this, ctor); + assert(isResolved() && this.clazz != null); + this.name = CONSTRUCTOR_NAME; + if (this.type == null) { + this.type = new Object[] { void.class, ctor.getParameterTypes() }; + } + } + + static public MemberName make(Constructor<?> ctor) { + MemberName tmp = new MemberName(ctor); + // Unreflected member names are resolved so intern them here. + return tmp.intern(); + } + + + /** Create a name for the given reflected field. The resulting name will be in a resolved state. + */ + public static MemberName make(Field field) { + return make(field, false); + } + + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Field field, boolean makeSetter) { + field.getClass(); // NPE check + // fill in vmtarget, vmindex while we have field in hand: + MethodHandleNatives.init(this, field); + assert(isResolved() && this.clazz != null); + this.name = field.getName(); + this.type = field.getType(); + byte refKind = this.getReferenceKind(); + assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); + if (makeSetter) { + assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); + changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); + } + } + + static public MemberName make(Field field, boolean makeSetter) { + MemberName tmp = new MemberName(field, makeSetter); + // Unreflected member names are resolved so intern them here. + return tmp.intern(); + } + + /** Initialize a query. It is not resolved. */ + private void init(Class<?> defClass, String name, Object type, int flags) { + // defining class is allowed to be null (for a naked name/type pair) + //name.toString(); // null check + //type.equals(type); // null check + // fill in fields: + this.clazz = defClass; + this.name = name; + this.type = type; + this.flags = flags; + assert(testAnyFlags(ALL_KINDS)); + assert(this.resolution == null); // nobody should have touched this yet + //assert(referenceKindIsConsistent()); // do this after resolution + } + + private void initResolved(boolean isResolved) { + assert(this.resolution == null); // not initialized yet! + if (!isResolved) + this.resolution = this; + assert(isResolved() == isResolved); + } + + /** + * Helper method to intern this member name in the declaring class' member name table. + */ + @SuppressWarnings("unchecked") + private MemberName intern() { + return clazz.internMemberName(this); + } + /** Return the declaring class of this member. * In the case of a bare name and type, the declaring class will be null. */ public Class<?> getDeclaringClass() { return clazz;
*** 477,501 **** --- 678,687 ---- public boolean isAccessibleFrom(Class<?> lookupClass) { return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE); } /** Initialize a query. It is not resolved. */ private void init(Class<?> defClass, String name, Object type, int flags) { // defining class is allowed to be null (for a naked name/type pair) //name.toString(); // null check //type.equals(type); // null check // fill in fields: this.clazz = defClass; this.name = name; this.type = type; this.flags = flags; assert(testAnyFlags(ALL_KINDS)); assert(this.resolution == null); // nobody should have touched this yet //assert(referenceKindIsConsistent()); // do this after resolution } /** * Calls down to the VM to fill in the fields. This method is * synchronized to avoid racing calls. */ private void expandFromVM() {
*** 513,559 **** --- 699,708 ---- assert((flags & RECOGNIZED_MODIFIERS) == 0); assert((mods & ~RECOGNIZED_MODIFIERS) == 0); assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); } /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ public MemberName(Method m) { this(m, false); } @SuppressWarnings("LeakingThisInConstructor") public MemberName(Method m, boolean wantSpecial) { m.getClass(); // NPE check // fill in vmtarget, vmindex while we have m in hand: MethodHandleNatives.init(this, m); if (clazz == null) { // MHN.init failed if (m.getDeclaringClass() == MethodHandle.class && isMethodHandleInvokeName(m.getName())) { // The JVM did not reify this signature-polymorphic instance. // Need a special case here. // See comments on MethodHandleNatives.linkMethod. MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); init(MethodHandle.class, m.getName(), type, flags); if (isMethodHandleInvoke()) return; } throw new LinkageError(m.toString()); } assert(isResolved() && this.clazz != null); this.name = m.getName(); if (this.type == null) this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; if (wantSpecial) { if (isAbstract()) throw new AbstractMethodError(this.toString()); if (getReferenceKind() == REF_invokeVirtual) changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); else if (getReferenceKind() == REF_invokeInterface) // invokeSpecial on a default method changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); } } public MemberName asSpecial() { switch (getReferenceKind()) { case REF_invokeSpecial: return this; case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
*** 595,635 **** --- 744,753 ---- return this; result = clone().changeReferenceKind(newRefKind, refKind); assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); return result; } /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ @SuppressWarnings("LeakingThisInConstructor") public MemberName(Constructor<?> ctor) { ctor.getClass(); // NPE check // fill in vmtarget, vmindex while we have ctor in hand: MethodHandleNatives.init(this, ctor); assert(isResolved() && this.clazz != null); this.name = CONSTRUCTOR_NAME; if (this.type == null) this.type = new Object[] { void.class, ctor.getParameterTypes() }; } /** Create a name for the given reflected field. The resulting name will be in a resolved state. */ public MemberName(Field fld) { this(fld, false); } @SuppressWarnings("LeakingThisInConstructor") public MemberName(Field fld, boolean makeSetter) { fld.getClass(); // NPE check // fill in vmtarget, vmindex while we have fld in hand: MethodHandleNatives.init(this, fld); assert(isResolved() && this.clazz != null); this.name = fld.getName(); this.type = fld.getType(); assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); byte refKind = this.getReferenceKind(); assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); if (makeSetter) { changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); } } public boolean isGetter() { return MethodHandleNatives.refKindIsGetter(getReferenceKind()); } public boolean isSetter() { return MethodHandleNatives.refKindIsSetter(getReferenceKind());
*** 639,655 **** --- 757,766 ---- assert(MethodHandleNatives.refKindIsGetter(refKind)); assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); return clone().changeReferenceKind(setterRefKind, refKind); } /** Create a name for the given class. The resulting name will be in a resolved state. */ public MemberName(Class<?> type) { init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); initResolved(true); } /** * Create a name for a signature-polymorphic invoker. * This is a placeholder for a signature-polymorphic instance * (of MH.invokeExact, etc.) that the JVM does not reify. * See comments on {@link MethodHandleNatives#linkMethod}.
*** 662,674 **** --- 773,782 ---- mem.flags |= mods; // it's not resolved, but add these modifiers anyway assert(mem.isMethodHandleInvoke()) : mem; return mem; } // bare-bones constructor; the JVM will fill it in MemberName() { } // locally useful cloner @Override protected MemberName clone() { try { return (MemberName) super.clone(); } catch (CloneNotSupportedException ex) {
*** 713,767 **** --- 821,863 ---- && this.getReferenceKind() == that.getReferenceKind() && Objects.equals(this.name, that.name) && Objects.equals(this.getType(), that.getType()); } // Construction from symbolic parts, for queries: /** Create a field or type name from the given components: * Declaring class, name, type, reference kind. * The declaring class may be supplied as null if this is to be a bare name and type. * The resulting name will in an unresolved state. + @Override + public int compareTo(Object o) { + MemberName that = (MemberName) o; + + /* First try an equals. This make the ordering checks easier because we + * don't have to be precise and can use hash codes. */ ! public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { ! init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); initResolved(false); ! if (equals(that)) { ! return 0; } /** Create a method or constructor name from the given components: * Declaring class, name, type, reference kind. * It will be a constructor if and only if the name is {@code "&lt;init&gt;"}. * The declaring class may be supplied as null if this is to be a bare name and type. * The last argument is optional, a boolean which requests REF_invokeSpecial. * The resulting name will in an unresolved state. */ public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); init(defClass, name, type, flagsMods(initFlags, 0, refKind)); initResolved(false); + + final int clazzDiff = this.clazz.hashCode() - that.clazz.hashCode(); + if (clazzDiff != 0) { + return clazzDiff; } /** Create a method, constructor, or field name from the given components: * Reference kind, declaring class, name, type. */ public MemberName(byte refKind, Class<?> defClass, String name, Object type) { int kindFlags; if (MethodHandleNatives.refKindIsField(refKind)) { kindFlags = IS_FIELD; if (!(type instanceof Class)) throw newIllegalArgumentException("not a field type"); } else if (MethodHandleNatives.refKindIsMethod(refKind)) { kindFlags = IS_METHOD; if (!(type instanceof MethodType)) throw newIllegalArgumentException("not a method type"); } else if (refKind == REF_newInvokeSpecial) { kindFlags = IS_CONSTRUCTOR; if (!(type instanceof MethodType) || !CONSTRUCTOR_NAME.equals(name)) throw newIllegalArgumentException("not a constructor type or name"); } else { throw newIllegalArgumentException("bad reference kind "+refKind); + + final int kindDiff = this.getReferenceKind() - that.getReferenceKind(); + if (kindDiff != 0) { + return kindDiff; } init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); ! initResolved(false); + ! final int nameDiff = this.name.hashCode() - that.name.hashCode(); + if (nameDiff != 0) { + return nameDiff; + } + + final int typeDiff = this.getType().hashCode() - that.getType().hashCode(); + if (typeDiff != 0) { + return typeDiff; + } + + // In the unlikely case all values above are equal we just return 1. + return 1; } /** Query whether this member name is resolved to a non-static, non-final method. */ public boolean hasReceiverTypeDispatch() { return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
*** 774,790 **** --- 870,879 ---- */ public boolean isResolved() { return resolution == null; } private void initResolved(boolean isResolved) { assert(this.resolution == null); // not initialized yet! if (!isResolved) this.resolution = this; assert(isResolved() == isResolved); } void checkForTypeAlias() { if (isInvocable()) { MethodType type; if (this.type instanceof MethodType) type = (MethodType) this.type;
*** 960,969 **** --- 1049,1059 ---- assert(refKind == m.getReferenceKind()); try { m = MethodHandleNatives.resolve(m, lookupClass); m.checkForTypeAlias(); m.resolution = null; + m.intern(); } catch (LinkageError ex) { // JVM reports that the "bytecode behavior" would get an error assert(!m.isResolved()); m.resolution = ex; return m;
*** 1067,1077 **** --- 1157,1162 ---- for (int i = 0; i < length; i++) buf[i] = new MemberName(); return buf; } } // static { // System.out.println("Hello world! My methods are:"); // System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null)); // } }

src/java.base/share/classes/java/lang/invoke/MemberName.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File