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 }