207 mtypeWithArg = mtypeWithArg
208 .insertParameterTypes(0, Object.class) // insert newly allocated obj
209 .changeReturnType(void.class); // <init> returns void
210 MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
211 try {
212 linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
213 } catch (ReflectiveOperationException ex) {
214 throw newInternalError(ex);
215 }
216 final int DMH_THIS = 0;
217 final int ARG_BASE = 1;
218 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
219 int nameCursor = ARG_LIMIT;
220 final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1);
221 final int GET_MEMBER = nameCursor++;
222 final int LINKER_CALL = nameCursor++;
223 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
224 assert(names.length == nameCursor);
225 if (doesAlloc) {
226 // names = { argx,y,z,... new C, init method }
227 names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
228 names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
229 } else if (needsInit) {
230 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
231 } else {
232 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
233 }
234 assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
235 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
236 assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
237 int result = LAST_RESULT;
238 if (doesAlloc) {
239 assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one
240 System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
241 outArgs[0] = names[NEW_OBJ];
242 result = NEW_OBJ;
243 }
244 names[LINKER_CALL] = new Name(linker, outArgs);
245 lambdaName += "_" + shortenSignature(basicTypeSignature(mtype));
246 LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
247 // This is a tricky bit of code. Don't send it through the LF interpreter.
248 lform.compileToBytecode();
249 return lform;
250 }
251
252 static Object findDirectMethodHandle(Name name) {
253 if (name.function == Lazy.NF_internalMemberName ||
254 name.function == Lazy.NF_internalMemberNameEnsureInit ||
255 name.function == Lazy.NF_constructorMethod) {
256 assert(name.arguments.length == 1);
257 return name.arguments[0];
258 }
259 return null;
260 }
261
262 private static void maybeCompile(LambdaForm lform, MemberName m) {
263 if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
264 // Help along bootstrapping...
265 lform.compileToBytecode();
266 }
267
268 /** Static wrapper for DirectMethodHandle.internalMemberName. */
269 @ForceInline
270 /*non-public*/ static Object internalMemberName(Object mh) {
271 return ((DirectMethodHandle)mh).member;
272 }
273
274 /** Static wrapper for DirectMethodHandle.internalMemberName.
275 * This one also forces initialization.
474 @ForceInline
475 /*non-public*/ static Object staticBase(Object accessorObj) {
476 return ((StaticAccessor)accessorObj).staticBase;
477 }
478
479 @ForceInline
480 /*non-public*/ static long staticOffset(Object accessorObj) {
481 return ((StaticAccessor)accessorObj).staticOffset;
482 }
483
484 @ForceInline
485 /*non-public*/ static Object checkCast(Object mh, Object obj) {
486 return ((DirectMethodHandle) mh).checkCast(obj);
487 }
488
489 Object checkCast(Object obj) {
490 return member.getReturnType().cast(obj);
491 }
492
493 // Caching machinery for field accessors:
494 private static byte
495 AF_GETFIELD = 0,
496 AF_PUTFIELD = 1,
497 AF_GETSTATIC = 2,
498 AF_PUTSTATIC = 3,
499 AF_GETSTATIC_INIT = 4,
500 AF_PUTSTATIC_INIT = 5,
501 AF_LIMIT = 6;
502 // Enumerate the different field kinds using Wrapper,
503 // with an extra case added for checked references.
504 private static int
505 FT_LAST_WRAPPER = Wrapper.values().length-1,
506 FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
507 FT_CHECKED_REF = FT_LAST_WRAPPER+1,
508 FT_LIMIT = FT_LAST_WRAPPER+2;
509 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
510 return ((formOp * FT_LIMIT * 2)
511 + (isVolatile ? FT_LIMIT : 0)
512 + ftypeKind);
513 }
514 private static final LambdaForm[] ACCESSOR_FORMS
515 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
516 private static int ftypeKind(Class<?> ftype) {
517 if (ftype.isPrimitive())
518 return Wrapper.forPrimitiveType(ftype).ordinal();
519 else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
520 return FT_UNCHECKED_REF;
521 else
522 return FT_CHECKED_REF;
523 }
524
525 /**
526 * Create a LF which can access the given field.
527 * Cache and share this structure among all fields with
528 * the same basicType and refKind.
596 if (!isStatic)
597 mtype = mtype.insertParameterTypes(0, Object.class);
598 final int DMH_THIS = 0;
599 final int ARG_BASE = 1;
600 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
601 // if this is for non-static access, the base pointer is stored at this index:
602 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
603 // if this is for write access, the value to be written is stored at this index:
604 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
605 int nameCursor = ARG_LIMIT;
606 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
607 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
608 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
609 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
610 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
611 final int LINKER_CALL = nameCursor++;
612 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
613 final int RESULT = nameCursor-1; // either the call or the cast
614 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
615 if (needsInit)
616 names[INIT_BAR] = new Name(Lazy.NF_ensureInitialized, names[DMH_THIS]);
617 if (needsCast && !isGetter)
618 names[PRE_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
619 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
620 assert(outArgs.length == (isGetter ? 3 : 4));
621 outArgs[0] = UNSAFE;
622 if (isStatic) {
623 outArgs[1] = names[F_HOLDER] = new Name(Lazy.NF_staticBase, names[DMH_THIS]);
624 outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_staticOffset, names[DMH_THIS]);
625 } else {
626 outArgs[1] = names[OBJ_CHECK] = new Name(Lazy.NF_checkBase, names[OBJ_BASE]);
627 outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_fieldOffset, names[DMH_THIS]);
628 }
629 if (!isGetter) {
630 outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
631 }
632 for (Object a : outArgs) assert(a != null);
633 names[LINKER_CALL] = new Name(linker, outArgs);
634 if (needsCast && isGetter)
635 names[POST_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
636 for (Name n : names) assert(n != null);
637 String fieldOrStatic = (isStatic ? "Static" : "Field");
638 String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging
639 if (needsCast) lambdaName += "Cast";
640 if (needsInit) lambdaName += "Init";
641 return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
642 }
643
644 /**
645 * Pre-initialized NamedFunctions for bootstrapping purposes.
646 * Factored in an inner class to delay initialization until first usage.
647 */
648 private static class Lazy {
649 static final NamedFunction
650 NF_internalMemberName,
651 NF_internalMemberNameEnsureInit,
652 NF_ensureInitialized,
653 NF_fieldOffset,
654 NF_checkBase,
655 NF_staticBase,
656 NF_staticOffset,
657 NF_checkCast,
658 NF_allocateInstance,
659 NF_constructorMethod;
660 static {
661 try {
662 NamedFunction nfs[] = {
663 NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
664 .getDeclaredMethod("internalMemberName", Object.class)),
665 NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
666 .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
667 NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
668 .getDeclaredMethod("ensureInitialized", Object.class)),
669 NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
670 .getDeclaredMethod("fieldOffset", Object.class)),
671 NF_checkBase = new NamedFunction(DirectMethodHandle.class
672 .getDeclaredMethod("checkBase", Object.class)),
673 NF_staticBase = new NamedFunction(DirectMethodHandle.class
674 .getDeclaredMethod("staticBase", Object.class)),
675 NF_staticOffset = new NamedFunction(DirectMethodHandle.class
676 .getDeclaredMethod("staticOffset", Object.class)),
677 NF_checkCast = new NamedFunction(DirectMethodHandle.class
678 .getDeclaredMethod("checkCast", Object.class, Object.class)),
679 NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
680 .getDeclaredMethod("allocateInstance", Object.class)),
681 NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
682 .getDeclaredMethod("constructorMethod", Object.class))
683 };
684 for (NamedFunction nf : nfs) {
685 // Each nf must be statically invocable or we get tied up in our bootstraps.
686 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
687 nf.resolve();
688 }
689 } catch (ReflectiveOperationException ex) {
690 throw newInternalError(ex);
691 }
692 }
693 }
694 }
|
207 mtypeWithArg = mtypeWithArg
208 .insertParameterTypes(0, Object.class) // insert newly allocated obj
209 .changeReturnType(void.class); // <init> returns void
210 MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
211 try {
212 linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
213 } catch (ReflectiveOperationException ex) {
214 throw newInternalError(ex);
215 }
216 final int DMH_THIS = 0;
217 final int ARG_BASE = 1;
218 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
219 int nameCursor = ARG_LIMIT;
220 final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1);
221 final int GET_MEMBER = nameCursor++;
222 final int LINKER_CALL = nameCursor++;
223 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
224 assert(names.length == nameCursor);
225 if (doesAlloc) {
226 // names = { argx,y,z,... new C, init method }
227 names[NEW_OBJ] = new Name(getConstantFunction(NF_allocateInstance), names[DMH_THIS]);
228 names[GET_MEMBER] = new Name(getConstantFunction(NF_constructorMethod), names[DMH_THIS]);
229 } else if (needsInit) {
230 names[GET_MEMBER] = new Name(getConstantFunction(NF_internalMemberNameEnsureInit), names[DMH_THIS]);
231 } else {
232 names[GET_MEMBER] = new Name(getConstantFunction(NF_internalMemberName), names[DMH_THIS]);
233 }
234 assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
235 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
236 assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
237 int result = LAST_RESULT;
238 if (doesAlloc) {
239 assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one
240 System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
241 outArgs[0] = names[NEW_OBJ];
242 result = NEW_OBJ;
243 }
244 names[LINKER_CALL] = new Name(linker, outArgs);
245 lambdaName += "_" + shortenSignature(basicTypeSignature(mtype));
246 LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
247 // This is a tricky bit of code. Don't send it through the LF interpreter.
248 lform.compileToBytecode();
249 return lform;
250 }
251
252 static Object findDirectMethodHandle(Name name) {
253 if (Objects.equals(name.function, getConstantFunction(NF_internalMemberName)) ||
254 Objects.equals(name.function, getConstantFunction(NF_internalMemberNameEnsureInit)) ||
255 Objects.equals(name.function, getConstantFunction(NF_constructorMethod))) {
256 assert(name.arguments.length == 1);
257 return name.arguments[0];
258 }
259 return null;
260 }
261
262 private static void maybeCompile(LambdaForm lform, MemberName m) {
263 if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
264 // Help along bootstrapping...
265 lform.compileToBytecode();
266 }
267
268 /** Static wrapper for DirectMethodHandle.internalMemberName. */
269 @ForceInline
270 /*non-public*/ static Object internalMemberName(Object mh) {
271 return ((DirectMethodHandle)mh).member;
272 }
273
274 /** Static wrapper for DirectMethodHandle.internalMemberName.
275 * This one also forces initialization.
474 @ForceInline
475 /*non-public*/ static Object staticBase(Object accessorObj) {
476 return ((StaticAccessor)accessorObj).staticBase;
477 }
478
479 @ForceInline
480 /*non-public*/ static long staticOffset(Object accessorObj) {
481 return ((StaticAccessor)accessorObj).staticOffset;
482 }
483
484 @ForceInline
485 /*non-public*/ static Object checkCast(Object mh, Object obj) {
486 return ((DirectMethodHandle) mh).checkCast(obj);
487 }
488
489 Object checkCast(Object obj) {
490 return member.getReturnType().cast(obj);
491 }
492
493 // Caching machinery for field accessors:
494 private static final byte
495 AF_GETFIELD = 0,
496 AF_PUTFIELD = 1,
497 AF_GETSTATIC = 2,
498 AF_PUTSTATIC = 3,
499 AF_GETSTATIC_INIT = 4,
500 AF_PUTSTATIC_INIT = 5,
501 AF_LIMIT = 6;
502 // Enumerate the different field kinds using Wrapper,
503 // with an extra case added for checked references.
504 private static final int
505 FT_LAST_WRAPPER = Wrapper.values().length-1,
506 FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
507 FT_CHECKED_REF = FT_LAST_WRAPPER+1,
508 FT_LIMIT = FT_LAST_WRAPPER+2;
509
510 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
511 return ((formOp * FT_LIMIT * 2)
512 + (isVolatile ? FT_LIMIT : 0)
513 + ftypeKind);
514 }
515 private static final LambdaForm[] ACCESSOR_FORMS
516 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
517 private static int ftypeKind(Class<?> ftype) {
518 if (ftype.isPrimitive())
519 return Wrapper.forPrimitiveType(ftype).ordinal();
520 else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
521 return FT_UNCHECKED_REF;
522 else
523 return FT_CHECKED_REF;
524 }
525
526 /**
527 * Create a LF which can access the given field.
528 * Cache and share this structure among all fields with
529 * the same basicType and refKind.
597 if (!isStatic)
598 mtype = mtype.insertParameterTypes(0, Object.class);
599 final int DMH_THIS = 0;
600 final int ARG_BASE = 1;
601 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
602 // if this is for non-static access, the base pointer is stored at this index:
603 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
604 // if this is for write access, the value to be written is stored at this index:
605 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
606 int nameCursor = ARG_LIMIT;
607 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
608 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
609 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
610 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
611 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
612 final int LINKER_CALL = nameCursor++;
613 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
614 final int RESULT = nameCursor-1; // either the call or the cast
615 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
616 if (needsInit)
617 names[INIT_BAR] = new Name(getConstantFunction(NF_ensureInitialized), names[DMH_THIS]);
618 if (needsCast && !isGetter)
619 names[PRE_CAST] = new Name(getConstantFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
620 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
621 assert(outArgs.length == (isGetter ? 3 : 4));
622 outArgs[0] = UNSAFE;
623 if (isStatic) {
624 outArgs[1] = names[F_HOLDER] = new Name(getConstantFunction(NF_staticBase), names[DMH_THIS]);
625 outArgs[2] = names[F_OFFSET] = new Name(getConstantFunction(NF_staticOffset), names[DMH_THIS]);
626 } else {
627 outArgs[1] = names[OBJ_CHECK] = new Name(getConstantFunction(NF_checkBase), names[OBJ_BASE]);
628 outArgs[2] = names[F_OFFSET] = new Name(getConstantFunction(NF_fieldOffset), names[DMH_THIS]);
629 }
630 if (!isGetter) {
631 outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
632 }
633 for (Object a : outArgs) assert(a != null);
634 names[LINKER_CALL] = new Name(linker, outArgs);
635 if (needsCast && isGetter)
636 names[POST_CAST] = new Name(getConstantFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
637 for (Name n : names) assert(n != null);
638 String fieldOrStatic = (isStatic ? "Static" : "Field");
639 String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging
640 if (needsCast) lambdaName += "Cast";
641 if (needsInit) lambdaName += "Init";
642 return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
643 }
644
645 private static NamedFunction getConstantFunction(int idx) {
646 NamedFunction function = FUNCTIONS[idx];
647 if (function != null) {
648 return function;
649 }
650 return setCachedFunction(idx, makeConstantFunction(idx));
651 }
652
653 private static synchronized NamedFunction setCachedFunction(int idx, final NamedFunction function) {
654 // Simulate a CAS, to avoid racy duplication of results.
655 NamedFunction prev = FUNCTIONS[idx];
656 if (prev != null) {
657 return prev;
658 }
659 function.resolve();
660 UNSAFE.storeFence();
661 FUNCTIONS[idx] = function;
662 return function;
663 }
664
665 // Indexes into constant functions:
666 private static final int
667 NF_internalMemberName = 0,
668 NF_internalMemberNameEnsureInit = 1,
669 NF_ensureInitialized = 2,
670 NF_fieldOffset = 3,
671 NF_checkBase = 4,
672 NF_staticBase = 5,
673 NF_staticOffset = 6,
674 NF_checkCast = 7,
675 NF_allocateInstance = 8,
676 NF_constructorMethod = 9,
677 NF_LIMIT = 10;
678
679 /**
680 * Statically initialized NamedFunctions for bootstrapping purposes.
681 * Delay initialization until first usage.
682 */
683 private static final @Stable NamedFunction[] FUNCTIONS = new NamedFunction[NF_LIMIT];
684
685 private static NamedFunction makeConstantFunction(int idx) {
686 try {
687 switch (idx) {
688 case NF_internalMemberName:
689 return new NamedFunction(DirectMethodHandle.class
690 .getDeclaredMethod("internalMemberName", Object.class));
691 case NF_internalMemberNameEnsureInit:
692 return new NamedFunction(DirectMethodHandle.class
693 .getDeclaredMethod("internalMemberNameEnsureInit", Object.class));
694 case NF_ensureInitialized:
695 return new NamedFunction(DirectMethodHandle.class
696 .getDeclaredMethod("ensureInitialized", Object.class));
697 case NF_fieldOffset:
698 return new NamedFunction(DirectMethodHandle.class
699 .getDeclaredMethod("fieldOffset", Object.class));
700 case NF_checkBase:
701 return new NamedFunction(DirectMethodHandle.class
702 .getDeclaredMethod("checkBase", Object.class));
703 case NF_staticBase:
704 return new NamedFunction(DirectMethodHandle.class
705 .getDeclaredMethod("staticBase", Object.class));
706 case NF_staticOffset:
707 return new NamedFunction(DirectMethodHandle.class
708 .getDeclaredMethod("staticOffset", Object.class));
709 case NF_checkCast:
710 return new NamedFunction(DirectMethodHandle.class
711 .getDeclaredMethod("checkCast", Object.class, Object.class));
712 case NF_allocateInstance:
713 return new NamedFunction(DirectMethodHandle.class
714 .getDeclaredMethod("allocateInstance", Object.class));
715 case NF_constructorMethod:
716 return new NamedFunction(DirectMethodHandle.class
717 .getDeclaredMethod("constructorMethod", Object.class));
718 }
719 } catch (ReflectiveOperationException ex) {
720 throw newInternalError(ex);
721 }
722 throw newInternalError("Unknown function index: " + idx);
723 }
724 }
|