vm_test.go 4.5 KB

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