22
33import java .lang .reflect .Method ;
44import java .lang .reflect .Modifier ;
5- import java .util .Collections ;
65import java .util .HashSet ;
76import java .util .IdentityHashMap ;
8- import java .util .List ;
9- import java .util .Map ;
107import java .util .Set ;
118
9+ import ai .timefold .jpyinterpreter .implementors .DelegatingInterfaceImplementor ;
1210import ai .timefold .jpyinterpreter .implementors .JavaPythonTypeConversionImplementor ;
1311import ai .timefold .jpyinterpreter .types .BuiltinTypes ;
1412import ai .timefold .jpyinterpreter .types .PythonLikeType ;
1513import ai .timefold .jpyinterpreter .util .MethodVisitorAdapters ;
1614import ai .timefold .jpyinterpreter .util .arguments .ArgumentSpec ;
1715
1816import org .objectweb .asm .ClassWriter ;
19- import org .objectweb .asm .MethodVisitor ;
2017import org .objectweb .asm .Opcodes ;
2118import org .objectweb .asm .Type ;
2219
@@ -251,64 +248,26 @@ private static void createMethodDelegate(ClassWriter classWriter,
251248 interfaceMethodVisitor .visitFieldInsn (Opcodes .GETSTATIC , wrapperInternalName ,
252249 "argumentSpec$" + interfaceMethod .getName (),
253250 Type .getDescriptor (ArgumentSpec .class ));
254- interfaceMethodVisitor .visitLdcInsn (interfaceMethod .getParameterCount ());
255- interfaceMethodVisitor .visitTypeInsn (Opcodes .ANEWARRAY , Type .getInternalName (PythonLikeObject .class ));
256- interfaceMethodVisitor .visitVarInsn (Opcodes .ASTORE , interfaceMethod .getParameterCount () + 2 );
257- for (int i = 0 ; i < interfaceMethod .getParameterCount (); i ++) {
258- var parameterType = interfaceMethod .getParameterTypes ()[i ];
259- interfaceMethodVisitor .visitVarInsn (Opcodes .ALOAD , interfaceMethod .getParameterCount () + 2 );
260- interfaceMethodVisitor .visitLdcInsn (i );
261- interfaceMethodVisitor .visitVarInsn (Type .getType (parameterType ).getOpcode (Opcodes .ILOAD ),
262- i + 1 );
263- if (parameterType .isPrimitive ()) {
264- convertPrimitiveToObjectType (parameterType , interfaceMethodVisitor );
265- }
266- interfaceMethodVisitor .visitVarInsn (Opcodes .ALOAD , interfaceMethod .getParameterCount () + 1 );
267- interfaceMethodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC ,
268- Type .getInternalName (JavaPythonTypeConversionImplementor .class ),
269- "wrapJavaObject" ,
270- Type .getMethodDescriptor (Type .getType (PythonLikeObject .class ), Type .getType (Object .class ), Type .getType (
271- Map .class )),
272- false );
273- interfaceMethodVisitor .visitInsn (Opcodes .AASTORE );
274- }
275251
276252 var functionSignature = delegateType .getMethodType (interfaceMethod .getName ())
277253 .orElseThrow (() -> new IllegalArgumentException (
278254 "Type %s cannot implement interface %s because it missing method %s."
279255 .formatted (delegateType , interfaceMethod .getDeclaringClass (), interfaceMethod )))
280256 .getDefaultFunctionSignature ()
281257 .orElseThrow ();
282-
283- interfaceMethodVisitor .visitVarInsn (Opcodes .ALOAD , interfaceMethod .getParameterCount () + 2 );
284- interfaceMethodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (List .class ),
285- "of" , Type .getMethodDescriptor (Type .getType (List .class ), Type .getType (Object [].class )),
286- true );
287- interfaceMethodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Collections .class ),
288- "emptyMap" , Type .getMethodDescriptor (Type .getType (Map .class )), false );
289- interfaceMethodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (ArgumentSpec .class ),
290- "extractArgumentList" , Type .getMethodDescriptor (
291- Type .getType (List .class ), Type .getType (List .class ), Type .getType (Map .class )),
258+ DelegatingInterfaceImplementor .prepareParametersForMethodCallFromArgumentSpec (
259+ interfaceMethod , interfaceMethodVisitor , functionSignature .getParameterTypes ().length ,
260+ Type .getType (functionSignature .getMethodDescriptor ().getMethodDescriptor ()),
292261 false );
293262
294- for (int i = 0 ; i < functionSignature .getParameterTypes ().length ; i ++) {
295- interfaceMethodVisitor .visitInsn (Opcodes .DUP );
296- interfaceMethodVisitor .visitLdcInsn (i );
297- interfaceMethodVisitor .visitMethodInsn (Opcodes .INVOKEINTERFACE , Type .getInternalName (List .class ),
298- "get" , Type .getMethodDescriptor (Type .getType (Object .class ), Type .INT_TYPE ), true );
299- interfaceMethodVisitor .visitTypeInsn (Opcodes .CHECKCAST ,
300- functionSignature .getParameterTypes ()[i ].getJavaTypeInternalName ());
301- interfaceMethodVisitor .visitInsn (Opcodes .SWAP );
302- }
303- interfaceMethodVisitor .visitInsn (Opcodes .POP );
304263 functionSignature .getMethodDescriptor ().callMethod (interfaceMethodVisitor );
305264
306265 var returnType = interfaceMethod .getReturnType ();
307266 if (returnType .equals (void .class )) {
308267 interfaceMethodVisitor .visitInsn (Opcodes .RETURN );
309268 } else {
310269 if (returnType .isPrimitive ()) {
311- loadBoxedPrimitiveTypeClass (returnType , interfaceMethodVisitor );
270+ DelegatingInterfaceImplementor . loadBoxedPrimitiveTypeClass (returnType , interfaceMethodVisitor );
312271 } else {
313272 interfaceMethodVisitor .visitLdcInsn (Type .getType (returnType ));
314273 }
@@ -320,7 +279,7 @@ private static void createMethodDelegate(ClassWriter classWriter,
320279 PythonLikeObject .class )),
321280 false );
322281 if (returnType .isPrimitive ()) {
323- unboxBoxedPrimitiveType (returnType , interfaceMethodVisitor );
282+ DelegatingInterfaceImplementor . unboxBoxedPrimitiveType (returnType , interfaceMethodVisitor );
324283 interfaceMethodVisitor .visitInsn (Type .getType (returnType ).getOpcode (Opcodes .IRETURN ));
325284 } else {
326285 interfaceMethodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (returnType ));
@@ -330,94 +289,4 @@ private static void createMethodDelegate(ClassWriter classWriter,
330289 interfaceMethodVisitor .visitMaxs (interfaceMethod .getParameterCount () + 2 , 1 );
331290 interfaceMethodVisitor .visitEnd ();
332291 }
333-
334- private static void convertPrimitiveToObjectType (Class <?> primitiveType , MethodVisitor methodVisitor ) {
335- if (primitiveType .equals (boolean .class )) {
336- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Boolean .class ),
337- "valueOf" , Type .getMethodDescriptor (Type .getType (Boolean .class ), Type .BOOLEAN_TYPE ), false );
338- } else if (primitiveType .equals (byte .class )) {
339- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Byte .class ),
340- "valueOf" , Type .getMethodDescriptor (Type .getType (Byte .class ), Type .BYTE_TYPE ), false );
341- } else if (primitiveType .equals (char .class )) {
342- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Character .class ),
343- "valueOf" , Type .getMethodDescriptor (Type .getType (Character .class ), Type .CHAR_TYPE ), false );
344- } else if (primitiveType .equals (short .class )) {
345- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Short .class ),
346- "valueOf" , Type .getMethodDescriptor (Type .getType (Short .class ), Type .SHORT_TYPE ), false );
347- } else if (primitiveType .equals (int .class )) {
348- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Integer .class ),
349- "valueOf" , Type .getMethodDescriptor (Type .getType (Integer .class ), Type .INT_TYPE ), false );
350- } else if (primitiveType .equals (long .class )) {
351- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Long .class ),
352- "valueOf" , Type .getMethodDescriptor (Type .getType (Long .class ), Type .LONG_TYPE ), false );
353- } else if (primitiveType .equals (float .class )) {
354- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Float .class ),
355- "valueOf" , Type .getMethodDescriptor (Type .getType (Float .class ), Type .FLOAT_TYPE ), false );
356- } else if (primitiveType .equals (double .class )) {
357- methodVisitor .visitMethodInsn (Opcodes .INVOKESTATIC , Type .getInternalName (Double .class ),
358- "valueOf" , Type .getMethodDescriptor (Type .getType (Double .class ), Type .DOUBLE_TYPE ), false );
359- } else {
360- throw new IllegalStateException ("Unknown primitive type %s." .formatted (primitiveType ));
361- }
362- }
363-
364- private static void loadBoxedPrimitiveTypeClass (Class <?> primitiveType , MethodVisitor methodVisitor ) {
365- if (primitiveType .equals (boolean .class )) {
366- methodVisitor .visitLdcInsn (Type .getType (Boolean .class ));
367- } else if (primitiveType .equals (byte .class )) {
368- methodVisitor .visitLdcInsn (Type .getType (Byte .class ));
369- } else if (primitiveType .equals (char .class )) {
370- methodVisitor .visitLdcInsn (Type .getType (Character .class ));
371- } else if (primitiveType .equals (short .class )) {
372- methodVisitor .visitLdcInsn (Type .getType (Short .class ));
373- } else if (primitiveType .equals (int .class )) {
374- methodVisitor .visitLdcInsn (Type .getType (Integer .class ));
375- } else if (primitiveType .equals (long .class )) {
376- methodVisitor .visitLdcInsn (Type .getType (Long .class ));
377- } else if (primitiveType .equals (float .class )) {
378- methodVisitor .visitLdcInsn (Type .getType (Float .class ));
379- } else if (primitiveType .equals (double .class )) {
380- methodVisitor .visitLdcInsn (Type .getType (Double .class ));
381- } else {
382- throw new IllegalStateException ("Unknown primitive type %s." .formatted (primitiveType ));
383- }
384- }
385-
386- private static void unboxBoxedPrimitiveType (Class <?> primitiveType , MethodVisitor methodVisitor ) {
387- if (primitiveType .equals (boolean .class )) {
388- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Boolean .class ));
389- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Boolean .class ),
390- "booleanValue" , Type .getMethodDescriptor (Type .BOOLEAN_TYPE ), false );
391- } else if (primitiveType .equals (byte .class )) {
392- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Byte .class ));
393- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Byte .class ),
394- "byteValue" , Type .getMethodDescriptor (Type .BYTE_TYPE ), false );
395- } else if (primitiveType .equals (char .class )) {
396- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Character .class ));
397- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Character .class ),
398- "charValue" , Type .getMethodDescriptor (Type .CHAR_TYPE ), false );
399- } else if (primitiveType .equals (short .class )) {
400- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Short .class ));
401- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Short .class ),
402- "shortValue" , Type .getMethodDescriptor (Type .SHORT_TYPE ), false );
403- } else if (primitiveType .equals (int .class )) {
404- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Integer .class ));
405- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Integer .class ),
406- "intValue" , Type .getMethodDescriptor (Type .INT_TYPE ), false );
407- } else if (primitiveType .equals (long .class )) {
408- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Long .class ));
409- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Long .class ),
410- "longValue" , Type .getMethodDescriptor (Type .LONG_TYPE ), false );
411- } else if (primitiveType .equals (float .class )) {
412- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Float .class ));
413- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Float .class ),
414- "floatValue" , Type .getMethodDescriptor (Type .FLOAT_TYPE ), false );
415- } else if (primitiveType .equals (double .class )) {
416- methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (Double .class ));
417- methodVisitor .visitMethodInsn (Opcodes .INVOKEVIRTUAL , Type .getInternalName (Double .class ),
418- "doubleValue" , Type .getMethodDescriptor (Type .DOUBLE_TYPE ), false );
419- } else {
420- throw new IllegalStateException ("Unknown primitive type %s." .formatted (primitiveType ));
421- }
422- }
423292}
0 commit comments