vm_test.go 4.6 KB

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