71
71
import static jdk .internal .org .objectweb .asm .Opcodes .LALOAD ;
72
72
import static jdk .internal .org .objectweb .asm .Opcodes .LASTORE ;
73
73
import static jdk .internal .org .objectweb .asm .Opcodes .LLOAD ;
74
+ import static jdk .internal .org .objectweb .asm .Opcodes .NEW ;
74
75
import static jdk .internal .org .objectweb .asm .Opcodes .NEWARRAY ;
75
76
import static jdk .internal .org .objectweb .asm .Opcodes .PUTFIELD ;
76
77
import static jdk .internal .org .objectweb .asm .Opcodes .PUTSTATIC ;
@@ -95,6 +96,12 @@ class MemoryAccessVarHandleGenerator {
95
96
private final static MethodHandle ADD_OFFSETS_HANDLE ;
96
97
private final static MethodHandle MUL_OFFSETS_HANDLE ;
97
98
99
+ private final static MethodType CONSTR_TYPE = MethodType .methodType (void .class , VarForm .class ,
100
+ boolean .class , long .class , long .class , long .class , boolean .class , long [].class );
101
+ // MemoryAccessVarHandleBase
102
+ private final static MethodType SUPER_CONTR_TYPE = MethodType .methodType (void .class , VarForm .class ,
103
+ boolean .class , long .class , long .class , long .class , boolean .class );
104
+
98
105
static {
99
106
helperClassCache = new HashMap <>();
100
107
helperClassCache .put (byte .class , MemoryAccessVarHandleByteHelper .class );
@@ -140,7 +147,7 @@ class MemoryAccessVarHandleGenerator {
140
147
Arrays .fill (components , long .class );
141
148
this .form = new VarForm (BASE_CLASS , MemoryAddressProxy .class , carrier , components );
142
149
this .helperClass = helperClassCache .get (carrier );
143
- this .implClassName = helperClass . getName (). replace ( '.' , '/' ) + dimensions ;
150
+ this .implClassName = internalName ( helperClass ) + dimensions ;
144
151
// live constants
145
152
Class <?>[] intermediate = new Class <?>[dimensions ];
146
153
Arrays .fill (intermediate , long .class );
@@ -164,8 +171,7 @@ MethodHandle generateHandleFactory() {
164
171
165
172
VarForm form = new VarForm (implCls , MemoryAddressProxy .class , carrier , components );
166
173
167
- MethodType constrType = MethodType .methodType (void .class , VarForm .class , boolean .class , long .class , long .class , long .class , long [].class );
168
- MethodHandle constr = lookup .findConstructor (implCls , constrType );
174
+ MethodHandle constr = lookup .findConstructor (implCls , CONSTR_TYPE );
169
175
constr = MethodHandles .insertArguments (constr , 0 , form );
170
176
return constr ;
171
177
} catch (Throwable ex ) {
@@ -202,6 +208,9 @@ byte[] generateClassBytes() {
202
208
203
209
addCarrierAccessor (cw );
204
210
211
+ addAsExact (cw );
212
+ addAsGeneric (cw );
213
+
205
214
for (VarHandle .AccessMode mode : VarHandle .AccessMode .values ()) {
206
215
addAccessModeMethodIfNeeded (mode , cw );
207
216
}
@@ -253,23 +262,23 @@ void addStaticInitializer(ClassWriter cw) {
253
262
}
254
263
255
264
void addConstructor (ClassWriter cw ) {
256
- MethodType constrType = MethodType .methodType (void .class , VarForm .class , boolean .class , long .class , long .class , long .class , long [].class );
257
- MethodVisitor mv = cw .visitMethod (0 , "<init>" , constrType .toMethodDescriptorString (), null , null );
265
+ MethodVisitor mv = cw .visitMethod (0 , "<init>" , CONSTR_TYPE .toMethodDescriptorString (), null , null );
258
266
mv .visitCode ();
259
267
//super call
260
268
mv .visitVarInsn (ALOAD , 0 );
261
- mv .visitVarInsn (ALOAD , 1 );
269
+ mv .visitVarInsn (ALOAD , 1 ); // vform
262
270
mv .visitTypeInsn (CHECKCAST , Type .getInternalName (VarForm .class ));
263
- mv .visitVarInsn (ILOAD , 2 );
264
- mv .visitVarInsn (LLOAD , 3 );
265
- mv .visitVarInsn (LLOAD , 5 );
266
- mv .visitVarInsn (LLOAD , 7 );
271
+ mv .visitVarInsn (ILOAD , 2 ); // be
272
+ mv .visitVarInsn (LLOAD , 3 ); // length
273
+ mv .visitVarInsn (LLOAD , 5 ); // offset
274
+ mv .visitVarInsn (LLOAD , 7 ); // alignmentMask
275
+ mv .visitVarInsn (ILOAD , 9 ); // exact
267
276
mv .visitMethodInsn (INVOKESPECIAL , Type .getInternalName (BASE_CLASS ), "<init>" ,
268
- MethodType . methodType ( void . class , VarForm . class , boolean . class , long . class , long . class , long . class ) .toMethodDescriptorString (), false );
277
+ SUPER_CONTR_TYPE .toMethodDescriptorString (), false );
269
278
//init dimensions
270
279
for (int i = 0 ; i < dimensions ; i ++) {
271
280
mv .visitVarInsn (ALOAD , 0 );
272
- mv .visitVarInsn (ALOAD , 9 );
281
+ mv .visitVarInsn (ALOAD , 10 );
273
282
mv .visitLdcInsn (i );
274
283
mv .visitInsn (LALOAD );
275
284
mv .visitFieldInsn (PUTFIELD , implClassName , "dim" + i , "J" );
@@ -280,11 +289,10 @@ void addConstructor(ClassWriter cw) {
280
289
}
281
290
282
291
void addAccessModeTypeMethod (ClassWriter cw ) {
283
- MethodType modeMethType = MethodType .methodType (MethodType .class , VarHandle .AccessMode .class );
292
+ MethodType modeMethType = MethodType .methodType (MethodType .class , VarHandle .AccessType .class );
284
293
MethodVisitor mv = cw .visitMethod (ACC_FINAL , "accessModeTypeUncached" , modeMethType .toMethodDescriptorString (), null , null );
285
294
mv .visitCode ();
286
295
mv .visitVarInsn (ALOAD , 1 );
287
- mv .visitFieldInsn (GETFIELD , Type .getInternalName (VarHandle .AccessMode .class ), "at" , VarHandle .AccessType .class .descriptorString ());
288
296
mv .visitLdcInsn (Type .getType (MemoryAddressProxy .class ));
289
297
mv .visitTypeInsn (CHECKCAST , Type .getInternalName (Class .class ));
290
298
mv .visitFieldInsn (GETSTATIC , implClassName , "carrier" , Class .class .descriptorString ());
@@ -409,6 +417,38 @@ void addCarrierAccessor(ClassWriter cw) {
409
417
mv .visitEnd ();
410
418
}
411
419
420
+ private void addAsExact (ClassWriter cw ) {
421
+ addAsExactOrAsGeneric (cw , "asExact" , true );
422
+ }
423
+
424
+ private void addAsGeneric (ClassWriter cw ) {
425
+ addAsExactOrAsGeneric (cw , "asGeneric" , false );
426
+ }
427
+
428
+ private void addAsExactOrAsGeneric (ClassWriter cw , String name , boolean exact ) {
429
+ MethodVisitor mv = cw .visitMethod (ACC_FINAL , name , "()Ljava/lang/invoke/VarHandle;" , null , null );
430
+ mv .visitCode ();
431
+ mv .visitTypeInsn (NEW , implClassName );
432
+ mv .visitInsn (DUP );
433
+ mv .visitVarInsn (ALOAD , 0 );
434
+ mv .visitFieldInsn (GETFIELD , internalName (VarHandle .class ), "vform" , VarForm .class .descriptorString ());
435
+ mv .visitVarInsn (ALOAD , 0 );
436
+ mv .visitFieldInsn (GETFIELD , internalName (MemoryAccessVarHandleBase .class ), "be" , boolean .class .descriptorString ());
437
+ mv .visitVarInsn (ALOAD , 0 );
438
+ mv .visitFieldInsn (GETFIELD , internalName (MemoryAccessVarHandleBase .class ), "length" , long .class .descriptorString ());
439
+ mv .visitVarInsn (ALOAD , 0 );
440
+ mv .visitFieldInsn (GETFIELD , internalName (MemoryAccessVarHandleBase .class ), "offset" , long .class .descriptorString ());
441
+ mv .visitVarInsn (ALOAD , 0 );
442
+ mv .visitFieldInsn (GETFIELD , internalName (MemoryAccessVarHandleBase .class ), "alignmentMask" , long .class .descriptorString ());
443
+ mv .visitIntInsn (BIPUSH , exact ? 1 : 0 );
444
+ mv .visitVarInsn (ALOAD , 0 );
445
+ mv .visitMethodInsn (INVOKEVIRTUAL , implClassName , "strides" , "()[J" , false );
446
+ mv .visitMethodInsn (INVOKESPECIAL , implClassName , "<init>" , CONSTR_TYPE .descriptorString (), false );
447
+ mv .visitInsn (ARETURN );
448
+ mv .visitMaxs (0 , 0 );
449
+ mv .visitEnd ();
450
+ }
451
+
412
452
// shared code generation helpers
413
453
414
454
private static int getSlotsForType (Class <?> c ) {
@@ -418,6 +458,10 @@ private static int getSlotsForType(Class<?> c) {
418
458
return 1 ;
419
459
}
420
460
461
+ private static String internalName (Class <?> cls ) {
462
+ return cls .getName ().replace ('.' , '/' );
463
+ }
464
+
421
465
/**
422
466
* Emits an actual return instruction conforming to the given return type.
423
467
*/
0 commit comments