summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changes1
-rw-r--r--byterun/interp.c33
2 files changed, 28 insertions, 6 deletions
diff --git a/Changes b/Changes
index effbe7335..d50ba201d 100644
--- a/Changes
+++ b/Changes
@@ -129,6 +129,7 @@ Bug fixes:
- PR#6361: Hashtbl.hash not terminating on some lazy values w/ recursive types
- PR#6383: Exception Not_found when using object type in absent module
- PR#6384: Uncaught Not_found exception with a hidden .cmi file
+- PR#6385: wrong allocation of large closures by the bytecode interpreter
- fix -dsource printing of "external _pipe = ..."
(Gabriel Scherer)
- bound-checking bug in caml_string_{get,set}{16,32,64}
diff --git a/byterun/interp.c b/byterun/interp.c
index a0e54d166..9b682ba6e 100644
--- a/byterun/interp.c
+++ b/byterun/interp.c
@@ -523,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;
}
@@ -534,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;