1 /* |
1 /* |
2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
45 |
45 |
46 // generic (untyped) invoker for the outgoing call |
46 // generic (untyped) invoker for the outgoing call |
47 private /*lazy*/ MethodHandle genericInvoker; |
47 private /*lazy*/ MethodHandle genericInvoker; |
48 |
48 |
49 // generic (untyped) invoker for the outgoing call; accepts a single Object[] |
49 // generic (untyped) invoker for the outgoing call; accepts a single Object[] |
50 private final /*lazy*/ MethodHandle[] varargsInvokers; |
50 private final /*lazy*/ MethodHandle[] spreadInvokers; |
51 |
51 |
52 // invoker for an unbound callsite |
52 // invoker for an unbound callsite |
53 private /*lazy*/ MethodHandle uninitializedCallSite; |
53 private /*lazy*/ MethodHandle uninitializedCallSite; |
54 |
54 |
55 /** Compute and cache information common to all collecting adapters |
55 /** Compute and cache information common to all collecting adapters |
56 * that implement members of the erasure-family of the given erased type. |
56 * that implement members of the erasure-family of the given erased type. |
57 */ |
57 */ |
58 public Invokers(Access token, MethodType targetType) { |
58 /*non-public*/ Invokers(MethodType targetType) { |
59 Access.check(token); |
|
60 this.targetType = targetType; |
59 this.targetType = targetType; |
61 this.varargsInvokers = new MethodHandle[targetType.parameterCount()+1]; |
60 this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1]; |
62 } |
61 } |
63 |
62 |
64 public static MethodType invokerType(MethodType targetType) { |
63 public static MethodType invokerType(MethodType targetType) { |
65 return targetType.insertParameterTypes(0, MethodHandle.class); |
64 return targetType.insertParameterTypes(0, MethodHandle.class); |
66 } |
65 } |
67 |
66 |
68 public MethodHandle exactInvoker() { |
67 public MethodHandle exactInvoker() { |
69 MethodHandle invoker = exactInvoker; |
68 MethodHandle invoker = exactInvoker; |
70 if (invoker != null) return invoker; |
69 if (invoker != null) return invoker; |
71 try { |
70 try { |
72 invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType); |
71 invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType); |
73 } catch (NoAccessException ex) { |
72 } catch (NoAccessException ex) { |
74 throw new InternalError("JVM cannot find invoker for "+targetType); |
73 throw new InternalError("JVM cannot find invoker for "+targetType); |
75 } |
74 } |
76 assert(invokerType(targetType) == invoker.type()); |
75 assert(invokerType(targetType) == invoker.type()); |
77 exactInvoker = invoker; |
76 exactInvoker = invoker; |
99 invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType)); |
98 invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType)); |
100 erasedInvoker = invoker; |
99 erasedInvoker = invoker; |
101 return invoker; |
100 return invoker; |
102 } |
101 } |
103 |
102 |
104 public MethodHandle varargsInvoker(int objectArgCount) { |
103 public MethodHandle spreadInvoker(int objectArgCount) { |
105 MethodHandle vaInvoker = varargsInvokers[objectArgCount]; |
104 MethodHandle vaInvoker = spreadInvokers[objectArgCount]; |
106 if (vaInvoker != null) return vaInvoker; |
105 if (vaInvoker != null) return vaInvoker; |
107 MethodHandle gInvoker = genericInvoker(); |
106 MethodHandle gInvoker = genericInvoker(); |
108 MethodType vaType = MethodType.genericMethodType(objectArgCount, true); |
107 MethodType vaType = MethodType.genericMethodType(objectArgCount, true); |
109 vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType)); |
108 vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType)); |
110 varargsInvokers[objectArgCount] = vaInvoker; |
109 spreadInvokers[objectArgCount] = vaInvoker; |
111 return vaInvoker; |
110 return vaInvoker; |
112 } |
111 } |
113 |
112 |
114 private static MethodHandle THROW_UCS = null; |
113 private static MethodHandle THROW_UCS = null; |
115 |
114 |
116 public MethodHandle uninitializedCallSite() { |
115 public MethodHandle uninitializedCallSite() { |
117 MethodHandle invoker = uninitializedCallSite; |
116 MethodHandle invoker = uninitializedCallSite; |
118 if (invoker != null) return invoker; |
117 if (invoker != null) return invoker; |
119 if (targetType.parameterCount() > 0) { |
118 if (targetType.parameterCount() > 0) { |
120 MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); |
119 MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); |
121 Invokers invokers0 = MethodTypeImpl.invokers(Access.TOKEN, type0); |
120 Invokers invokers0 = MethodTypeImpl.invokers(type0); |
122 invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), |
121 invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), |
123 0, targetType.parameterList()); |
122 0, targetType.parameterList()); |
124 assert(invoker.type().equals(targetType)); |
123 assert(invoker.type().equals(targetType)); |
125 uninitializedCallSite = invoker; |
124 uninitializedCallSite = invoker; |
126 return invoker; |
125 return invoker; |