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