Hi everyone,

I registered autumn of last year for a bugfix(Bug JDK-8229902). I have a 
working bugfix, but was asked to investigate the issue a bit deeper in order to 
find an appropriate course of action.
I wasnt able to put in enough time before the end-of-year and beginning-of-year 
madness at my dayjobs, so sorry for the slow pace. Now, I was able to put in 
some more time and I feel like I am a step further.

So here's my two cents:
Like already explained, the bug is caused by the conditional flush()-call in 
the freespace-function (this is called to make sure that there is enough space 
in the buffer, before something is put into it). The unconditional 
flushBuffer()-call works fine, however. You can fix the bug by setting 
m_autoflush to false or commenting out the flush()-call in freespace. (file: 
/modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/RenderingQueue.cpp)

Since both functions contain the word "flush", I feel the urge to explain:
The RenderingQueue is basically a LinkedList of Bytearrays. the 
freespace-function checks if there is enough space in the current bytearray for 
whatever you want to put in it. If there is not enough space, a new Bytearray 
is declared and set as current, so that what you put into the buffer gets put 
into the new bytearray.
However, this new bytearray is NOT part of the LinkedList on the java side of 
things, but exists only in c++.

So here is what the two functions are doing:
- flushBuffer "flushes" the current c++ bytearray into the java LinkedList and 
declares a new current c++-Bytearray. After this, you have a new, empty c++ 
Bytearray, and the LinkedList on the java side contains one more Bytearray (the 
old current c++ array)
- flush() "flushes" the whole LinkedList of bytearrays. It decodes all its 
Bytearrays. After this, you have a new, empty java LinkedList<BufferData>. (in 
file: modules/javafx.web/src/main/java/com/sun/webkit/graphics
/WCRenderQueue.java, BufferData is a helper class around a ByteArray, its a bit 
confusing, flushBuffer adds a new BufferData to the list, but only on the next 
flushBuffer-call, the bytebuffer of the bufferdata gets set to the bytearray, 
and can therefore be decoded by flush())

Now there is still some mess here, (does it work to put in Glyphs? to me it 
looks like they never make it into the bytearray) there are flushbuffer calls 
directly before freespace-calls, so clearly space and time is wasted. (~30% 
time on my setup, still havent checked how much memory can be saved)

I see two ways of tackling this beast:
1. clearly the naming is confusing and has lead to mistakes in using the 
RenderingQueue from the outside. I could maybe make the naming a bit better and 
explain the two functions better in the comments. Then fix or take out the 
unnecessary/inefficient flush/flushBuffer-calls, just from a time and 
(memory)space point of view, the bug AND related inefficencies are perfectly 
solvable this way.
2. solve the problem "once and for all": The way I see it, todays 
buffer-solution is unnecessary complicated. Wouldnt it be nicer, if you could 
just put things into the buffer and let the RenderingQueue worry about the 
details(is there enough space etc.)? Same thing when you want the Queue to 
decode. The fact that the current bytebuffer has to be "flushed" into the 
LinkedList before decoding is a special technique of the RenderingQueue. Of 
course, you should know about it, if you are messing around inside 
RenderingQueue. But when you are just using a RenderingQueue, I think you 
should be freed from the resposibility of micromanaging RenderingQueue.

I will need to put in some more time for either solution. This is not just a 
bugfix for the specific bug.
My first approach was to fix the bug with minimal changes (just "flipping" one 
bit from true to false), now I would prefer to fix the underlying problem in a 
more substantial way. And if I'm doing that, I would prefer strategy (2.), 
rather than (1.)

Even tough (2.) will not cause alot of code change, it will significantly 
change RenderingQueues behavior as seen from the outside, rather than just fix 
its wrong or inefficient behavior. Of course I will still need to present the 
solution in a git commit in order for you people to decide if thats a good 
idea/strategy.

What do you guys (or just Kevin ?) think? You want me to put my time into a 
more comprehensive strategy or is my time better spent fixing specific problems 
and leave the bigger changes to people with more experience and knowledge?

kind regards
Dani Kurmann

Reply via email to