18
18
import java .lang .reflect .Method ;
19
19
import java .util .Random ;
20
20
21
- import static org .objectweb .asm .Opcodes .*;
22
-
23
21
/**
24
22
* The function call-site class compiler.
25
23
* This cannot use {@link mx.kenzie.foundation} because it is required for
@@ -48,7 +46,7 @@ public Class<?> createClass()
48
46
final Class <?>[] parameters = target .getParameterTypes ();
49
47
final Class <?> expected = source .returnType ();
50
48
final Class <?> result = target .getReturnType ();
51
- if (arguments .length != parameters .length )
49
+ if (arguments .length != parameters .length ) // todo dynamic?
52
50
throw new ScriptRuntimeError ("Function argument count did not match target parameter count." );
53
51
final ClassWriter writer = new ClassWriter (0 );
54
52
writer .visit (Skript .JAVA_VERSION , 0x0001 | 0x1000 , location , null , "java/lang/Object" , null );
@@ -62,13 +60,18 @@ public Class<?> createClass()
62
60
final Class <?> parameter = parameters [i ];
63
61
visitor .visitVarInsn (20 + this .instructionOffset (argument ), i );
64
62
this .boxAtomic (visitor , parameter );
65
- visitor .visitTypeInsn (CHECKCAST , Type .getInternalName (this .getUnboxingType (parameter )));
63
+ visitor .visitTypeInsn (192 , Type .getInternalName (this .getUnboxingType (parameter )));
66
64
this .unbox (visitor , parameter );
67
65
}
68
66
this .invoke (visitor );
69
- this .box (visitor , result );
70
- visitor .visitTypeInsn (CHECKCAST , Type .getInternalName (this .getWrapperType (expected )));
71
- visitor .visitInsn (171 + this .instructionOffset (expected ));
67
+ if (result == void .class ) {
68
+ visitor .visitInsn (1 );
69
+ visitor .visitInsn (176 );
70
+ } else {
71
+ this .box (visitor , result );
72
+ visitor .visitTypeInsn (192 , Type .getInternalName (this .getWrapperType (expected )));
73
+ visitor .visitInsn (171 + this .instructionOffset (expected ));
74
+ }
72
75
visitor .visitMaxs (Math .max (parameters .length + 1 + this .wideIndexOffset (parameters , result ), 1 ), arguments .length );
73
76
visitor .visitEnd ();
74
77
writer .visitEnd ();
@@ -85,38 +88,7 @@ public CallSite getCallSite()
85
88
//region Utilities
86
89
protected void invoke (MethodVisitor visitor ) {
87
90
final boolean special = target .getDeclaringClass ().isInterface ();
88
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (target .getDeclaringClass ()), target .getName (), Type .getMethodDescriptor (target ), special );
89
- }
90
-
91
- protected void doTypeConversion (MethodVisitor visitor , Class <?> from , Class <?> to ) {
92
- if (from == to ) return ;
93
- if (from == void .class || to == void .class ) return ;
94
- if (from .isPrimitive () && to .isPrimitive ()) {
95
- final int opcode ;
96
- if (from == float .class ) {
97
- if (to == double .class ) opcode = F2D ;
98
- else if (to == long .class ) opcode = F2L ;
99
- else opcode = F2I ;
100
- } else if (from == double .class ) {
101
- if (to == float .class ) opcode = D2F ;
102
- else if (to == long .class ) opcode = D2L ;
103
- else opcode = D2I ;
104
- } else if (from == long .class ) {
105
- if (to == float .class ) opcode = L2F ;
106
- else if (to == double .class ) opcode = L2D ;
107
- else opcode = L2I ;
108
- } else {
109
- if (to == float .class ) opcode = I2F ;
110
- else if (to == double .class ) opcode = I2D ;
111
- else if (to == byte .class ) opcode = I2B ;
112
- else if (to == short .class ) opcode = I2S ;
113
- else if (to == char .class ) opcode = I2C ;
114
- else opcode = I2L ;
115
- }
116
- visitor .visitInsn (opcode );
117
- } else if (from .isPrimitive () ^ to .isPrimitive ()) {
118
- throw new IllegalArgumentException ("Type wrapping is currently unsupported due to side-effects: '" + from .getSimpleName () + "' -> '" + to .getSimpleName () + "'" );
119
- } else visitor .visitTypeInsn (CHECKCAST , Type .getInternalName (to ));
91
+ visitor .visitMethodInsn (184 , Type .getInternalName (target .getDeclaringClass ()), target .getName (), Type .getMethodDescriptor (target ), special );
120
92
}
121
93
122
94
protected Class <?> getUnboxingType (Class <?> primitive ) {
@@ -143,48 +115,48 @@ protected Class<?> getWrapperType(Class<?> primitive) {
143
115
144
116
protected void boxAtomic (MethodVisitor visitor , Class <?> parameter ) {
145
117
if (parameter == AtomicVariable .class )
146
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (AtomicVariable .class ), "wrap" , "(Ljava/lang/Object;)" + Type .getDescriptor (AtomicVariable .class ), false );
118
+ visitor .visitMethodInsn (184 , Type .getInternalName (AtomicVariable .class ), "wrap" , "(Ljava/lang/Object;)" + Type .getDescriptor (AtomicVariable .class ), false );
147
119
else
148
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (AtomicVariable .class ), "unwrap" , "(Ljava/lang/Object;)Ljava/lang/Object;" , false );
120
+ visitor .visitMethodInsn (184 , Type .getInternalName (AtomicVariable .class ), "unwrap" , "(Ljava/lang/Object;)Ljava/lang/Object;" , false );
149
121
}
150
122
151
123
protected void unbox (MethodVisitor visitor , Class <?> parameter ) {
152
124
final String source = Type .getInternalName (OperatorHandler .class );
153
125
if (parameter == byte .class )
154
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxB" , "(Ljava/lang/Number;)B" , false );
126
+ visitor .visitMethodInsn (184 , source , "unboxB" , "(Ljava/lang/Number;)B" , false );
155
127
if (parameter == short .class )
156
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxS" , "(Ljava/lang/Number;)S" , false );
128
+ visitor .visitMethodInsn (184 , source , "unboxS" , "(Ljava/lang/Number;)S" , false );
157
129
if (parameter == int .class )
158
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxI" , "(Ljava/lang/Number;)I" , false );
130
+ visitor .visitMethodInsn (184 , source , "unboxI" , "(Ljava/lang/Number;)I" , false );
159
131
if (parameter == long .class )
160
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxJ" , "(Ljava/lang/Number;)J" , false );
132
+ visitor .visitMethodInsn (184 , source , "unboxJ" , "(Ljava/lang/Number;)J" , false );
161
133
if (parameter == float .class )
162
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxF" , "(Ljava/lang/Number;)F" , false );
134
+ visitor .visitMethodInsn (184 , source , "unboxF" , "(Ljava/lang/Number;)F" , false );
163
135
if (parameter == double .class )
164
- visitor .visitMethodInsn (INVOKESTATIC , source , "unboxD" , "(Ljava/lang/Number;)D" , false );
136
+ visitor .visitMethodInsn (184 , source , "unboxD" , "(Ljava/lang/Number;)D" , false );
165
137
if (parameter == boolean .class )
166
- visitor .visitMethodInsn (INVOKESTATIC , source , "unbox" , "(Ljava/lang/Boolean;)Z" , false );
138
+ visitor .visitMethodInsn (184 , source , "unbox" , "(Ljava/lang/Boolean;)Z" , false );
167
139
if (parameter == char .class )
168
- visitor .visitMethodInsn (INVOKESTATIC , source , "unbox" , "(Ljava/lang/Character;)C" , false );
140
+ visitor .visitMethodInsn (184 , source , "unbox" , "(Ljava/lang/Character;)C" , false );
169
141
}
170
142
171
143
protected void box (MethodVisitor visitor , Class <?> value ) {
172
144
if (value == byte .class )
173
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Byte .class ), "valueOf" , "(B)Ljava/lang/Byte;" , false );
145
+ visitor .visitMethodInsn (184 , Type .getInternalName (Byte .class ), "valueOf" , "(B)Ljava/lang/Byte;" , false );
174
146
if (value == short .class )
175
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Short .class ), "valueOf" , "(S)Ljava/lang/Short;" , false );
147
+ visitor .visitMethodInsn (184 , Type .getInternalName (Short .class ), "valueOf" , "(S)Ljava/lang/Short;" , false );
176
148
if (value == int .class )
177
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Integer .class ), "valueOf" , "(I)Ljava/lang/Integer;" , false );
149
+ visitor .visitMethodInsn (184 , Type .getInternalName (Integer .class ), "valueOf" , "(I)Ljava/lang/Integer;" , false );
178
150
if (value == long .class )
179
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Long .class ), "valueOf" , "(J)Ljava/lang/Long;" , false );
151
+ visitor .visitMethodInsn (184 , Type .getInternalName (Long .class ), "valueOf" , "(J)Ljava/lang/Long;" , false );
180
152
if (value == float .class )
181
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Float .class ), "valueOf" , "(F)Ljava/lang/Float;" , false );
153
+ visitor .visitMethodInsn (184 , Type .getInternalName (Float .class ), "valueOf" , "(F)Ljava/lang/Float;" , false );
182
154
if (value == double .class )
183
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Double .class ), "valueOf" , "(D)Ljava/lang/Double;" , false );
155
+ visitor .visitMethodInsn (184 , Type .getInternalName (Double .class ), "valueOf" , "(D)Ljava/lang/Double;" , false );
184
156
if (value == boolean .class )
185
- visitor .visitMethodInsn (INVOKESTATIC , Type .getInternalName (Boolean .class ), "valueOf" , "(Z)Ljava/lang/Boolean;" , false );
157
+ visitor .visitMethodInsn (184 , Type .getInternalName (Boolean .class ), "valueOf" , "(Z)Ljava/lang/Boolean;" , false );
186
158
if (value == void .class )
187
- visitor .visitInsn (ACONST_NULL );
159
+ visitor .visitInsn (1 );
188
160
}
189
161
190
162
protected int wideIndexOffset (Class <?>[] params , Class <?> ret ) {
0 commit comments