Yes, the simple hash function in footer.S is loose by design and will
definitely trigger false positive "hot" traces. Note, though, that
as far as triggering an actual trace compilation request, the hash
function here is only half of the test. This is the "first level" hot
trace filter. Look at the beginning of dvmCheckJitTraceRequest in
Jit.c and you will find the second level filter.
It goes something like this:
o When interpreting and we reach a potential trace head, hash rPC
and decrement counter. If zero, then we may have an interesting rPC.
[Note: this operation is frequently performed during interpretation
and must not only be fast, but should avoid excessive D-cache
pollution].
o On trigger, ask the question "Do we already have a translation for
this rPC?"
o If so, jump to the translation.
o If not, tentatively switch the interpreter into trace selection
mode.
o In dvmCheckJitTraceRequest(), check the 2nd-level filter to see if
we have seen a trace request for this exact rPC recently. If so,
proceed with trace selection and generate a trace. If not, record
this rPC in the 2nd-level filter, discard the trace selection request
and revert to normal interpretation.
In this style of trace JIT there is an inherent tension between
wanting to avoid uselessly compiling cold traces vs. the desire to
transition into natively-compiled code as soon as possible. The first
level hash & test serves two purposes: identifying hot trace heads
*and* identifying points at which we can re-enter the translated code
cache. We expect a lot of false positives here, but the cost of a
false positive at this level is low - whereas the opportunity cost of
missing a point at which we could transition from interpretation back
to previously translated code is high.
The second level filter requires that a specific rPC goes hot twice in
a relatively short period of time before we commit the resources to
generating a trace.
...Bill
On Jan 12, 9:38 pm, Neo < hyangse...@gmail.com> wrote:
> In the source code,
> The table for profiling is about 2K(1<<11) Byte size.
> The table index is calculate by simple hash function.
> I think, rPC value could have more value than 2K.
> If then, different rPC share the same hash index.
> So, cold code could be compiled by hash index sharing.
> This index guarantee the unique value about rPC??
>
> This kind of hash could reduce the size of hash table,
> And could reduce the speed of calculation.
>
> #define JIT_PROF_SIZE (1 << JIT_PROF_SIZE_LOG_2)
> pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
>
> common_updateProfile:
> eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
> lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out
> excess bits
> ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
> GET_INST_OPCODE(ip)
> subs r1,r1,#1 @ decrement counter
> strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
> GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough
> otherwise */
definitely trigger false positive "hot" traces. Note, though, that
as far as triggering an actual trace compilation request, the hash
function here is only half of the test. This is the "first level" hot
trace filter. Look at the beginning of dvmCheckJitTraceRequest in
Jit.c and you will find the second level filter.
It goes something like this:
o When interpreting and we reach a potential trace head, hash rPC
and decrement counter. If zero, then we may have an interesting rPC.
[Note: this operation is frequently performed during interpretation
and must not only be fast, but should avoid excessive D-cache
pollution].
o On trigger, ask the question "Do we already have a translation for
this rPC?"
o If so, jump to the translation.
o If not, tentatively switch the interpreter into trace selection
mode.
o In dvmCheckJitTraceRequest(), check the 2nd-level filter to see if
we have seen a trace request for this exact rPC recently. If so,
proceed with trace selection and generate a trace. If not, record
this rPC in the 2nd-level filter, discard the trace selection request
and revert to normal interpretation.
In this style of trace JIT there is an inherent tension between
wanting to avoid uselessly compiling cold traces vs. the desire to
transition into natively-compiled code as soon as possible. The first
level hash & test serves two purposes: identifying hot trace heads
*and* identifying points at which we can re-enter the translated code
cache. We expect a lot of false positives here, but the cost of a
false positive at this level is low - whereas the opportunity cost of
missing a point at which we could transition from interpretation back
to previously translated code is high.
The second level filter requires that a specific rPC goes hot twice in
a relatively short period of time before we commit the resources to
generating a trace.
...Bill
- hide quoted text -
On Jan 12, 9:38 pm, Neo < hyangse...@gmail.com> wrote:
> In the source code,
> The table for profiling is about 2K(1<<11) Byte size.
> The table index is calculate by simple hash function.
> I think, rPC value could have more value than 2K.
> If then, different rPC share the same hash index.
> So, cold code could be compiled by hash index sharing.
> This index guarantee the unique value about rPC??
>
> This kind of hash could reduce the size of hash table,
> And could reduce the speed of calculation.
>
> #define JIT_PROF_SIZE (1 << JIT_PROF_SIZE_LOG_2)
> pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
>
> common_updateProfile:
> eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
> lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out
> excess bits
> ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
> GET_INST_OPCODE(ip)
> subs r1,r1,#1 @ decrement counter
> strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
> GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough
> otherwise */