Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast interpreter: legacy try instruction #286

Open
vouillon opened this issue Feb 10, 2025 · 1 comment
Open

Fast interpreter: legacy try instruction #286

vouillon opened this issue Feb 10, 2025 · 1 comment

Comments

@vouillon
Copy link
Contributor

The legacy try instruction is currently not supported by the fast interpreter. I was wondering how much work it would take to fix that. It seems that most of the required code is already there.

With the following module:

(module
  (tag $tag)
  (func (export "main")
    (try
      (do (throw $tag))
      (catch $tag)))
)

we currently get this error:

$ ~/sources/wizard-engine/bin/wizeng.x86-64-linux -ext:exception-handling exn.wasm
!X86_64StackError: unknown or unsupported write of value tag 00 @ 0x000076BEC0142000
	in X86_64Stack.fatal() [src/engine/x86-64/X86_64Stack.v3 @ 463:29]
	in X86_64Stack.writeValue() [src/engine/x86-64/X86_64Stack.v3 @ 446:38]
	in X86_64Stack.findExHandler() [src/engine/x86-64/X86_64Stack.v3 @ 203:48]
	in X86_64Stack.walk() [src/engine/x86-64/X86_64Stack.v3 @ 134:80]
	in X86_64Stack.throw() [src/engine/x86-64/X86_64Stack.v3 @ 101:42]
	in X86_64Runtime.runtime_THROW() [src/engine/x86-64/X86_64Runtime.v3 @ 143:35]
	in [fast-int] #0
	in [return-parent-stub]
	in X86_64Stack.resume() [src/engine/x86-64/X86_64Stack.v3 @ 73:56]
	in X86_64StackManager.runOnFreshStack() [src/engine/x86-64/X86_64Stack.v3 @ 1010:62]
	in X86_64InterpreterOnlyStrategy.call() [src/engine/x86-64/X86_64Target.v3 @ 150:58]
	in Execute.call() [src/engine/Execute.v3 @ 18:36]
	in main() [src/wizeng.main.v3 @ 176:45]

Function writeValue does not support writing a reference value. But we cannot just add a case:

                        BpTypeCode.REF.code => vp.store<Object>(Value.Ref.!(v).val);

Indeed, the current tag is wrong: 00 when the the tag of references is 64. I tried writing a function that update the tag as well. But there seems another issue since the contents of the stack does not appear quite right, as can be seen with this second module:

(module
  (tag $tag (param (ref eq)))
  (type $struct (struct (field (ref func)) (field (ref eq))))
  (func $main (export "main")
    (drop
      (struct.new $struct (ref.func $main)
        (block $exit (result (ref eq))
          (try
            (do
              (throw $tag (ref.i31 (i32.const 0))))
            (catch $tag
              (br $exit (pop (ref eq)))))
          (unreachable)))))
)
$ ~/sources/wizard-engine/bin/wizeng.x86-64-linux -ext:exception-handling -ext:gc -ti exn-bug.wasm 
+1:   ref.func[func=0]
+3:   block[(ref eq)]
+6:   try[]
+8:   i32.const[0]
+10:  ref.i31
+12:  throw[tag=0]
+16:  br[depth=1]
+20:  end
+21:  struct.new[type=2]
!X86_64StackError: expected ref, got i31
	in X86_64Stack.fatal() [src/engine/x86-64/X86_64Stack.v3 @ 469:29]
	in X86_64Stack.popObject() [src/engine/x86-64/X86_64Stack.v3 @ 359:42]
	in ExecStack.popFunction() [src/engine/WasmStack.v3 @ 49:44]
	in X86_64Stack.pop() [src/engine/x86-64/X86_64Stack.v3 @ 311:69]
	in X86_64Stack.popV() [src/engine/x86-64/X86_64Stack.v3 @ 293:27]
	in Runtime.STRUCT_NEW() [src/engine/Runtime.v3 @ 42:47]
	in X86_64Runtime.runtime_STRUCT_NEW() [src/engine/x86-64/X86_64Runtime.v3 @ 206:42]
	in [fast-int] #0
	in [return-parent-stub]
	in X86_64Stack.resume() [src/engine/x86-64/X86_64Stack.v3 @ 73:56]
	in X86_64StackManager.runOnFreshStack() [src/engine/x86-64/X86_64Stack.v3 @ 1016:62]
	in X86_64InterpreterOnlyStrategy.call() [src/engine/x86-64/X86_64Target.v3 @ 150:58]
	in Execute.call() [src/engine/Execute.v3 @ 18:36]
	in main() [src/wizeng.main.v3 @ 176:45]
@titzer
Copy link
Owner

titzer commented Feb 10, 2025

Hmm. So the try and catch bytecodes should execute properly in the fast interpreter; it just seems that the method entry logic doesn't handle legacy exceptions. The writeValue() method is being used here because we're cheating with some extra slots in the frame to store the lexically-scoped exception packages (basically before exnref). Those tags are wrong because I didn't follow through and implement the bump by the number of exception slots (FuncDecl.num_ex_slots) in the fast interpreter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants