github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/vm_test.go (about)

     1  package goja
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/nuvolaris/goja/file"
     7  	"github.com/nuvolaris/goja/parser"
     8  	"github.com/nuvolaris/goja/unistring"
     9  )
    10  
    11  func TestTaggedTemplateArgExport(t *testing.T) {
    12  	vm := New()
    13  	vm.Set("f", func(v Value) {
    14  		v.Export()
    15  	})
    16  	vm.RunString("f`test`")
    17  }
    18  
    19  func TestVM1(t *testing.T) {
    20  	r := &Runtime{}
    21  	r.init()
    22  
    23  	vm := r.vm
    24  
    25  	vm.prg = &Program{
    26  		src:    file.NewFile("dummy", "", 1),
    27  		values: []Value{valueInt(2), valueInt(3), asciiString("test")},
    28  		code: []instruction{
    29  			&bindGlobal{vars: []unistring.String{"v"}},
    30  			newObject,
    31  			setGlobal("v"),
    32  			loadVal(2),
    33  			loadVal(1),
    34  			loadVal(0),
    35  			add,
    36  			setElem,
    37  			pop,
    38  			loadDynamic("v"),
    39  		},
    40  	}
    41  
    42  	vm.run()
    43  
    44  	rv := vm.pop()
    45  
    46  	if obj, ok := rv.(*Object); ok {
    47  		if v := obj.self.getStr("test", nil).ToInteger(); v != 5 {
    48  			t.Fatalf("Unexpected property value: %v", v)
    49  		}
    50  	} else {
    51  		t.Fatalf("Unexpected result: %v", rv)
    52  	}
    53  
    54  }
    55  
    56  func TestEvalVar(t *testing.T) {
    57  	const SCRIPT = `
    58  	function test() {
    59  		var a;
    60  		return eval("var a = 'yes'; var z = 'no'; a;") === "yes" && a === "yes";
    61  	}
    62  	test();
    63  	`
    64  
    65  	testScript(SCRIPT, valueTrue, t)
    66  }
    67  
    68  func TestResolveMixedStack1(t *testing.T) {
    69  	const SCRIPT = `
    70  	function test(arg) {
    71  		var a = 1;
    72  		var scope = {};
    73  		(function() {return arg})(); // move arguments to stash
    74  		with (scope) {
    75  			a++; // resolveMixedStack1 here
    76  			return a + arg;
    77  		}
    78  	}
    79  	test(40);
    80  	`
    81  
    82  	testScript(SCRIPT, valueInt(42), t)
    83  }
    84  
    85  func TestNewArrayFromIterClosed(t *testing.T) {
    86  	const SCRIPT = `
    87  	const [a, ...other] = [];
    88  	assert.sameValue(a, undefined);
    89  	assert(Array.isArray(other));
    90  	assert.sameValue(other.length, 0);
    91  	`
    92  	testScriptWithTestLib(SCRIPT, _undefined, t)
    93  }
    94  
    95  func BenchmarkVmNOP2(b *testing.B) {
    96  	prg := []func(*vm){
    97  		//loadVal(0).exec,
    98  		//loadVal(1).exec,
    99  		//add.exec,
   100  		jump(1).exec,
   101  	}
   102  
   103  	r := &Runtime{}
   104  	r.init()
   105  
   106  	vm := r.vm
   107  	vm.prg = &Program{
   108  		values: []Value{intToValue(2), intToValue(3)},
   109  	}
   110  
   111  	for i := 0; i < b.N; i++ {
   112  		vm.pc = 0
   113  		for !vm.halted() {
   114  			prg[vm.pc](vm)
   115  		}
   116  		//vm.sp--
   117  		/*r := vm.pop()
   118  		if r.ToInteger() != 5 {
   119  			b.Fatalf("Unexpected result: %+v", r)
   120  		}
   121  		if vm.sp != 0 {
   122  			b.Fatalf("Unexpected sp: %d", vm.sp)
   123  		}*/
   124  	}
   125  }
   126  
   127  func BenchmarkVmNOP(b *testing.B) {
   128  	r := &Runtime{}
   129  	r.init()
   130  
   131  	vm := r.vm
   132  	vm.prg = &Program{
   133  		code: []instruction{
   134  			jump(1),
   135  			//jump(1),
   136  		},
   137  	}
   138  
   139  	for i := 0; i < b.N; i++ {
   140  		vm.pc = 0
   141  		vm.run()
   142  	}
   143  
   144  }
   145  
   146  func BenchmarkVm1(b *testing.B) {
   147  	r := &Runtime{}
   148  	r.init()
   149  
   150  	vm := r.vm
   151  
   152  	//ins1 := loadVal1(0)
   153  	//ins2 := loadVal1(1)
   154  
   155  	vm.prg = &Program{
   156  		values: []Value{valueInt(2), valueInt(3)},
   157  		code: []instruction{
   158  			loadVal(0),
   159  			loadVal(1),
   160  			add,
   161  		},
   162  	}
   163  
   164  	for i := 0; i < b.N; i++ {
   165  		vm.pc = 0
   166  		vm.run()
   167  		r := vm.pop()
   168  		if r.ToInteger() != 5 {
   169  			b.Fatalf("Unexpected result: %+v", r)
   170  		}
   171  		if vm.sp != 0 {
   172  			b.Fatalf("Unexpected sp: %d", vm.sp)
   173  		}
   174  	}
   175  }
   176  
   177  func BenchmarkFib(b *testing.B) {
   178  	const TEST_FIB = `
   179  function fib(n) {
   180  if (n < 2) return n;
   181  return fib(n - 2) + fib(n - 1);
   182  }
   183  
   184  fib(35);
   185  `
   186  	b.StopTimer()
   187  	prg, err := parser.ParseFile(nil, "test.js", TEST_FIB, 0)
   188  	if err != nil {
   189  		b.Fatal(err)
   190  	}
   191  
   192  	c := newCompiler()
   193  	c.compile(prg, false, true, nil)
   194  	c.p.dumpCode(b.Logf)
   195  
   196  	r := &Runtime{}
   197  	r.init()
   198  
   199  	vm := r.vm
   200  
   201  	var expectedResult Value = valueInt(9227465)
   202  
   203  	b.StartTimer()
   204  
   205  	vm.prg = c.p
   206  	vm.run()
   207  	v := vm.result
   208  
   209  	b.Logf("stack size: %d", len(vm.stack))
   210  	b.Logf("stashAllocs: %d", vm.stashAllocs)
   211  
   212  	if !v.SameAs(expectedResult) {
   213  		b.Fatalf("Result: %+v, expected: %+v", v, expectedResult)
   214  	}
   215  
   216  }
   217  
   218  func BenchmarkEmptyLoop(b *testing.B) {
   219  	const SCRIPT = `
   220  	function f() {
   221  		for (var i = 0; i < 100; i++) {
   222  		}
   223  	}
   224  	f()
   225  	`
   226  	b.StopTimer()
   227  	vm := New()
   228  	prg := MustCompile("test.js", SCRIPT, false)
   229  	// prg.dumpCode(log.Printf)
   230  	b.StartTimer()
   231  	for i := 0; i < b.N; i++ {
   232  		vm.RunProgram(prg)
   233  	}
   234  }
   235  
   236  func BenchmarkVMAdd(b *testing.B) {
   237  	vm := &vm{}
   238  	vm.stack = append(vm.stack, nil, nil)
   239  	vm.sp = len(vm.stack)
   240  
   241  	var v1 Value = valueInt(3)
   242  	var v2 Value = valueInt(5)
   243  
   244  	for i := 0; i < b.N; i++ {
   245  		vm.stack[0] = v1
   246  		vm.stack[1] = v2
   247  		add.exec(vm)
   248  		vm.sp++
   249  	}
   250  }
   251  
   252  func BenchmarkFuncCall(b *testing.B) {
   253  	const SCRIPT = `
   254  	function f(a, b, c, d) {
   255  	}
   256  	`
   257  
   258  	b.StopTimer()
   259  
   260  	vm := New()
   261  	prg := MustCompile("test.js", SCRIPT, false)
   262  
   263  	vm.RunProgram(prg)
   264  	if f, ok := AssertFunction(vm.Get("f")); ok {
   265  		b.StartTimer()
   266  		for i := 0; i < b.N; i++ {
   267  			f(nil, nil, intToValue(1), intToValue(2), intToValue(3), intToValue(4), intToValue(5), intToValue(6))
   268  		}
   269  	} else {
   270  		b.Fatal("f is not a function")
   271  	}
   272  }
   273  
   274  func BenchmarkAssertInt(b *testing.B) {
   275  	v := intToValue(42)
   276  	for i := 0; i < b.N; i++ {
   277  		if i, ok := v.(valueInt); !ok || int64(i) != 42 {
   278  			b.Fatal()
   279  		}
   280  	}
   281  }