On 12/5/06, Xiao-Feng Li <[EMAIL PROTECTED]> wrote:
On 12/4/06, Robin Garner <[EMAIL PROTECTED]> wrote:
> > On 11/30/06, Robin Garner <[EMAIL PROTECTED]> wrote:
> >> Xiao-Feng Li wrote:
> >> >
> >> > /* If the slot is in NOS or the target is not in NOS, we simply
> >> > return*/
> >> > if( p_slot.GE( NOS_BOUNDARY) || p_target.LT( NOS_BOUNDARY) )
> >> > return;
> >> >
> >> > /* Otherwise, we need remember it in native code. */
> >> > VMHelper.WriteBarrierSlotRem(p_slot, p_target);
> >>
> >> Shouldn't this be
> >> if( p_slot.LT( NOS_BOUNDARY) && p_target.GE( NOS_BOUNDARY) )
> >> VMHelper.WriteBarrierSlotRem(p_slot, p_target);
> >>
> >> ?? Ie we're recording old-to-new pointers.
> >
> > Robin, aren't they the same but exchanging the two branches of
> > condition checking? :-)
>
> Yes, of course. Doh. !(A|B) = !A&!B.
>
> I do think the second is clearer though :)
Since I somehow am not a branch predictor fun, I am used to put the
common TRUE case in the branch condition so that the fast path can be
scheduled as fall-through branch automatically by the JIT. This might
be very old and obsolete C programming wisdom. :-)
Actually, in modern compilers this may not work. I like approach used
in linux kernel:
if (unlikely(expr)) {
}
where 'unlikely' is highly compiler specific and defined something like:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
--
Ivan