Have lj_ir_kptr_ accept pointers in [0, 4G) rather than [-2G, 2G)

The assertion logic is the only thing actually changing within
`lj_ir_kptr_`: the existing `mref` / `setmref` invocations already deal in
zero-extended pointers rather than sign-extended pointers.

Perhaps surprisingly, the logic around continuation pointers is changing.
To appreciate why, the following cryptic comment from vm_x86.dasc comes
into play:
```
  |->cont_dispatch:
...
  |  movsxd RAa, dword [RB-16]  // May be negative on WIN64 with debug.
```
Namely, when using MSVC in debug mode, function symbols with external
linkage are subject to extra jump stubs in order to support incremental
linking. For example, these jump stubs might look like:
```
...
lj_bcwrite:
07FFC47A5EF23  jmp         lj_bcwrite (07FFC47AB5750h)
lj_cont_ra:
07FFC47A5EF28  jmp         lj_cont_ra (07FFC47A6230Dh)
lj_ir_call:
07FFC47A5EF2D  jmp         lj_ir_call (07FFC47AF6310h)
lj_cconv_tv_bf:
07FFC47A5EF32  jmp         lj_cconv_tv_bf (07FFC47AC1EA0h)
...
```
When continutation pointers are formed, it is e.g. 07FFC47A5EF28 rather
than 07FFC47A6230 from which lj_vm_asm_begin gets subtracted, and it can
be the case that 07FFC47A5EF28 is less than lj_vm_asm_begin. Consequently,
this could previously result in continuation pointers in range [-2G, 0).
(The eagle-eyed reader might think that lj_vm_asm_begin is also a function
symbol with external linkage, but buildvm is careful to define it as a
data symbol rather than a function symbol).

This change was actually motivated by an assertion failure in WIN64 debug
mode (wherein `snap_replay_const` does `lj_ir_kptr(J, ir_kptr(ir))`, as
`ir_kptr` performs zero-extension, and then `lj_ir_kptr` would barf), but
given the recent block allocator change to support the [0, 4G) address
range on (non-x64) 64-bit platforms, the change seems prudent for other
reasons too.
This commit is contained in:
Peter Cawley 2016-04-23 23:07:48 +01:00
parent 344fe5f01d
commit 33ee12a91b
4 changed files with 9 additions and 13 deletions

View File

@ -118,11 +118,7 @@ static void recff_stitch(jit_State *J)
/* Ditto for the IR. */ /* Ditto for the IR. */
memmove(&J->base[1], &J->base[-1], sizeof(TRef)*(J->maxslot+1)); memmove(&J->base[1], &J->base[-1], sizeof(TRef)*(J->maxslot+1));
#if LJ_64 trcont = lj_ir_kptr(J, mkcontptr(cont));
trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin));
#else
trcont = lj_ir_kptr(J, (void *)cont);
#endif
J->base[0] = trcont | TREF_CONT; J->base[0] = trcont | TREF_CONT;
J->ktracep = lj_ir_k64_reserve(J); J->ktracep = lj_ir_k64_reserve(J);
lua_assert(irt_toitype_(IRT_P64) == LJ_TTRACE); lua_assert(irt_toitype_(IRT_P64) == LJ_TTRACE);

View File

@ -345,7 +345,7 @@ TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr)
{ {
IRIns *ir, *cir = J->cur.ir; IRIns *ir, *cir = J->cur.ir;
IRRef ref; IRRef ref;
lua_assert((void *)(intptr_t)i32ptr(ptr) == ptr); lua_assert((void *)(uintptr_t)u32ptr(ptr) == ptr);
for (ref = J->chain[op]; ref; ref = cir[ref].prev) for (ref = J->chain[op]; ref; ref = cir[ref].prev)
if (mref(cir[ref].ptr, void) == ptr) if (mref(cir[ref].ptr, void) == ptr)
goto found; goto found;

View File

@ -843,12 +843,16 @@ static LJ_AINLINE void setlightudV(TValue *o, void *p)
#endif #endif
#if LJ_FR2 #if LJ_FR2
#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)(void *)(f)) #define mkcontptr(f) ((void *)(f))
#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)mkcontptr(f))
#elif LJ_64 #elif LJ_64
#define mkcontptr(f) \
((void *)(uintptr_t)(uint32_t)((int64_t)(f) - (int64_t)lj_vm_asm_begin))
#define setcont(o, f) \ #define setcont(o, f) \
((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin)
#else #else
#define setcont(o, f) setlightudV((o), (void *)(f)) #define mkcontptr(f) ((void *)(f))
#define setcont(o, f) setlightudV((o), mkcontptr(f))
#endif #endif
#define tvchecklive(L, o) \ #define tvchecklive(L, o) \

View File

@ -882,11 +882,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) static BCReg rec_mm_prep(jit_State *J, ASMFunction cont)
{ {
BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize; BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize;
#if LJ_64 TRef trcont = lj_ir_kptr(J, mkcontptr(cont));
TRef trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin));
#else
TRef trcont = lj_ir_kptr(J, (void *)cont);
#endif
J->base[top] = trcont | TREF_CONT; J->base[top] = trcont | TREF_CONT;
J->framedepth++; J->framedepth++;
for (s = J->maxslot; s < top; s++) for (s = J->maxslot; s < top; s++)