61 member.getReferenceKind() == REF_invokeInterface &&
62 member.isMethod() && !member.isAbstract()) {
63 // Check for corner case: invokeinterface of Object method
64 MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
65 m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
66 if (m != null && m.isPublic()) {
67 assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong
68 member = m;
69 }
70 }
71
72 this.member = member;
73 }
74
75 // Factory methods:
76 static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
77 MethodType mtype = member.getMethodOrFieldType();
78 if (!member.isStatic()) {
79 if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
80 throw new InternalError(member.toString());
81 mtype = mtype.insertParameterTypes(0, refc.isValue() ? refc.asValueType() : refc);
82 }
83 if (!member.isField()) {
84 // refKind reflects the original type of lookup via findSpecial or
85 // findVirtual etc.
86 switch (refKind) {
87 case REF_invokeSpecial: {
88 member = member.asSpecial();
89 // if caller is an interface we need to adapt to get the
90 // receiver check inserted
91 if (callerClass == null) {
92 throw new InternalError("callerClass must not be null for REF_invokeSpecial");
93 }
94 LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
95 return new Special(mtype, lform, member, callerClass);
96 }
97 case REF_invokeInterface: {
98 // for interfaces we always need the receiver typecheck,
99 // so we always pass 'true' to ensure we adapt if needed
100 // to include the REF_invokeSpecial case
101 LambdaForm lform = preparedLambdaForm(member, true);
102 return new Interface(mtype, lform, member, refc);
103 }
104 default: {
105 LambdaForm lform = preparedLambdaForm(member);
106 return new DirectMethodHandle(mtype, lform, member);
107 }
108 }
109 } else {
110 LambdaForm lform = preparedFieldLambdaForm(member);
111 if (member.isStatic()) {
112 long offset = MethodHandleNatives.staticFieldOffset(member);
113 Object base = MethodHandleNatives.staticFieldBase(member);
114 return member.isValue() ? new StaticValueAccessor(mtype, lform, member, base, offset)
115 : new StaticAccessor(mtype, lform, member, base, offset);
116 } else {
117 long offset = MethodHandleNatives.objectFieldOffset(member);
118 assert(offset == (int)offset);
119 return member.isValue() ? new ValueAccessor(mtype, lform, member, (int)offset)
120 : new Accessor(mtype, lform, member, (int)offset);
121
122 }
123 }
124 }
125 static DirectMethodHandle make(Class<?> refc, MemberName member) {
126 byte refKind = member.getReferenceKind();
127 if (refKind == REF_invokeSpecial)
128 refKind = REF_invokeVirtual;
129 return make(refKind, refc, member, null /* no callerClass context */);
130 }
131 static DirectMethodHandle make(MemberName member) {
132 if (member.isConstructor() && member.getReturnType() == void.class)
133 return makeAllocator(member);
134 return make(member.getDeclaringClass(), member);
135 }
136 private static DirectMethodHandle makeAllocator(MemberName ctor) {
137 assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
138 Class<?> instanceClass = ctor.getDeclaringClass();
139 if (instanceClass.isValue())
140 instanceClass = instanceClass.asValueType(); // convert to Q-Type
141 ctor = ctor.asConstructor();
142 assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
143 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
144 LambdaForm lform = preparedLambdaForm(ctor);
145 MemberName init = ctor.asSpecial();
146 assert(init.getMethodType().returnType() == void.class);
147 return new Constructor(mtype, lform, ctor, init, instanceClass);
148 }
149
150 @Override
151 BoundMethodHandle rebind() {
152 return BoundMethodHandle.makeReinvoker(this);
153 }
154
155 @Override
156 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
157 assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses
158 return new DirectMethodHandle(mt, lf, member);
159 }
160
650 return isValue ? FT_CHECKED_VALUE : FT_CHECKED_REF;
651 }
652
653 /**
654 * Create a LF which can access the given field.
655 * Cache and share this structure among all fields with
656 * the same basicType and refKind.
657 */
658 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
659 Class<?> ftype = m.getFieldType();
660 byte formOp;
661 switch (m.getReferenceKind()) {
662 case REF_getField: formOp = AF_GETFIELD; break;
663 case REF_putField: formOp = AF_PUTFIELD; break;
664 case REF_getStatic: formOp = AF_GETSTATIC; break;
665 case REF_putStatic: formOp = AF_PUTSTATIC; break;
666 default: throw new InternalError(m.toString());
667 }
668 if (shouldBeInitialized(m)) {
669 // precompute the barrier-free version:
670 preparedFieldLambdaForm(formOp, m.isVolatile(), m.isValue(), m.isFlattened(), ftype);
671 assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
672 (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
673 formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
674 }
675 LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isValue(), m.isFlattened(), ftype);
676 maybeCompile(lform, m);
677 assert(lform.methodType().dropParameterTypes(0, 1)
678 .equals(m.getInvocationType().basicType()))
679 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
680 return lform;
681 }
682
683 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, boolean isValue, boolean isFlatValue, Class<?> ftype) {
684 int ftypeKind = ftypeKind(ftype, isValue);
685 int afIndex = afIndex(formOp, isVolatile, isFlatValue, ftypeKind);
686 LambdaForm lform = ACCESSOR_FORMS[afIndex];
687 if (lform != null) return lform;
688 lform = makePreparedFieldLambdaForm(formOp, isVolatile, isValue, isFlatValue, ftypeKind);
689 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
690 return lform;
691 }
692
693 private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
694
695 private static Kind getFieldKind(boolean isGetter, boolean isVolatile, boolean isFlatValue, Wrapper wrapper) {
|
61 member.getReferenceKind() == REF_invokeInterface &&
62 member.isMethod() && !member.isAbstract()) {
63 // Check for corner case: invokeinterface of Object method
64 MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
65 m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
66 if (m != null && m.isPublic()) {
67 assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong
68 member = m;
69 }
70 }
71
72 this.member = member;
73 }
74
75 // Factory methods:
76 static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
77 MethodType mtype = member.getMethodOrFieldType();
78 if (!member.isStatic()) {
79 if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
80 throw new InternalError(member.toString());
81 mtype = mtype.insertParameterTypes(0, refc.asPrimaryType());
82 }
83 if (!member.isField()) {
84 // refKind reflects the original type of lookup via findSpecial or
85 // findVirtual etc.
86 switch (refKind) {
87 case REF_invokeSpecial: {
88 member = member.asSpecial();
89 // if caller is an interface we need to adapt to get the
90 // receiver check inserted
91 if (callerClass == null) {
92 throw new InternalError("callerClass must not be null for REF_invokeSpecial");
93 }
94 LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
95 return new Special(mtype, lform, member, callerClass);
96 }
97 case REF_invokeInterface: {
98 // for interfaces we always need the receiver typecheck,
99 // so we always pass 'true' to ensure we adapt if needed
100 // to include the REF_invokeSpecial case
101 LambdaForm lform = preparedLambdaForm(member, true);
102 return new Interface(mtype, lform, member, refc);
103 }
104 default: {
105 LambdaForm lform = preparedLambdaForm(member);
106 return new DirectMethodHandle(mtype, lform, member);
107 }
108 }
109 } else {
110 LambdaForm lform = preparedFieldLambdaForm(member);
111 if (member.isStatic()) {
112 long offset = MethodHandleNatives.staticFieldOffset(member);
113 Object base = MethodHandleNatives.staticFieldBase(member);
114 return member.isInlineableField() ? new StaticValueAccessor(mtype, lform, member, base, offset)
115 : new StaticAccessor(mtype, lform, member, base, offset);
116 } else {
117 long offset = MethodHandleNatives.objectFieldOffset(member);
118 assert(offset == (int)offset);
119 return member.isInlineableField() ? new ValueAccessor(mtype, lform, member, (int)offset)
120 : new Accessor(mtype, lform, member, (int)offset);
121
122 }
123 }
124 }
125 static DirectMethodHandle make(Class<?> refc, MemberName member) {
126 byte refKind = member.getReferenceKind();
127 if (refKind == REF_invokeSpecial)
128 refKind = REF_invokeVirtual;
129 return make(refKind, refc, member, null /* no callerClass context */);
130 }
131 static DirectMethodHandle make(MemberName member) {
132 if (member.isConstructor() && member.getReturnType() == void.class)
133 return makeAllocator(member);
134 return make(member.getDeclaringClass(), member);
135 }
136 private static DirectMethodHandle makeAllocator(MemberName ctor) {
137 assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
138 Class<?> instanceClass = ctor.getDeclaringClass().asPrimaryType(); // convert to Q-Type
139 ctor = ctor.asConstructor();
140 assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
141 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
142 LambdaForm lform = preparedLambdaForm(ctor);
143 MemberName init = ctor.asSpecial();
144 assert(init.getMethodType().returnType() == void.class);
145 return new Constructor(mtype, lform, ctor, init, instanceClass);
146 }
147
148 @Override
149 BoundMethodHandle rebind() {
150 return BoundMethodHandle.makeReinvoker(this);
151 }
152
153 @Override
154 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
155 assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses
156 return new DirectMethodHandle(mt, lf, member);
157 }
158
648 return isValue ? FT_CHECKED_VALUE : FT_CHECKED_REF;
649 }
650
651 /**
652 * Create a LF which can access the given field.
653 * Cache and share this structure among all fields with
654 * the same basicType and refKind.
655 */
656 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
657 Class<?> ftype = m.getFieldType();
658 byte formOp;
659 switch (m.getReferenceKind()) {
660 case REF_getField: formOp = AF_GETFIELD; break;
661 case REF_putField: formOp = AF_PUTFIELD; break;
662 case REF_getStatic: formOp = AF_GETSTATIC; break;
663 case REF_putStatic: formOp = AF_PUTSTATIC; break;
664 default: throw new InternalError(m.toString());
665 }
666 if (shouldBeInitialized(m)) {
667 // precompute the barrier-free version:
668 preparedFieldLambdaForm(formOp, m.isVolatile(), m.isInlineableField(), m.isFlattened(), ftype);
669 assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
670 (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
671 formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
672 }
673 LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isInlineableField(), m.isFlattened(), ftype);
674 maybeCompile(lform, m);
675 assert(lform.methodType().dropParameterTypes(0, 1)
676 .equals(m.getInvocationType().basicType()))
677 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
678 return lform;
679 }
680
681 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, boolean isValue, boolean isFlatValue, Class<?> ftype) {
682 int ftypeKind = ftypeKind(ftype, isValue);
683 int afIndex = afIndex(formOp, isVolatile, isFlatValue, ftypeKind);
684 LambdaForm lform = ACCESSOR_FORMS[afIndex];
685 if (lform != null) return lform;
686 lform = makePreparedFieldLambdaForm(formOp, isVolatile, isValue, isFlatValue, ftypeKind);
687 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
688 return lform;
689 }
690
691 private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
692
693 private static Kind getFieldKind(boolean isGetter, boolean isVolatile, boolean isFlatValue, Wrapper wrapper) {
|