浏览代码

Fixed stack lengths adjustment in suspend/resume

Dmitry Panov 2 年之前
父节点
当前提交
96b1610dd4
共有 3 个文件被更改,包括 26 次插入15 次删除
  1. 1 3
      func.go
  2. 16 0
      runtime_test.go
  3. 9 12
      vm.go

+ 1 - 3
func.go

@@ -733,9 +733,7 @@ func (g *generator) step() (res Value, resultType resultType, ex *Exception) {
 		g.ctx = execCtx{}
 		g.vm.pc = -g.vm.pc + 1
 		res = g.vm.pop()
-		g.vm.suspend(&g.ctx, uint32(len(g.vm.tryStack))-g.tryStackLen,
-			uint32(len(g.vm.iterStack))-g.iterStackLen,
-			uint32(len(g.vm.refStack))-g.refStackLen)
+		g.vm.suspend(&g.ctx, g.tryStackLen, g.iterStackLen, g.refStackLen)
 		g.vm.sp = g.vm.sb - 1
 		g.vm.callStack = g.vm.callStack[:len(g.vm.callStack)-1] // remove the frame with pc == -2, as ret would do
 	}

+ 16 - 0
runtime_test.go

@@ -2662,6 +2662,22 @@ func TestSuspendResumeRelStackLen(t *testing.T) {
 	testAsyncFunc(SCRIPT, valueTrue, t)
 }
 
+func TestSuspendResumeStacks(t *testing.T) {
+	const SCRIPT = `
+async function f1() {
+	throw new Error();
+}
+async function f() {
+  try {
+	await f1();
+  } catch {}
+}
+
+result = await f();
+	`
+	testAsyncFunc(SCRIPT, _undefined, t)
+}
+
 func TestNestedTopLevelConstructorCall(t *testing.T) {
 	r := New()
 	c := func(call ConstructorCall, rt *Runtime) *Object {

+ 9 - 12
vm.go

@@ -66,10 +66,9 @@ type execCtx struct {
 func (vm *vm) suspend(ectx *execCtx, tryStackLen, iterStackLen, refStackLen uint32) {
 	vm.saveCtx(&ectx.context)
 	ectx.stack = append(ectx.stack[:0], vm.stack[vm.sb-1:vm.sp]...)
-	if tryStackLen > 0 {
-		l := len(vm.tryStack) - int(tryStackLen)
-		ectx.tryStack = append(ectx.tryStack[:0], vm.tryStack[l:]...)
-		vm.tryStack = vm.tryStack[:l]
+	if len(vm.tryStack) > int(tryStackLen) {
+		ectx.tryStack = append(ectx.tryStack[:0], vm.tryStack[tryStackLen:]...)
+		vm.tryStack = vm.tryStack[:tryStackLen]
 		sp := int32(vm.sb - 1)
 		for i := range ectx.tryStack {
 			tf := &ectx.tryStack[i]
@@ -78,15 +77,13 @@ func (vm *vm) suspend(ectx *execCtx, tryStackLen, iterStackLen, refStackLen uint
 			tf.sp -= sp
 		}
 	}
-	if iterStackLen > 0 {
-		l := len(vm.iterStack) - int(iterStackLen)
-		ectx.iterStack = append(ectx.iterStack[:0], vm.iterStack[l:]...)
-		vm.iterStack = vm.iterStack[:l]
+	if len(vm.iterStack) > int(iterStackLen) {
+		ectx.iterStack = append(ectx.iterStack[:0], vm.iterStack[iterStackLen:]...)
+		vm.iterStack = vm.iterStack[:iterStackLen]
 	}
-	if refStackLen > 0 {
-		l := len(vm.refStack) - int(refStackLen)
-		ectx.refStack = append(ectx.refStack[:0], vm.refStack[l:]...)
-		vm.refStack = vm.refStack[:l]
+	if len(vm.refStack) > int(refStackLen) {
+		ectx.refStack = append(ectx.refStack[:0], vm.refStack[refStackLen:]...)
+		vm.refStack = vm.refStack[:refStackLen]
 	}
 }