[PATCH] minor regex cleanup: use switch for enum

Peter Levart peter.levart at gmail.com
Tue Apr 24 10:41:23 UTC 2018


On 04/23/2018 11:18 PM, David Lloyd wrote:
> FWIW I strongly doubt this will improve performance; probably the
> opposite in fact, as IIRC an enum switch generates an extra class
> (though perhaps this has changed).

switch on enum is basically a switch on Enum's ordinal mapped via the 
int[] array constructed in a synthetic nested class of the class 
containing the switch statement, so that separate compilation of an Enum 
class that changes ordinal values of particular enum constants doesn't 
change the semantics of the switch logic. For example...

// X.java
public enum X {
     A, B, C
}

// Code.java
public class Code {
     public void m(X x) {
         switch (x) {
             case A: // ... branch A
                 break;
             case B: // ... branch B
                 break;
             case C: // ... branch C
                 break;
             default: // ... default branch
         }
     }
}


...Code.java translates to something like the following (modulo error 
handling)...

public class Code {l

     static class m$switch$1 {
         static final int[] caseindex = new int[X.values().length];
         static {
             caseindex[X.A.ordinal()] = 1;
             caseindex[X.B.ordinal()] = 2;
             caseindex[X.C.ordinal()] = 3;
         }
     }

     public void m(X x) {
         switch (m$switch$1.caseindex[x.ordinal()]) {
             case 1: // ... branch A
                 break;
             case 2: // ... branch B
                 break;
             case 3: // ... branch C
                 break;
             default: // ... default branch        }
     }
}


Pefrormance-wise this is similar to switch on int. So pretty optimal. 
Decision should only be made on the count of code clarity here.

While speaking of performance of enum switches, I have a question for a 
more knowledgeable person...

Should JIT be able to fold above 'x' variable/parameter into a constant 
(suppose m() was called in a loop with an explicitly specified constant 
value such as X.A), it could further expand this decision to the 
x.ordinal() value (if the final instance 'ordinal' field in the X enum 
class was marked with @Stable), it could then further expand this 
decision to the looked up value of the m$switch$1.caseindex[] slot if 
caseindex array field in sytnhetic class was marked with @Stable, 
therefore transforming the switch to a switch on int constant, 
optimizing the JITed code to directly execute branch A and eliminate all 
other branches from generated code.

The question is whether JIT is presently treating those fields (and 
array) as @Stable or not?

Regards, Peter

>   The original code was quite
> compact and utilized identity comparisons, and given there are only
> three alternatives it probably was able to exploit branch prediction
> as well (if such a thing even matters in this context).
>
> I'm not a reviewer but this change seems pointless without supporting perf data.
>
> On Mon, Apr 23, 2018 at 4:05 PM, Xueming Shen <xueming.shen at oracle.com> wrote:
>> I would assume in case of an exception thrown from
>> appendExpandedReplacement() we don't
>> want "text" to be pushed into the "sb".
>>
>> -sherman
>>
>> On 4/23/18, 1:49 PM, Isaac Levy wrote:
>>> Thanks. Another small perf patch below -- maybe we can combine. Avoids a
>>> StringBuilder allocation:
>>>
>>> --- a/src/java.base/share/classes/java/util/regex/Matcher.java
>>> +++ b/src/java.base/share/classes/java/util/regex/Matcher.java
>>> @@ -993,13 +993,11 @@
>>>      public Matcher appendReplacement(StringBuilder sb, String replacement)
>>> {
>>>           // If no match, return error
>>>           if (first < 0)
>>>               throw new IllegalStateException("No match available");
>>> -        StringBuilder result = new StringBuilder();
>>> -        appendExpandedReplacement(replacement, result);
>>>           // Append the intervening text
>>>           sb.append(text, lastAppendPosition, first);
>>>           // Append the match substitution
>>> +        appendExpandedReplacement(replacement, sb);
>>> -        sb.append(result);
>>>
>>>
>>> On Mon, Apr 23, 2018 at 4:31 PM, Xueming Shen <xueming.shen at oracle.com
>>> <mailto:xueming.shen at oracle.com>> wrote:
>>>> this looks fine.
>>>>
>>>> -sherman
>>
>
>



More information about the core-libs-dev mailing list