aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/SPEC.md2
-rw-r--r--src/compiler/types.zc4
-rw-r--r--tests/conformance/8-runtime/o3_receiver_method_enter.zc13
3 files changed, 17 insertions, 2 deletions
diff --git a/docs/SPEC.md b/docs/SPEC.md
index c80b220..1aa135a 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -624,7 +624,7 @@ switch (s) { case circle(r): pn(r); case rect(w, h): pn(w * h); case dot: ps("do
o3 int sum(fixed int[?] a) { int s = 0; for (int i = 0; i < len(a); i++) s += a[i]; return s; }
```
-4.10.3 no collection runs inside an o3 region, from any code path. an allocation that would collect grows the heap instead and leaves a collection pending; an explicit `rt.gc()` inside the region is pending too. when the outermost region is left (the end of an `o3 { }` block, a `return`, `break` or `continue` out of it, or the return of an o3 function called from normal code), the pending collection runs once. if the heap can't grow, the allocation is a runtime trap (out of heap memory, exit status 2).
+4.10.3 no collection runs inside an o3 region, from any code path. an allocation that would collect grows the heap instead and leaves a collection pending; an explicit `rt.gc()` inside the region is pending too. when the outermost region is left (the end of an `o3 { }` block, a `return`, `break` or `continue` out of it, or the return of an o3 function called from normal code, directly or as a receiver method), the pending collection runs once. if the heap can't grow, the allocation is a runtime trap (out of heap memory, exit status 2).
4.10.4 drops (6.15) don't run inside o3: setting a drop inside an o3 region is error: a drop can't be set inside an o3 region, and ending the lifetime of a value with a drop inside an o3 region, by `rt.free`, at a scope end, or as a temporary, is error: x: has drop and can't end inside an o3 region. a drop the compiler can't see (unchecked code) that comes to run inside o3 stops the program: zy: a drop can't run inside an o3 region.
### 4.11 memdebug
diff --git a/src/compiler/types.zc b/src/compiler/types.zc
index ca31248..81547a5 100644
--- a/src/compiler/types.zc
+++ b/src/compiler/types.zc
@@ -873,7 +873,8 @@ int methcall(int s, word rst, word receiver_fact, int receiver, word receiver_ma
}
if ((sflag[s] & F_SIG) && np != ((ssig[s] >> 1) & 31)) serrn(sname[s], "wrong number of arguments");
if (sflag[s] & F_GEN) { s = ginstance(s, bs); effect_specialize(original, s, requirements, edges); }
- fnref(s); op(O_CALL);
+ if (!o3on && (sflag[s] & F_O3)) { o3_enter_code(); fnref(s); op(O_CALL); callname(intern("rt.o3_leave")); op(O_DROP); } // into o3 from normal code, as call() does
+ else { fnref(s); op(O_CALL); }
lv = 0;
lvk = LV_NONE;
xzero = 0;
@@ -885,6 +886,7 @@ int methcall(int s, word rst, word receiver_fact, int receiver, word receiver_ma
xstamp = 0;
xty = tword;
if (ft) xty = subst(ft[4], bs);
+ if (!o3on && (sflag[s] & F_O3) && ft && hasptr(xty)) { lit(xty); callname(s_fatten); } // non-o3 called o3: fatten the result here
if (isfl(xty)) xfloat = 1;
effect_value = 0;
if (!ret && (isptr(xty) || xty == tword)) {
diff --git a/tests/conformance/8-runtime/o3_receiver_method_enter.zc b/tests/conformance/8-runtime/o3_receiver_method_enter.zc
new file mode 100644
index 0000000..3a8d92d
--- /dev/null
+++ b/tests/conformance/8-runtime/o3_receiver_method_enter.zc
@@ -0,0 +1,13 @@
+// expect: 1003 1003 0/
+// spec 4.10.3: an o3 function called from normal code as a receiver method (run.method) enters the region like a direct call, so no collection runs inside it
+include rt;
+o3 int depth_of(int[?] v) { int i = 0, s = 0; while (i < len(v)) { s = s + v[i]; i++; } return rt.o3_depth * 1000 + s; }
+run.method("depth_of", depth_of);
+fn main() {
+ int[?] v = rt.new(int[?]); v.push(1); v.push(2);
+ rt.put_n(depth_of(v)); rt.put_c(32);
+ rt.put_n(v.depth_of()); rt.put_c(32);
+ rt.put_n(rt.o3_depth); rt.put_c(10);
+ return 0;
+}
+// zc0: skip