mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6768 from hasumikin/fix/envadjust
This commit is contained in:
@@ -134,19 +134,29 @@ static inline void
|
||||
envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
|
||||
{
|
||||
mrb_callinfo *ci = mrb->c->cibase;
|
||||
ptrdiff_t delta = newbase - oldbase;
|
||||
/*
|
||||
* Byte-level calculation to avoid truncation when allocator alignment is
|
||||
* smaller than sizeof(mrb_value).
|
||||
* eg: MRB_NO_BOXING + MRB_INT64 with MRB_32BIT => sizeof(mrb_value)=16
|
||||
* And when memory allocator's alignment is 8 bytes
|
||||
* Pointer subtraction on mrb_value* would truncate (8/16 -> 0).
|
||||
* So, we use char* for pointer calculation to get the correct offset in bytes,
|
||||
* then apply that offset to mrb_value* pointers.
|
||||
*/
|
||||
ptrdiff_t off = (char *)newbase - (char *)oldbase;
|
||||
|
||||
if (delta == 0) return;
|
||||
if (off == 0) return;
|
||||
while (ci <= mrb->c->ci) {
|
||||
struct REnv *e = mrb_vm_ci_env(ci);
|
||||
|
||||
mrb_value *new_stack = (mrb_value *)((char *)ci->stack + off);
|
||||
|
||||
if (e) {
|
||||
mrb_assert(e->cxt == mrb->c && MRB_ENV_ONSTACK_P(e));
|
||||
mrb_assert(e->stack == ci->stack);
|
||||
|
||||
e->stack += delta;
|
||||
e->stack = new_stack;
|
||||
}
|
||||
ci->stack += delta;
|
||||
ci->stack = new_stack;
|
||||
ci++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user