@@ -202,7 +202,7 @@ private void parseBytecodeDSLModel(TypeElement typeElement, BytecodeDSLModel mod
202202 model .enableYield = ElementUtils .getAnnotationValue (Boolean .class , generateBytecodeMirror , "enableYield" );
203203 model .storeBciInFrame = ElementUtils .getAnnotationValue (Boolean .class , generateBytecodeMirror , "storeBciInFrame" );
204204 model .enableQuickening = ElementUtils .getAnnotationValue (Boolean .class , generateBytecodeMirror , "enableQuickening" );
205- model .specializationDebugListener = types .SpecializationDebugListener == null ? false : ElementUtils .isAssignable (typeElement .asType (), types .SpecializationDebugListener );
205+ model .specializationDebugListener = types .BytecodeDebugListener == null ? false : ElementUtils .isAssignable (typeElement .asType (), types .BytecodeDebugListener );
206206 model .addDefault ();
207207
208208 // check basic declaration properties
@@ -523,45 +523,91 @@ private void parseBytecodeDSLModel(TypeElement typeElement, BytecodeDSLModel mod
523523 if (operation .kind != OperationKind .CUSTOM_SIMPLE ) {
524524 continue ;
525525 }
526- InstructionModel instruction = operation .instruction ;
527- boolean autoQuicken = false ;
528- for (int valueIndex = 0 ; valueIndex < instruction .signature .valueCount ; valueIndex ++) {
529- TypeMirror type = instruction .signature .getSpecializedType (valueIndex );
526+ InstructionModel genericInstruction = operation .instruction ;
527+ boolean autoOperationQuicken = false ;
528+ for (int valueIndex = 0 ; valueIndex < genericInstruction .signature .valueCount ; valueIndex ++) {
529+ TypeMirror type = genericInstruction .signature .getSpecializedType (valueIndex );
530530 if (model .isBoxingEliminated (type )) {
531- autoQuicken = true ;
531+ autoOperationQuicken = true ;
532532 break ;
533533 }
534534 }
535- if (autoQuicken ) {
535+ if (autoOperationQuicken ) {
536536 List <String > allIds = operation .instruction .nodeData .getSpecializations ().stream ().filter ((s ) -> s .getMethod () != null ).map ((s ) -> s .getMethodName ()).toList ();
537537 quickenings .add (new QuickenDecision (operation .name , new HashSet <>(allIds )));
538538 }
539+
540+ boolean genericReturnBoxingElimanted = model .isBoxingEliminated (genericInstruction .signature .returnType );
541+
542+ if (operation .instruction .nodeData .getSpecializations ().size () > 1 ) {
543+ for (SpecializationData specialization : operation .instruction .nodeData .getSpecializations ()) {
544+ if (specialization .getMethod () == null || specialization .isFallback ()) {
545+ continue ;
546+ }
547+ boolean autoQuickenSpecialization = false ;
548+ if (model .isBoxingEliminated (specialization .getMethod ().getReturnType ()) && //
549+ /*
550+ * Unexpected result specializations effectively have an
551+ * Object return type. This could probably be directly
552+ * handled by the bytecode DSL.
553+ */
554+ !specialization .hasUnexpectedResultRewrite () && //
555+ /*
556+ * If the instruction signature is already boxing eliminated
557+ * we do not need to automatically quicken each
558+ * specialization for its return type. This avoids automatic
559+ * quickening of specializations if only the return type
560+ * needs quickening.
561+ */
562+ !genericReturnBoxingElimanted ) {
563+ autoQuickenSpecialization = true ;
564+ }
565+ for (int valueIndex = 0 ; valueIndex < genericInstruction .signature .valueCount ; valueIndex ++) {
566+ TypeMirror type = specialization .getSignatureParameters ().get (valueIndex ).getType ();
567+ if (model .isBoxingEliminated (type )) {
568+ autoQuickenSpecialization = true ;
569+ break ;
570+ }
571+ }
572+
573+ if (autoQuickenSpecialization ) {
574+ List <String > allIds = List .of (specialization .getMethodName ());
575+ quickenings .add (new QuickenDecision (operation .name , new HashSet <>(allIds )));
576+ }
577+ }
578+ }
539579 }
540580 }
541581
542- Set <QuickenDecision > uniqueQuickenings = new LinkedHashSet <>(quickenings );
543- for (QuickenDecision decision : uniqueQuickenings ) {
544- OperationModel operation = null ;
545- for (OperationModel current : model .getOperations ()) {
546- if (current .name .equals (decision .operation ())) {
547- operation = current ;
548- break ;
582+ Map <String , List <QuickenDecision >> quickeningsByOperation = quickenings .stream ().distinct ().collect (Collectors .groupingBy (QuickenDecision ::operation ));
583+ for (var groupedDecision : quickeningsByOperation .entrySet ()) {
584+ String operationName = groupedDecision .getKey ();
585+ List <QuickenDecision > decisions = groupedDecision .getValue ();
586+ OperationModel operation = model .getOperationByName (operationName );
587+ List <List <SpecializationData >> resolvedQuickenings = decisions .stream ().map ((d ) -> operation .instruction .nodeData .findSpecializationsByName (d .specializations ())).sorted (
588+ (s0 , s1 ) -> {
589+ if (s0 .size () != s1 .size ()) {
590+ // sort by size we want to check single specialization
591+ // quickenings first
592+ return Integer .compare (s0 .size (), s1 .size ());
593+ }
594+ return 0 ;
595+ }).toList ();
596+
597+ for (List <SpecializationData > includedSpecializations : resolvedQuickenings ) {
598+ String name ;
599+ if (includedSpecializations .size () == operation .instruction .nodeData .getSpecializations ().size ()) {
600+ // all specializations included
601+ name = "#" ;
602+ } else {
603+ name = String .join ("#" , includedSpecializations .stream ().map ((s ) -> s .getId ()).toList ());
549604 }
550- }
551605
552- List <SpecializationData > includedSpecializations = operation .instruction .nodeData .findSpecializationsByName (decision .specializations ());
553- String name ;
554- if (includedSpecializations .size () == operation .instruction .nodeData .getSpecializations ().size ()) {
555- // all specializations included
556- name = "#" ;
557- } else {
558- name = String .join ("#" , includedSpecializations .stream ().map ((s ) -> s .getId ()).toList ());
606+ Signature signature = CustomOperationParser .createPolymorphicSignature (includedSpecializations .stream ().map (s -> s .getMethod ()).toList (), null );
607+ InstructionModel baseInstruction = operation .instruction ;
608+ InstructionModel quickenedInstruction = model .quickenInstruction (baseInstruction , signature , ElementUtils .firstLetterUpperCase (name ));
609+ quickenedInstruction .filteredSpecializations = includedSpecializations ;
559610 }
560-
561- Signature signature = CustomOperationParser .createPolymorphicSignature (includedSpecializations .stream ().map (s -> s .getMethod ()).toList (), null );
562- InstructionModel baseInstruction = operation .instruction ;
563- InstructionModel quickenedInstruction = model .quickenInstruction (baseInstruction , signature , ElementUtils .firstLetterUpperCase (name ));
564- quickenedInstruction .filteredSpecializations = includedSpecializations ;
565611 }
566612
567613 if (model .usesBoxingElimination ()) {
0 commit comments