diff options
Diffstat (limited to 'byterun/interp.c')
-rw-r--r-- | byterun/interp.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/byterun/interp.c b/byterun/interp.c index 591b51778..e22b28b8b 100644 --- a/byterun/interp.c +++ b/byterun/interp.c @@ -181,14 +181,6 @@ sp is a local copy of the global variable caml_extern_sp. */ #endif #endif -/* Division and modulus madness */ - -#ifdef NONSTANDARD_DIV_MOD -extern intnat caml_safe_div(intnat p, intnat q); -extern intnat caml_safe_mod(intnat p, intnat q); -#endif - - #ifdef DEBUG static intnat caml_bcodcount; #endif @@ -531,10 +523,21 @@ value caml_interprete(code_t prog, asize_t prog_size) int nvars = *pc++; int i; if (nvars > 0) *--sp = accu; - Alloc_small(accu, 1 + nvars, Closure_tag); + if (nvars < Max_young_wosize) { + /* nvars + 1 <= Max_young_wosize, can allocate in minor heap */ + Alloc_small(accu, 1 + nvars, Closure_tag); + for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i]; + } else { + /* PR#6385: must allocate in major heap */ + /* caml_alloc_shr and caml_initialize never trigger a GC, + so no need to Setup_for_gc */ + accu = caml_alloc_shr(1 + nvars, Closure_tag); + for (i = 0; i < nvars; i++) caml_initialize(&Field(accu, i + 1), sp[i]); + } + /* The code pointer is not in the heap, so no need to go through + caml_initialize. */ Code_val(accu) = pc + *pc; pc++; - for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i]; sp += nvars; Next; } @@ -542,15 +545,25 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(CLOSUREREC): { int nfuncs = *pc++; int nvars = *pc++; + mlsize_t blksize = nfuncs * 2 - 1 + nvars; int i; value * p; if (nvars > 0) *--sp = accu; - Alloc_small(accu, nfuncs * 2 - 1 + nvars, Closure_tag); - p = &Field(accu, nfuncs * 2 - 1); - for (i = 0; i < nvars; i++) { - *p++ = sp[i]; + if (blksize <= Max_young_wosize) { + Alloc_small(accu, blksize, Closure_tag); + p = &Field(accu, nfuncs * 2 - 1); + for (i = 0; i < nvars; i++, p++) *p = sp[i]; + } else { + /* PR#6385: must allocate in major heap */ + /* caml_alloc_shr and caml_initialize never trigger a GC, + so no need to Setup_for_gc */ + accu = caml_alloc_shr(blksize, Closure_tag); + p = &Field(accu, nfuncs * 2 - 1); + for (i = 0; i < nvars; i++, p++) caml_initialize(p, sp[i]); } sp += nvars; + /* The code pointers and infix headers are not in the heap, + so no need to go through caml_initialize. */ p = &Field(accu, 0); *p = (value) (pc + pc[0]); *--sp = accu; @@ -780,7 +793,7 @@ value caml_interprete(code_t prog, asize_t prog_size) if (accu == Val_false) pc += *pc; else pc++; Next; Instruct(SWITCH): { - uint32 sizes = *pc++; + uint32_t sizes = *pc++; if (Is_block(accu)) { intnat index = Tag_val(accu); Assert ((uintnat) index < (sizes >> 16)); @@ -962,21 +975,13 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(DIVINT): { intnat divisor = Long_val(*sp++); if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } -#ifdef NONSTANDARD_DIV_MOD - accu = Val_long(caml_safe_div(Long_val(accu), divisor)); -#else accu = Val_long(Long_val(accu) / divisor); -#endif Next; } Instruct(MODINT): { intnat divisor = Long_val(*sp++); if (divisor == 0) { Setup_for_c_call; caml_raise_zero_divide(); } -#ifdef NONSTANDARD_DIV_MOD - accu = Val_long(caml_safe_mod(Long_val(accu), divisor)); -#else accu = Val_long(Long_val(accu) % divisor); -#endif Next; } Instruct(ANDINT): |