RFR: 8079136: Accessing a nested sublist leads to StackOverflowError

Martin Buchholz martinrb at google.com
Thu May 7 22:07:05 UTC 2015


On Thu, May 7, 2015 at 9:18 AM, Ivan Gerasimov <ivan.gerasimov at oracle.com>
wrote:

>
>  ---
>>
>> I would make modCount an argument to updateSizeAndModCount.
>>
>>  I did that initially, but later realized that this argument should never
> be different from root.modCount.
>
>
Sure, but you'd keep it in a local variable in the loop instead of a field
read.  No big deal either way.


>  ---
>>
>> Separate out hot and cold code in subListRangeCheck (although
>> pre-existing code had the same problem)
>>
>> +    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
>> +        if (fromIndex < 0)
>> +            throw new IndexOutOfBoundsException("fromIndex = " +
>> fromIndex);
>> +        if (toIndex > size)
>> +            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
>> +        if (fromIndex > toIndex)
>> +            throw new IllegalArgumentException("fromIndex(" + fromIndex +
>> +                                               ") > toIndex(" + toIndex
>> + ")");
>> +    }
>> +
>>
>> if ((fromIndex < 0) | (toIndex > size) | (fromIndex > toIndex))
>> slowpath();
>>
>>  Recently, I investigated this possible way of optimization, and I was
> surprised to discover that javac generates more compact code for logical
> operators, comparing to bitwise operators for booleans.
>
> I've just tried it again to refresh my memory and here are results for a
> simple function:
>
> This >>> void f(int index) { if (index < 0 || index >= size) throw new
> Error(); } <<< compiles into 20 bytecode commads.
> This >>> void f(int index) { if (index < 0 | index >= size) throw new
> Error(); } <<< produces 34 commads.
>
> This is because the bitwise or operator really operates on integers.
> So, javac first conditionally initializes an auxiliary integer variables
> to either 0 or 1, then ORs them, and then checks the result.
> As the result, we have 3 branches in the code above.
>
> Another approach would be to do something like this:
>     void f(int index) {
>         int x = index | (size - 1 - index);
>         if (x < 0)
>             throw new Error();
>     }
> The code length (23) is still a bit greater, comparing to the first
> version, but on the other hand it's got only one branch.
> It's still not clear though, if this going to be more efficient or not.
>
> I recommend to leave this code as is for now, and investigate the ways to
> optimize it in a different CR.


You make a good point about code size of logical operations on booleans.  I
don't know which will be more efficient in practice - it depends on the
hotspot implementation.  I agree with your analysis.



More information about the core-libs-dev mailing list