266266
267267import java .lang .invoke .MethodHandle ;
268268import java .lang .invoke .MethodType ;
269+ import java .util .Objects ;
269270
271+ import com .oracle .svm .core .NeverInline ;
272+ import com .oracle .svm .core .invoke .Target_java_lang_invoke_MemberName ;
270273import com .oracle .svm .core .jdk .InternalVMMethod ;
274+ import com .oracle .svm .core .methodhandles .MethodHandleInterpreterUtils ;
271275import com .oracle .svm .core .util .VMError ;
272276import com .oracle .svm .espresso .classfile .ConstantPool ;
277+ import com .oracle .svm .espresso .shared .meta .SignaturePolymorphicIntrinsic ;
273278import com .oracle .svm .interpreter .debug .DebuggerEvents ;
274279import com .oracle .svm .interpreter .debug .EventKind ;
275280import com .oracle .svm .interpreter .debug .SteppingControl ;
@@ -364,7 +369,7 @@ public static Object execute(InterpreterResolvedJavaMethod method, InterpreterFr
364369 public static Object execute (InterpreterResolvedJavaMethod method , Object [] args , boolean forceStayInInterpreter ) {
365370 InterpreterFrame frame = EspressoFrame .allocate (method .getMaxLocals (), method .getMaxStackSize (), args );
366371
367- InterpreterUtil .guarantee (!method .isNative (), "trying to interpret native method %s" , method );
372+ InterpreterUtil .guarantee (!method .isNative () || method . getSignaturePolymorphicIntrinsic () != null , "trying to interpret native method %s" , method );
368373
369374 initializeFrame (frame , method );
370375 return execute0 (method , frame , forceStayInInterpreter );
@@ -379,8 +384,13 @@ private static Object execute0(InterpreterResolvedJavaMethod method, Interpreter
379384 assert lockTarget != null ;
380385 InterpreterToVM .monitorEnter (frame , nullCheck (lockTarget ));
381386 }
382- int startTop = startingStackOffset (method .getMaxLocals ());
383- return Root .executeBodyFromBCI (frame , method , 0 , startTop , stayInInterpreter );
387+ SignaturePolymorphicIntrinsic intrinsic = method .getSignaturePolymorphicIntrinsic ();
388+ if (intrinsic != null ) {
389+ return IntrinsicRoot .execute (frame , method , intrinsic , stayInInterpreter );
390+ } else {
391+ int startTop = startingStackOffset (method .getMaxLocals ());
392+ return Root .executeBodyFromBCI (frame , method , 0 , startTop , stayInInterpreter );
393+ }
384394 } finally {
385395 InterpreterToVM .releaseInterpreterFrameLocks (frame );
386396 }
@@ -467,8 +477,144 @@ private static void traceInterpreterException(InterpreterResolvedJavaMethod meth
467477 .string ("/top=" ).unsigned (top ).newline ();
468478 }
469479
470- public static final class Root {
480+ private static void traceIntrinsicEnter (InterpreterResolvedJavaMethod method , int indent , SignaturePolymorphicIntrinsic intrinsic ) {
481+ /* arguments to Log methods might have side-effects */
482+ if (!InterpreterOptions .InterpreterTraceSupport .getValue ()) {
483+ return ;
484+ }
485+
486+ setLogIndent (indent + 2 );
487+ traceInterpreter (" " .repeat (indent )) //
488+ .string ("[interp] Intrinsic Entered " ) //
489+ .string (method .getDeclaringClass ().getName ()) //
490+ .string ("::" ) //
491+ .string (method .getName ()) //
492+ .string (method .getSignature ().toMethodDescriptor ()) //
493+ .string (" with iid=" ).string (intrinsic .name ()) //
494+ .newline ();
495+ }
496+
497+ private static void traceInvokeBasic (InterpreterResolvedJavaMethod target , int indent ) {
498+ /* arguments to Log methods might have side-effects */
499+ if (!InterpreterOptions .InterpreterTraceSupport .getValue ()) {
500+ return ;
501+ }
502+
503+ traceInterpreter (" " .repeat (indent )) //
504+ .string ("invokeBasic target=" ) //
505+ .string (target .getDeclaringClass ().getName ()) //
506+ .string ("::" ) //
507+ .string (target .getName ()) //
508+ .string (target .getSignature ().toMethodDescriptor ()) //
509+ .newline ();
510+ }
471511
512+ private static void traceLinkTo (InterpreterResolvedJavaMethod target , SignaturePolymorphicIntrinsic intrinsic , int indent ) {
513+ /* arguments to Log methods might have side-effects */
514+ if (!InterpreterOptions .InterpreterTraceSupport .getValue ()) {
515+ return ;
516+ }
517+
518+ traceInterpreter (" " .repeat (indent )) //
519+ .string (intrinsic .name ())
520+ .string (" target=" ) //
521+ .string (target .getDeclaringClass ().getName ()) //
522+ .string ("::" ) //
523+ .string (target .getName ()) //
524+ .string (target .getSignature ().toMethodDescriptor ()) //
525+ .newline ();
526+ }
527+
528+ public static final class IntrinsicRoot {
529+ @ NeverInline ("needed far stack walking" )
530+ public static Object execute (InterpreterFrame frame , InterpreterResolvedJavaMethod method , SignaturePolymorphicIntrinsic intrinsic , boolean forceStayInInterpreter ) {
531+ int indent = getLogIndent ();
532+ traceIntrinsicEnter (method , indent , intrinsic );
533+ return switch (intrinsic ) {
534+ case InvokeBasic -> {
535+ MethodHandle mh = (MethodHandle ) EspressoFrame .getThis (frame );
536+ Target_java_lang_invoke_MemberName vmentry = MethodHandleInterpreterUtils .extractVMEntry (mh );
537+ InterpreterResolvedJavaMethod target = InterpreterResolvedJavaMethod .fromMemberName (vmentry );
538+ Object [] calleeArgs = frame .getArguments ();
539+ // This should integrate with the debugger GR-70801
540+ boolean preferStayInInterpreter = forceStayInInterpreter ;
541+ traceInvokeBasic (target , indent );
542+ try {
543+ yield InterpreterToVM .dispatchInvocation (target , calleeArgs , false , forceStayInInterpreter , preferStayInInterpreter , false );
544+ } catch (SemanticJavaException e ) {
545+ throw uncheckedThrow (e .getCause ());
546+ }
547+ }
548+ case LinkToStatic , LinkToSpecial , LinkToVirtual , LinkToInterface -> {
549+ InterpreterResolvedJavaMethod resolutionSeed = getLinkToTarget (frame );
550+ InterpreterUnresolvedSignature signature = resolutionSeed .getSignature ();
551+ Object [] basicArgs = unbasic (frame , signature , false );
552+ // This should integrate with the debugger GR-70801
553+ boolean preferStayInInterpreter = forceStayInInterpreter ;
554+ traceLinkTo (resolutionSeed , intrinsic , indent );
555+ try {
556+ boolean isInvokeInterface = intrinsic == SignaturePolymorphicIntrinsic .LinkToInterface ;
557+ boolean isVirtual = isInvokeInterface || intrinsic == SignaturePolymorphicIntrinsic .LinkToVirtual ;
558+ Object result = InterpreterToVM .dispatchInvocation (resolutionSeed , basicArgs , isVirtual , forceStayInInterpreter , preferStayInInterpreter , isInvokeInterface );
559+ yield rebasic (result , signature .getReturnKind ());
560+ } catch (SemanticJavaException e ) {
561+ throw uncheckedThrow (e .getCause ());
562+ }
563+ }
564+ default -> throw VMError .shouldNotReachHere (Objects .toString (intrinsic ));
565+ };
566+ }
567+ }
568+
569+ private static InterpreterResolvedJavaMethod getLinkToTarget (InterpreterFrame frame ) {
570+ Object [] arguments = frame .getArguments ();
571+ Target_java_lang_invoke_MemberName memberName = (Target_java_lang_invoke_MemberName ) arguments [arguments .length - 1 ];
572+ return InterpreterResolvedJavaMethod .fromMemberName (memberName );
573+ }
574+
575+ private static Object [] unbasic (InterpreterFrame frame , InterpreterUnresolvedSignature targetSig , boolean inclReceiver ) {
576+ Object [] arguments = frame .getArguments ();
577+ int parameterCount = targetSig .getParameterCount (inclReceiver );
578+ Object [] res = new Object [parameterCount ];
579+ int start = 0 ;
580+ if (inclReceiver ) {
581+ res [start ++] = arguments [0 ];
582+ }
583+ for (int i = start ; i < parameterCount ; i ++) {
584+ JavaKind kind = targetSig .getParameterKind (i - start );
585+ res [i ] = unbasic (arguments [i ], kind );
586+ }
587+ return res ;
588+ }
589+
590+ // Transforms ints to sub-words
591+ public static Object unbasic (Object arg , JavaKind kind ) {
592+ return switch (kind ) {
593+ case Boolean -> (int ) arg != 0 ;
594+ case Byte -> (byte ) (int ) arg ;
595+ case Char -> (char ) (int ) arg ;
596+ case Short -> (short ) (int ) arg ;
597+ default -> arg ;
598+ };
599+ }
600+
601+ private static Object rebasic (Object value , JavaKind returnType ) {
602+ // @formatter:off
603+ return switch (returnType ) {
604+ case Boolean -> stackIntToBoolean ((int ) value );
605+ case Byte -> (byte ) value ;
606+ case Short -> (short ) value ;
607+ case Char -> (char ) value ;
608+ case Int , Long , Float , Double , Object
609+ -> value ;
610+ case Void -> null ; // void
611+ default -> throw VMError .shouldNotReachHereAtRuntime ();
612+ };
613+ // @formatter:on
614+ }
615+
616+ public static final class Root {
617+ @ NeverInline ("needed far stack walking" )
472618 private static Object executeBodyFromBCI (InterpreterFrame frame , InterpreterResolvedJavaMethod method , int startBCI , int startTop ,
473619 boolean forceStayInInterpreter ) {
474620 int curBCI = startBCI ;
0 commit comments