@@ -33,7 +33,7 @@ class X86_64Stack extends WasmStack {
3333 }
3434 clear();
3535 if (valuerep.tagged) RiGc.registerScanner(this, X86_64Stack.scan);
36- if (Trace.stack && Debug.stack) Trace.OUT.put2("newStack start=0x%x, end=0x%x", mapping.range.start - Pointer.NULL, mapping.range.end - Pointer.NULL).ln();
36+ if (Debug.stack) Trace.OUT.put2("newStack start=0x%x, end=0x%x", mapping.range.start - Pointer.NULL, mapping.range.end - Pointer.NULL).ln();
3737 }
3838 // Gets the state of this stack.
3939 def state() -> StackState {
@@ -120,7 +120,7 @@ class X86_64Stack extends WasmStack {
120120 // stop the stackwalk. Otherwise stop at the return-parent stub. In any case, return the last
121121 // valid stack pointer, and a boolean indicating if the walk stopped early (due to {f} returning {false}).
122122 // (XXX: takes a function {f} with an additional parameter, and the parameter, to avoid a closure).
123- private def walk<P>(f: (Pointer, RiUserCode, StackFramePos, P) -> bool, param: P, start_sp: Pointer, continue_to_parent: bool) -> (bool, StackFramePos) {
123+ def walk<P>(f: (Pointer, RiUserCode, StackFramePos, P) -> bool, param: P, start_sp: Pointer, continue_to_parent: bool) -> (bool, StackFramePos) {
124124 var stack = this;
125125 var sp = start_sp;
126126 if (Trace.stack && Debug.stack) {
@@ -185,7 +185,7 @@ class X86_64Stack extends WasmStack {
185185 }
186186 // Increment by {Pointer.SIZE} to skip the return address pushed by {resume}.
187187 var frame = TargetFrame(rsp + Pointer.SIZE);
188- var accessor = frame.getFrameAccessor( );
188+ var accessor = frame.getFrameAccessorOfStack(this );
189189 var func = accessor.func();
190190 var handler = func.decl.findSuspensionHandler(func.instance, tag, accessor.pc());
191191 if (handler.handler_pc < 0) { // not found
@@ -469,9 +469,15 @@ class X86_64Stack extends WasmStack {
469469 code.scanFrame(ip, pos.frame.sp);
470470 return true;
471471 }
472+ // XXX: If you ever get a nonsensical stacktrace (i.e., non-contiguous, untraceble
473+ // call stack) where a virtual call on a value returned by {X86_64Stack.readValue}
474+ // shows up somewhere in it, it's almost certainly the REF <=> REF_U64 tag coercion.
472475 def readValue(base: Pointer, offset: int) -> Value {
476+ // TODO: correctly tag the REF_U64 storage kind (requires typed REF_NULL loads).
473477 if (!valuerep.tagged) fatal("untyped frame access requires value tagging to be enabled");
474478 var tp = base + offset * valuerep.slot_size;
479+
480+ if (!mapping.range.contains(base)) System.error("FrameAccessError", "base out of bounds");
475481 if (!mapping.range.contains(tp)) System.error("FrameAccessError", "out of bounds");
476482 var vp = tp + valuerep.tag_size;
477483 var tag = tp.load<u8>() & '\x7F';
@@ -484,6 +490,7 @@ class X86_64Stack extends WasmStack {
484490 BpTypeCode.NULLEXTERNREF.code,
485491 BpTypeCode.I31REF.code => return readI31OrObject(vp);
486492
493+ // TODO: check if nullref needs REF_U64 coercion
487494 BpTypeCode.STRUCTREF.code,
488495 BpTypeCode.NULLREF.code,
489496 BpTypeCode.ARRAYREF.code,
@@ -572,6 +579,22 @@ class X86_64Stack extends WasmStack {
572579 if (bits == 0) return Values.REF_NULL;
573580 if ((bits & 1) == 1) return Value.I31(u31.view(bits >> 1));
574581 var obj = vp.load<Object>();
582+ // TODO[sc]: revisit this check
583+ if (FeatureDisable.unboxedConts) {
584+ if (Continuations.objectIsContinuation(obj)) {
585+ return Value.Cont(Continuations.objectToContinuation(obj));
586+ }
587+ } else {
588+ if (WasmStack.?(obj)) {
589+ var version = (vp + 8).load<u64>();
590+ return Value.Cont(Continuations.continuationWithVersion(WasmStack.!(obj), version));
591+ }
592+ }
593+
594+ if (ExecStack.?(obj)) {
595+ // {vp} points to an unboxed continuation.
596+ var x = 1 / 0;
597+ }
575598 return Value.Ref(obj);
576599 }
577600 def popResult(rt: Array<ValueType>) -> Result {
@@ -589,7 +612,7 @@ def G = X86_64MasmRegs.toGpr, X = X86_64MasmRegs.toXmmr;
589612component X86_64Stacks {
590613 var RESUME_STUB_POINTER: Pointer;
591614
592- def getFrameAccessor (sp: Pointer) -> X86_64FrameAccessor {
615+ def getFrameAccessorOfStack (sp: Pointer, stack: X86_64Stack ) -> X86_64FrameAccessor {
593616 var retip = (sp + -RETADDR_SIZE).load<Pointer>();
594617 var code = RiRuntime.findUserCode(retip);
595618 match (code) {
@@ -598,7 +621,7 @@ component X86_64Stacks {
598621 if (prev != null) return prev;
599622 // Interpreter frames store the {WasmFunction} _and_ {FuncDecl}.
600623 var decl = (sp + X86_64InterpreterFrame.func_decl.offset).load<FuncDecl>();
601- var n = X86_64FrameAccessor.new(X86_64Runtime.curStack , sp, decl);
624+ var n = X86_64FrameAccessor.new(stack , sp, decl);
602625 (sp + X86_64InterpreterFrame.accessor.offset).store<X86_64FrameAccessor>(n);
603626 return n;
604627 }
@@ -608,13 +631,19 @@ component X86_64Stacks {
608631 // SPC frames only store the {WasmFunction}.
609632 var wf = (sp + X86_64InterpreterFrame.wasm_func.offset).load<WasmFunction>();
610633 // TODO: assert wf.decl == x.decl()
611- var n = X86_64FrameAccessor.new(X86_64Runtime.curStack , sp, wf.decl);
634+ var n = X86_64FrameAccessor.new(stack , sp, wf.decl);
612635 (sp + X86_64InterpreterFrame.accessor.offset).store<X86_64FrameAccessor>(n);
613636 return n;
614637 }
615638 }
616639 return null;
617640 }
641+
642+ // TODO[cleanup]: defaulting to {curStack} should be deprecated with stack-switching
643+ def getFrameAccessor(sp: Pointer) -> X86_64FrameAccessor {
644+ return getFrameAccessorOfStack(sp, X86_64Runtime.curStack);
645+ }
646+
618647 def traceIpAndSp(ip: Pointer, sp: Pointer, out: Range<byte> -> void) {
619648 var buf = X86_64Runtime.globalFrameDescriptionBuf;
620649 buf.put2("\t@[ip=0x%x, sp=0x%x] ", ip - Pointer.NULL, sp - Pointer.NULL).send(out);
@@ -1025,6 +1054,13 @@ class X86_64FrameAccessor(stack: X86_64Stack, sp: Pointer, decl: FuncDecl) exten
10251054 var vfp = (sp + X86_64InterpreterFrame.vfp.offset).load<Pointer>();
10261055 return stack.readValue(vfp, i);
10271056 }
1057+ // Get the value at {vfp + i}.
1058+ // XXX: refactor
1059+ def getValue(i: int) -> Value {
1060+ checkNotUnwound();
1061+ var vfp = (sp + X86_64InterpreterFrame.vfp.offset).load<Pointer>();
1062+ return stack.readValue(vfp, i);
1063+ }
10281064 // Get the value of frame variable {i}.
10291065 def getFrameVar(i: int) -> Value {
10301066 checkNotUnwound();
@@ -1116,7 +1152,7 @@ class X86_64FrameAccessor(stack: X86_64Stack, sp: Pointer, decl: FuncDecl) exten
11161152 var st_ptr = if(stp == st_entries.length, Pointer.atContents(st_entries), Pointer.atElement(func.sidetable.entries, stp));
11171153 (sp + X86_64InterpreterFrame.stp.offset) .store<Pointer>(st_ptr);
11181154 }
1119- private def vfp() -> Pointer {
1155+ def vfp() -> Pointer {
11201156 return (sp + X86_64InterpreterFrame.vfp.offset).load<Pointer>();
11211157 }
11221158 private def set_vsp(p: Pointer) {
0 commit comments