11
11
import java .util .*;
12
12
import java .util .concurrent .*;
13
13
14
- import static org .objectweb .asm .Opcodes .*;
15
-
16
14
public class LambdaReifier {
17
15
18
16
// These globals are used for communicating with the Java agent which
19
17
// is spying on the LambdaMetafactory's dynamically generated bytecode.
20
18
// We expect only one class being processed at a time, so it should
21
19
// be an error if these collections contain more than one element.
22
20
private static final BlockingDeque <Handle > currentLambdaImplMethod = new LinkedBlockingDeque <>(1 );
21
+ private static final BlockingDeque <Handle > currentLambdaBridgeMethod = new LinkedBlockingDeque <>(1 );
23
22
private static final BlockingDeque <Type > currentInvokedType = new LinkedBlockingDeque <>(1 );
24
23
private static final BlockingDeque <String > currentLambdaClass = new LinkedBlockingDeque <>(1 );
25
24
26
- public static LambdaFactoryMethod reifyLambdaClass (Handle lambdaImplMethod , Class <?> invoker , String invokedName , Type invokedType , Handle bsm , Object [] bsmArgs ) {
25
+ public static LambdaFactoryMethod reifyLambdaClass (Handle lambdaImplMethod , Handle lambdaBridgeMethod ,
26
+ Class <?> invoker , String invokedName , Type invokedType , Handle bsm , Object [] bsmArgs ) {
27
27
try {
28
28
setLambdaImplMethod (lambdaImplMethod );
29
+ setLambdaBridgeMethod (lambdaBridgeMethod );
29
30
setInvokedType (invokedType );
30
31
31
32
// Causes the lambda class to be loaded. Retrolambda's Java agent
@@ -46,6 +47,10 @@ private static void setLambdaImplMethod(Handle lambdaImplMethod) {
46
47
currentLambdaImplMethod .push (lambdaImplMethod );
47
48
}
48
49
50
+ private static void setLambdaBridgeMethod (Handle lambdaBridgeMethod ) {
51
+ currentLambdaBridgeMethod .push (lambdaBridgeMethod );
52
+ }
53
+
49
54
private static void setInvokedType (Type invokedType ) {
50
55
currentInvokedType .push (invokedType );
51
56
}
@@ -58,6 +63,10 @@ public static Handle getLambdaImplMethod() {
58
63
return currentLambdaImplMethod .getFirst ();
59
64
}
60
65
66
+ public static Handle getLambdaBridgeMethod () {
67
+ return currentLambdaBridgeMethod .getFirst ();
68
+ }
69
+
61
70
public static LambdaFactoryMethod getLambdaFactoryMethod () {
62
71
String lambdaClass = currentLambdaClass .getFirst ();
63
72
Type invokedType = currentInvokedType .getFirst ();
@@ -66,6 +75,7 @@ public static LambdaFactoryMethod getLambdaFactoryMethod() {
66
75
67
76
private static void resetGlobals () {
68
77
currentLambdaImplMethod .clear ();
78
+ currentLambdaBridgeMethod .clear ();
69
79
currentInvokedType .clear ();
70
80
currentLambdaClass .clear ();
71
81
}
@@ -77,12 +87,12 @@ private static CallSite callBootstrapMethod(Class<?> invoker, String invokedName
77
87
List <Object > args = new ArrayList <>();
78
88
args .add (caller );
79
89
args .add (invokedName );
80
- args .add (toMethodType (invokedType , cl ));
90
+ args .add (Types . toMethodType (invokedType , cl ));
81
91
for (Object arg : bsmArgs ) {
82
- args .add (asmToJdkType (arg , cl , caller ));
92
+ args .add (Types . asmToJdkType (arg , cl , caller ));
83
93
}
84
94
85
- MethodHandle bootstrapMethod = toMethodHandle (bsm , cl , caller );
95
+ MethodHandle bootstrapMethod = Types . toMethodHandle (bsm , cl , caller );
86
96
return (CallSite ) bootstrapMethod .invokeWithArguments (args );
87
97
}
88
98
@@ -91,41 +101,4 @@ private static MethodHandles.Lookup getLookup(Class<?> targetClass) throws Excep
91
101
ctor .setAccessible (true );
92
102
return ctor .newInstance (targetClass );
93
103
}
94
-
95
- private static Object asmToJdkType (Object arg , ClassLoader classLoader , MethodHandles .Lookup caller ) throws Exception {
96
- if (arg instanceof Type ) {
97
- return toMethodType ((Type ) arg , classLoader );
98
- } else if (arg instanceof Handle ) {
99
- return toMethodHandle ((Handle ) arg , classLoader , caller );
100
- } else {
101
- return arg ;
102
- }
103
- }
104
-
105
- private static MethodType toMethodType (Type type , ClassLoader classLoader ) {
106
- return MethodType .fromMethodDescriptorString (type .getInternalName (), classLoader );
107
- }
108
-
109
- private static MethodHandle toMethodHandle (Handle handle , ClassLoader classLoader , MethodHandles .Lookup lookup ) throws Exception {
110
- MethodType type = MethodType .fromMethodDescriptorString (handle .getDesc (), classLoader );
111
- Class <?> owner = classLoader .loadClass (handle .getOwner ().replace ('/' , '.' ));
112
-
113
- switch (handle .getTag ()) {
114
- case H_INVOKESTATIC :
115
- return lookup .findStatic (owner , handle .getName (), type );
116
-
117
- case H_INVOKEVIRTUAL :
118
- case H_INVOKEINTERFACE :
119
- return lookup .findVirtual (owner , handle .getName (), type );
120
-
121
- case H_INVOKESPECIAL :
122
- return lookup .findSpecial (owner , handle .getName (), type , owner );
123
-
124
- case H_NEWINVOKESPECIAL :
125
- return lookup .findConstructor (owner , type );
126
-
127
- default :
128
- throw new AssertionError ("Unexpected handle type: " + handle );
129
- }
130
- }
131
104
}
0 commit comments