vm_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package goja
  2. import (
  3. "github.com/dop251/goja/file"
  4. "github.com/dop251/goja/parser"
  5. "github.com/dop251/goja/unistring"
  6. "testing"
  7. )
  8. func TestTaggedTemplateArgExport(t *testing.T) {
  9. vm := New()
  10. vm.Set("f", func(v Value) {
  11. v.Export()
  12. })
  13. vm.RunString("f`test`")
  14. }
  15. func TestVM1(t *testing.T) {
  16. r := &Runtime{}
  17. r.init()
  18. vm := r.vm
  19. vm.prg = &Program{
  20. src: file.NewFile("dummy", "", 1),
  21. code: []instruction{
  22. &bindGlobal{vars: []unistring.String{"v"}},
  23. newObject,
  24. setGlobal("v"),
  25. loadVal{asciiString("test")},
  26. loadVal{valueInt(3)},
  27. loadVal{valueInt(2)},
  28. add,
  29. setElem,
  30. pop,
  31. loadDynamic("v"),
  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. }
  85. r := &Runtime{}
  86. r.init()
  87. vm := r.vm
  88. vm.prg = &Program{}
  89. for i := 0; i < b.N; i++ {
  90. vm.pc = 0
  91. for !vm.halted() {
  92. prg[vm.pc](vm)
  93. }
  94. //vm.sp--
  95. /*r := vm.pop()
  96. if r.ToInteger() != 5 {
  97. b.Fatalf("Unexpected result: %+v", r)
  98. }
  99. if vm.sp != 0 {
  100. b.Fatalf("Unexpected sp: %d", vm.sp)
  101. }*/
  102. }
  103. }
  104. func BenchmarkVmNOP(b *testing.B) {
  105. r := &Runtime{}
  106. r.init()
  107. vm := r.vm
  108. vm.prg = &Program{
  109. code: []instruction{
  110. jump(1),
  111. //jump(1),
  112. },
  113. }
  114. for i := 0; i < b.N; i++ {
  115. vm.pc = 0
  116. vm.run()
  117. }
  118. }
  119. func BenchmarkVm1(b *testing.B) {
  120. r := &Runtime{}
  121. r.init()
  122. vm := r.vm
  123. //ins1 := loadVal1(0)
  124. //ins2 := loadVal1(1)
  125. vm.prg = &Program{
  126. code: []instruction{
  127. loadVal{valueInt(2)},
  128. loadVal{valueInt(3)},
  129. add,
  130. },
  131. }
  132. for i := 0; i < b.N; i++ {
  133. vm.pc = 0
  134. vm.run()
  135. r := vm.pop()
  136. if r.ToInteger() != 5 {
  137. b.Fatalf("Unexpected result: %+v", r)
  138. }
  139. if vm.sp != 0 {
  140. b.Fatalf("Unexpected sp: %d", vm.sp)
  141. }
  142. }
  143. }
  144. func BenchmarkFib(b *testing.B) {
  145. const TEST_FIB = `
  146. function fib(n) {
  147. if (n < 2) return n;
  148. return fib(n - 2) + fib(n - 1);
  149. }
  150. fib(35);
  151. `
  152. b.StopTimer()
  153. prg, err := parser.ParseFile(nil, "test.js", TEST_FIB, 0)
  154. if err != nil {
  155. b.Fatal(err)
  156. }
  157. c := newCompiler()
  158. c.compile(prg, false, true, nil)
  159. c.p.dumpCode(b.Logf)
  160. r := &Runtime{}
  161. r.init()
  162. vm := r.vm
  163. var expectedResult Value = valueInt(9227465)
  164. b.StartTimer()
  165. vm.prg = c.p
  166. vm.run()
  167. v := vm.result
  168. b.Logf("stack size: %d", len(vm.stack))
  169. b.Logf("stashAllocs: %d", vm.stashAllocs)
  170. if !v.SameAs(expectedResult) {
  171. b.Fatalf("Result: %+v, expected: %+v", v, expectedResult)
  172. }
  173. }
  174. func BenchmarkEmptyLoop(b *testing.B) {
  175. const SCRIPT = `
  176. function f() {
  177. for (var i = 0; i < 100; i++) {
  178. }
  179. }
  180. f()
  181. `
  182. b.StopTimer()
  183. vm := New()
  184. prg := MustCompile("test.js", SCRIPT, false)
  185. // prg.dumpCode(log.Printf)
  186. b.StartTimer()
  187. for i := 0; i < b.N; i++ {
  188. vm.RunProgram(prg)
  189. }
  190. }
  191. func BenchmarkVMAdd(b *testing.B) {
  192. vm := &vm{}
  193. vm.stack = append(vm.stack, nil, nil)
  194. vm.sp = len(vm.stack)
  195. var v1 Value = valueInt(3)
  196. var v2 Value = valueInt(5)
  197. for i := 0; i < b.N; i++ {
  198. vm.stack[0] = v1
  199. vm.stack[1] = v2
  200. add.exec(vm)
  201. vm.sp++
  202. }
  203. }
  204. func BenchmarkFuncCall(b *testing.B) {
  205. const SCRIPT = `
  206. function f(a, b, c, d) {
  207. }
  208. `
  209. b.StopTimer()
  210. vm := New()
  211. prg := MustCompile("test.js", SCRIPT, false)
  212. vm.RunProgram(prg)
  213. if f, ok := AssertFunction(vm.Get("f")); ok {
  214. b.StartTimer()
  215. for i := 0; i < b.N; i++ {
  216. f(nil, nil, intToValue(1), intToValue(2), intToValue(3), intToValue(4), intToValue(5), intToValue(6))
  217. }
  218. } else {
  219. b.Fatal("f is not a function")
  220. }
  221. }
  222. func BenchmarkAssertInt(b *testing.B) {
  223. v := intToValue(42)
  224. for i := 0; i < b.N; i++ {
  225. if i, ok := v.(valueInt); !ok || int64(i) != 42 {
  226. b.Fatal()
  227. }
  228. }
  229. }
  230. func BenchmarkLoadVal(b *testing.B) {
  231. var ins instruction
  232. b.ReportAllocs()
  233. for i := 0; i < b.N; i++ {
  234. ins = loadVal{valueInt(1)}
  235. _ = ins
  236. }
  237. }