< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page

        

*** 102,116 **** } else { LambdaForm lform = preparedFieldLambdaForm(member); if (member.isStatic()) { long offset = MethodHandleNatives.staticFieldOffset(member); Object base = MethodHandleNatives.staticFieldBase(member); ! return new StaticAccessor(mtype, lform, member, base, offset); } else { long offset = MethodHandleNatives.objectFieldOffset(member); assert(offset == (int)offset); ! return new Accessor(mtype, lform, member, (int)offset); } } } static DirectMethodHandle make(Class<?> refc, MemberName member) { byte refKind = member.getReferenceKind(); --- 102,119 ---- } else { LambdaForm lform = preparedFieldLambdaForm(member); if (member.isStatic()) { long offset = MethodHandleNatives.staticFieldOffset(member); Object base = MethodHandleNatives.staticFieldBase(member); ! return member.isFlattenable() ? new StaticValueAccessor(mtype, lform, member, base, offset) ! : new StaticAccessor(mtype, lform, member, base, offset); } else { long offset = MethodHandleNatives.objectFieldOffset(member); assert(offset == (int)offset); ! return member.isFlattenable() ? new ValueAccessor(mtype, lform, member, (int)offset) ! : new Accessor(mtype, lform, member, (int)offset); ! } } } static DirectMethodHandle make(Class<?> refc, MemberName member) { byte refKind = member.getReferenceKind();
*** 488,497 **** --- 491,515 ---- MethodHandle copyWith(MethodType mt, LambdaForm lf) { return new Accessor(mt, lf, member, fieldOffset); } } + static class ValueAccessor extends Accessor { + private ValueAccessor(MethodType mtype, LambdaForm form, MemberName member, + int fieldOffset) { + super(mtype, form, member, fieldOffset); + } + + @Override Object checkCast(Object obj) { + return fieldType.cast(Objects.requireNonNull(obj)); + } + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new ValueAccessor(mt, lf, member, fieldOffset); + } + } + @ForceInline /*non-public*/ static long fieldOffset(Object accessorObj) { // Note: We return a long because that is what Unsafe.getObject likes. // We store a plain int because it is more compact. return ((Accessor)accessorObj).fieldOffset;
*** 509,521 **** return Objects.requireNonNull(obj); } /** This subclass handles static field references. */ static class StaticAccessor extends DirectMethodHandle { ! private final Class<?> fieldType; ! private final Object staticBase; ! private final long staticOffset; private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member, Object staticBase, long staticOffset) { super(mtype, form, member); this.fieldType = member.getFieldType(); --- 527,539 ---- return Objects.requireNonNull(obj); } /** This subclass handles static field references. */ static class StaticAccessor extends DirectMethodHandle { ! final Class<?> fieldType; ! final Object staticBase; ! final long staticOffset; private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member, Object staticBase, long staticOffset) { super(mtype, form, member); this.fieldType = member.getFieldType();
*** 530,539 **** --- 548,573 ---- MethodHandle copyWith(MethodType mt, LambdaForm lf) { return new StaticAccessor(mt, lf, member, staticBase, staticOffset); } } + static class StaticValueAccessor extends StaticAccessor { + private StaticValueAccessor(MethodType mtype, LambdaForm form, MemberName member, + Object staticBase, long staticOffset) { + super(mtype, form, member, staticBase, staticOffset); + } + + @Override Object checkCast(Object obj) { + return fieldType.cast(Objects.requireNonNull(obj)); + } + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new StaticValueAccessor(mt, lf, member, staticBase, staticOffset); + } + } + + @ForceInline /*non-public*/ static Object nullCheck(Object obj) { return Objects.requireNonNull(obj); }
*** 574,615 **** AF_PUTSTATIC = 3, AF_GETSTATIC_INIT = 4, AF_PUTSTATIC_INIT = 5, AF_LIMIT = 6; // Enumerate the different field kinds using Wrapper, ! // with an extra case added for checked references. static final int FT_LAST_WRAPPER = Wrapper.COUNT-1, FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(), FT_CHECKED_REF = FT_LAST_WRAPPER+1, ! FT_LIMIT = FT_LAST_WRAPPER+2; ! private static int afIndex(byte formOp, boolean isFlattened, boolean isVolatile, int ftypeKind) { return ((formOp * FT_LIMIT * 2) - + (isFlattened ? FT_LIMIT : 0) + (isVolatile ? FT_LIMIT : 0) + ftypeKind); } @Stable private static final LambdaForm[] ACCESSOR_FORMS ! = new LambdaForm[afIndex(AF_LIMIT, false,false, 0)]; ! static int ftypeKind(Class<?> ftype) { if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal(); ! else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) return FT_UNCHECKED_REF; ! else ! return FT_CHECKED_REF; } /** * Create a LF which can access the given field. * Cache and share this structure among all fields with * the same basicType and refKind. */ private static LambdaForm preparedFieldLambdaForm(MemberName m) { Class<?> ftype = m.getFieldType(); boolean isVolatile = m.isVolatile(); boolean isFlattened = m.isFlattened(); byte formOp; switch (m.getReferenceKind()) { case REF_getField: formOp = AF_GETFIELD; break; case REF_putField: formOp = AF_PUTFIELD; break; --- 608,652 ---- AF_PUTSTATIC = 3, AF_GETSTATIC_INIT = 4, AF_PUTSTATIC_INIT = 5, AF_LIMIT = 6; // Enumerate the different field kinds using Wrapper, ! // with an extra case added for checked references and value field access static final int FT_LAST_WRAPPER = Wrapper.COUNT-1, FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(), FT_CHECKED_REF = FT_LAST_WRAPPER+1, ! FT_CHECKED_VALUE = FT_LAST_WRAPPER+2, // flattened and non-flattened ! FT_LIMIT = FT_LAST_WRAPPER+4; ! private static int afIndex(byte formOp, boolean isVolatile, boolean isFlattened, int ftypeKind) { return ((formOp * FT_LIMIT * 2) + (isVolatile ? FT_LIMIT : 0) + + (isFlattened ? 1 : 0) + ftypeKind); } @Stable private static final LambdaForm[] ACCESSOR_FORMS ! = new LambdaForm[afIndex(AF_LIMIT, false, false, 0)]; ! static int ftypeKind(Class<?> ftype, boolean isNullable) { if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal(); ! else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) { return FT_UNCHECKED_REF; ! } else ! // null check for value type in addition to check cast ! return isNullable ? FT_CHECKED_REF : FT_CHECKED_VALUE; } /** * Create a LF which can access the given field. * Cache and share this structure among all fields with * the same basicType and refKind. */ private static LambdaForm preparedFieldLambdaForm(MemberName m) { Class<?> ftype = m.getFieldType(); boolean isVolatile = m.isVolatile(); + boolean isNullable = m.isNullable(); boolean isFlattened = m.isFlattened(); byte formOp; switch (m.getReferenceKind()) { case REF_getField: formOp = AF_GETFIELD; break; case REF_putField: formOp = AF_PUTFIELD; break;
*** 617,652 **** case REF_putStatic: formOp = AF_PUTSTATIC; break; default: throw new InternalError(m.toString()); } if (shouldBeInitialized(m)) { // precompute the barrier-free version: ! preparedFieldLambdaForm(formOp, isFlattened, isVolatile, ftype); assert((AF_GETSTATIC_INIT - AF_GETSTATIC) == (AF_PUTSTATIC_INIT - AF_PUTSTATIC)); formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC); } ! LambdaForm lform = preparedFieldLambdaForm(formOp, isFlattened, isVolatile, ftype); maybeCompile(lform, m); assert(lform.methodType().dropParameterTypes(0, 1) .equals(m.getInvocationType().basicType())) : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); return lform; } ! private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isFlattened, boolean isVolatile, Class<?> ftype) { ! int ftypeKind = ftypeKind(ftype); ! int afIndex = afIndex(formOp, isFlattened, isVolatile, ftypeKind); LambdaForm lform = ACCESSOR_FORMS[afIndex]; if (lform != null) return lform; ! lform = makePreparedFieldLambdaForm(formOp, isFlattened, isVolatile, ftypeKind); ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS return lform; } private static final Wrapper[] ALL_WRAPPERS = Wrapper.values(); ! private static Kind getFieldKind(boolean isGetter, boolean isFlattened, boolean isVolatile, Wrapper wrapper) { if (isGetter) { if (isVolatile) { switch (wrapper) { case BOOLEAN: return GET_BOOLEAN_VOLATILE; case BYTE: return GET_BYTE_VOLATILE; --- 654,690 ---- case REF_putStatic: formOp = AF_PUTSTATIC; break; default: throw new InternalError(m.toString()); } if (shouldBeInitialized(m)) { // precompute the barrier-free version: ! preparedFieldLambdaForm(formOp, isVolatile, isFlattened, isNullable, ftype); assert((AF_GETSTATIC_INIT - AF_GETSTATIC) == (AF_PUTSTATIC_INIT - AF_PUTSTATIC)); formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC); } ! LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, isFlattened, isNullable, ftype); maybeCompile(lform, m); assert(lform.methodType().dropParameterTypes(0, 1) .equals(m.getInvocationType().basicType())) : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); return lform; } ! private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, boolean isFlattened, boolean isNullable, Class<?> ftype) { ! int ftypeKind = ftypeKind(ftype, isNullable); ! assert(isNullable ? (ftypeKind < FT_CHECKED_VALUE) : (ftypeKind == FT_CHECKED_VALUE)); ! int afIndex = afIndex(formOp, isVolatile, isFlattened, ftypeKind); LambdaForm lform = ACCESSOR_FORMS[afIndex]; if (lform != null) return lform; ! lform = makePreparedFieldLambdaForm(formOp, isVolatile, isFlattened, ftypeKind); ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS return lform; } private static final Wrapper[] ALL_WRAPPERS = Wrapper.values(); ! private static Kind getFieldKind(boolean isGetter, boolean isVolatile, boolean isFlattened, Wrapper wrapper) { if (isGetter) { if (isVolatile) { switch (wrapper) { case BOOLEAN: return GET_BOOLEAN_VOLATILE; case BYTE: return GET_BYTE_VOLATILE;
*** 654,664 **** case CHAR: return GET_CHAR_VOLATILE; case INT: return GET_INT_VOLATILE; case LONG: return GET_LONG_VOLATILE; case FLOAT: return GET_FLOAT_VOLATILE; case DOUBLE: return GET_DOUBLE_VOLATILE; ! case OBJECT: return GET_REFERENCE_VOLATILE; } } else { switch (wrapper) { case BOOLEAN: return GET_BOOLEAN; case BYTE: return GET_BYTE; --- 692,702 ---- case CHAR: return GET_CHAR_VOLATILE; case INT: return GET_INT_VOLATILE; case LONG: return GET_LONG_VOLATILE; case FLOAT: return GET_FLOAT_VOLATILE; case DOUBLE: return GET_DOUBLE_VOLATILE; ! case OBJECT: return isFlattened ? GET_VALUE_VOLATILE : GET_REFERENCE_VOLATILE; } } else { switch (wrapper) { case BOOLEAN: return GET_BOOLEAN; case BYTE: return GET_BYTE;
*** 680,690 **** case CHAR: return PUT_CHAR_VOLATILE; case INT: return PUT_INT_VOLATILE; case LONG: return PUT_LONG_VOLATILE; case FLOAT: return PUT_FLOAT_VOLATILE; case DOUBLE: return PUT_DOUBLE_VOLATILE; ! case OBJECT: return PUT_REFERENCE_VOLATILE; } } else { switch (wrapper) { case BOOLEAN: return PUT_BOOLEAN; case BYTE: return PUT_BYTE; --- 718,728 ---- case CHAR: return PUT_CHAR_VOLATILE; case INT: return PUT_INT_VOLATILE; case LONG: return PUT_LONG_VOLATILE; case FLOAT: return PUT_FLOAT_VOLATILE; case DOUBLE: return PUT_DOUBLE_VOLATILE; ! case OBJECT: return isFlattened ? PUT_VALUE_VOLATILE : PUT_REFERENCE_VOLATILE; } } else { switch (wrapper) { case BOOLEAN: return PUT_BOOLEAN; case BYTE: return PUT_BYTE;
*** 699,719 **** } } throw new AssertionError("Invalid arguments"); } ! static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isFlattened, boolean isVolatile, int ftypeKind) { boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1); boolean isStatic = (formOp >= AF_GETSTATIC); boolean needsInit = (formOp >= AF_GETSTATIC_INIT); ! boolean needsCast = (ftypeKind == FT_CHECKED_REF); Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]); Class<?> ft = fw.primitiveType(); ! assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind); // getObject, putIntVolatile, etc. ! Kind kind = getFieldKind(isGetter, isFlattened, isVolatile, fw); MethodType linkerType; if (isFlattened) { linkerType = isGetter ? MethodType.methodType(ft, Object.class, long.class, Class.class) : MethodType.methodType(void.class, Object.class, long.class, Class.class, ft); --- 737,757 ---- } } throw new AssertionError("Invalid arguments"); } ! static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, boolean isFlattened, int ftypeKind) { boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1); boolean isStatic = (formOp >= AF_GETSTATIC); boolean needsInit = (formOp >= AF_GETSTATIC_INIT); ! boolean needsCast = (ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_VALUE); Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]); Class<?> ft = fw.primitiveType(); ! assert(needsCast ? true : ftypeKind(ft, ftypeKind != FT_CHECKED_VALUE) == ftypeKind); // getObject, putIntVolatile, etc. ! Kind kind = getFieldKind(isGetter, isVolatile, isFlattened, fw); MethodType linkerType; if (isFlattened) { linkerType = isGetter ? MethodType.methodType(ft, Object.class, long.class, Class.class) : MethodType.methodType(void.class, Object.class, long.class, Class.class, ft);
< prev index next >