فهرست منبع

Upgrade benchmark project and add YantraJS (#1276)

Marko Lahma 2 سال پیش
والد
کامیت
3eddf04b74

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5 - 5
Jint.Benchmark/ArrayBenchmark.cs


+ 6 - 8
Jint.Benchmark/ArrayStressBenchmark.cs

@@ -1,13 +1,11 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class ArrayStressBenchmark : SingleScriptBenchmark
 {
-    [MemoryDiagnoser]
-    public class ArrayStressBenchmark : SingleScriptBenchmark
-    {
-        protected override string Script => "var ret=[],tmp,num=100,i=256;for(var j1=0;j1<i*15;j1++){ret=[];ret.length=i}for(var j2=0;j2<i*10;j2++){ret=new Array(i)}ret=[];for(var j3=0;j3<i;j3++){ret.unshift(j3)}ret=[];for(var j4=0;j4<i;j4++){ret.splice(0,0,j4)}var a=ret.slice();for(var j5=0;j5<i;j5++){tmp=a.shift()}var b=ret.slice();for(var j6=0;j6<i;j6++){tmp=b.splice(0,1)}ret=[];for(var j7=0;j7<i*25;j7++){ret.push(j7)}var c=ret.slice();for(var j8=0;j8<i*25;j8++){tmp=c.pop()}var done = true;";
+    protected override string Script => "var ret=[],tmp,num=100,i=256;for(var j1=0;j1<i*15;j1++){ret=[];ret.length=i}for(var j2=0;j2<i*10;j2++){ret=new Array(i)}ret=[];for(var j3=0;j3<i;j3++){ret.unshift(j3)}ret=[];for(var j4=0;j4<i;j4++){ret.splice(0,0,j4)}var a=ret.slice();for(var j5=0;j5<i;j5++){tmp=a.shift()}var b=ret.slice();for(var j6=0;j6<i;j6++){tmp=b.splice(0,1)}ret=[];for(var j7=0;j7<i*25;j7++){ret.push(j7)}var c=ret.slice();for(var j8=0;j8<i*25;j8++){tmp=c.pop()}var done = true;";
 
-        [Params(20)]
-        public override int N { get; set; }
-    }
+    public override int N => 10;
 }

+ 53 - 54
Jint.Benchmark/DictionaryBenchmark.cs

@@ -1,73 +1,72 @@
 using Jint.Collections;
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class DictionaryBenchmark
 {
-    [MemoryDiagnoser]
-    public class DictionaryBenchmark
+    private static readonly string[] _keys =
     {
-        private static readonly string[] _keys =
-        {
-            "some",
-            "key and",
-            "another",
-            "varying",
-            "---the --",
-            "keys and more",
-            "aa bbb",
-            "asasd asd ",
-            "asdsad asd as s",
-            "asdadsasa",
-            "23323232323",
-            "asdadsada sa213"
-        };
+        "some",
+        "key and",
+        "another",
+        "varying",
+        "---the --",
+        "keys and more",
+        "aa bbb",
+        "asasd asd ",
+        "asdsad asd as s",
+        "asdadsasa",
+        "23323232323",
+        "asdadsada sa213"
+    };
 
-        [Params(0, 2, 3, 5, 8, 9, 10)]
-        public int N { get; set; }
+    [Params(0, 2, 3, 5, 8, 9, 10)]
+    public int N { get; set; }
 
-        [Benchmark]
-        public void HybridDictionary()
+    [Benchmark]
+    public void HybridDictionary()
+    {
+        var hybridDictionary = new HybridDictionary<object>();
+        for (var i = 0; i < N; i++)
         {
-            var hybridDictionary = new HybridDictionary<object>();
-            for (var i = 0; i < N; i++)
-            {
-                hybridDictionary.Add(_keys[i], _keys);
-            }
+            hybridDictionary.Add(_keys[i], _keys);
+        }
 
-            foreach (var key in _keys)
-            {
-                hybridDictionary.ContainsKey(key);
-            }
+        foreach (var key in _keys)
+        {
+            hybridDictionary.ContainsKey(key);
         }
+    }
 
-        [Benchmark]
-        public void Dictionary()
+    [Benchmark]
+    public void Dictionary()
+    {
+        var dictionary = new Dictionary<string, object>();
+        for (var i = 0; i < N; i++)
         {
-            var dictionary = new Dictionary<string, object>();
-            for (var i = 0; i < N; i++)
-            {
-                dictionary.Add(_keys[i], _keys);
-            }
+            dictionary.Add(_keys[i], _keys);
+        }
 
-            foreach (var key in _keys)
-            {
-                dictionary.ContainsKey(key);
-            }
+        foreach (var key in _keys)
+        {
+            dictionary.ContainsKey(key);
         }
+    }
 
-        [Benchmark]
-        public void StringDictionarySlim()
+    [Benchmark]
+    public void StringDictionarySlim()
+    {
+        var dictionary = new StringDictionarySlim<object>();
+        for (var i = 0; i < N; i++)
         {
-            var dictionary = new StringDictionarySlim<object>();
-            for (var i = 0; i < N; i++)
-            {
-                dictionary[_keys[i]] =_keys;
-            }
+            dictionary[_keys[i]] =_keys;
+        }
 
-            foreach (var key in _keys)
-            {
-                dictionary.ContainsKey(key);
-            }
+        foreach (var key in _keys)
+        {
+            dictionary.ContainsKey(key);
         }
     }
-}
+}

+ 38 - 39
Jint.Benchmark/DromaeoBenchmark.cs

@@ -1,57 +1,56 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class DromaeoBenchmark
 {
-    [MemoryDiagnoser]
-    public class DromaeoBenchmark
+    public static readonly Dictionary<string, string> files = new Dictionary<string, string>
     {
-        public static readonly Dictionary<string, string> files = new Dictionary<string, string>
-        {
-            {"dromaeo-3d-cube", null},
-            {"dromaeo-core-eval", null},
-            {"dromaeo-object-array", null},
-            {"dromaeo-object-regexp", null},
-            {"dromaeo-object-string", null},
-            {"dromaeo-string-base64", null}
-        };
-
-        private Engine engine;
-
-        [GlobalSetup]
-        public void Setup()
+        {"dromaeo-3d-cube", null},
+        {"dromaeo-core-eval", null},
+        {"dromaeo-object-array", null},
+        {"dromaeo-object-regexp", null},
+        {"dromaeo-object-string", null},
+        {"dromaeo-string-base64", null}
+    };
+
+    private Engine engine;
+
+    [GlobalSetup]
+    public void Setup()
+    {
+        foreach (var fileName in files.Keys.ToList())
         {
-            foreach (var fileName in files.Keys.ToList())
-            {
-                files[fileName] = File.ReadAllText($"Scripts/dromaeo/{fileName}.js");
-            }
+            files[fileName] = File.ReadAllText($"Scripts/dromaeo/{fileName}.js");
+        }
 
-            engine = new Engine()
-                .SetValue("log", new Action<object>(Console.WriteLine))
-                .SetValue("assert", new Action<bool>(b => { }));
+        engine = new Engine()
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(b => { }));
 
-            engine.Execute(@"
+        engine.Execute(@"
 var startTest = function () { };
 var test = function (name, fn) { fn(); };
 var endTest = function () { };
 var prep = function (fn) { fn(); };
 ");
-        }
+    }
 
-        [ParamsSource(nameof(FileNames))]
-        public string FileName { get; set; }
+    [ParamsSource(nameof(FileNames))]
+    public string FileName { get; set; }
 
-        public IEnumerable<string> FileNames()
+    public IEnumerable<string> FileNames()
+    {
+        foreach (var entry in files)
         {
-            foreach (var entry in files)
-            {
-                yield return entry.Key;
-            }
+            yield return entry.Key;
         }
+    }
 
-        [Benchmark]
-        public void Run()
-        {
-            engine.Execute(files[FileName]);
-        }
+    [Benchmark]
+    public void Run()
+    {
+        engine.Execute(files[FileName]);
     }
-}
+}

+ 16 - 17
Jint.Benchmark/EngineConstructionBenchmark.cs

@@ -2,24 +2,23 @@
 using Esprima;
 using Esprima.Ast;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class EngineConstructionBenchmark
 {
-    [MemoryDiagnoser]
-    public class EngineConstructionBenchmark
-    {
-        private readonly Script _program;
+    private readonly Script _program;
 
-        public EngineConstructionBenchmark()
-        {
-            var parser = new JavaScriptParser();
-            _program = parser.ParseScript("return [].length + ''.length");
-        }
+    public EngineConstructionBenchmark()
+    {
+        var parser = new JavaScriptParser();
+        _program = parser.ParseScript("return [].length + ''.length");
+    }
 
-        [Benchmark]
-        public double BuildEngine()
-        {
-            var engine = new Engine();
-            return engine.Evaluate(_program).AsNumber();
-        }
+    [Benchmark]
+    public double BuildEngine()
+    {
+        var engine = new Engine();
+        return engine.Evaluate(_program).AsNumber();
     }
-}
+}

+ 6 - 8
Jint.Benchmark/EvaluationBenchmark.cs

@@ -1,11 +1,11 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class EvaluationBenchmark : SingleScriptBenchmark
 {
-    [MemoryDiagnoser]
-    public class EvaluationBenchmark : SingleScriptBenchmark
-    {
-        protected override string Script => @"
+    protected override string Script => @"
             var o = {};
             o.Foo = 'bar';
             o.Baz = 42.0001;
@@ -26,7 +26,5 @@ namespace Jint.Benchmark
             var done = true;
         ";
 
-        [Params(20)]
-        public override int N { get; set; }
-    }
+    public override int N => 20;
 }

+ 204 - 205
Jint.Benchmark/InteropBenchmark.cs

@@ -3,298 +3,297 @@ using BenchmarkDotNet.Attributes;
 using Jint.Native;
 using Jint.Native.Array;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class InteropBenchmark
 {
-    [MemoryDiagnoser]
-    public class InteropBenchmark
+    private const int OperationsPerInvoke = 1_000;
+
+    public class Person
     {
-        private const int OperationsPerInvoke = 1_000;
+        public string Name { get; set; }
+        public int Age { get; set; }
+    }
 
-        public class Person
-        {
-            public string Name { get; set; }
-            public int Age { get; set; }
-        }
+    private Engine _engine;
 
-        private Engine _engine;
+    [GlobalSetup]
+    public void Setup()
+    {
+        _engine = new Engine(cfg => cfg.AllowClr(
+                typeof(Person).GetTypeInfo().Assembly,
+                typeof(Console).GetTypeInfo().Assembly,
+                typeof(System.IO.File).GetTypeInfo().Assembly))
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(x => { }))
+            .SetValue("equal", new Action<object, object>((x, y) => { }));
+    }
 
-        [GlobalSetup]
-        public void Setup()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void DelegatesCanBeSet()
+    {
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            _engine = new Engine(cfg => cfg.AllowClr(
-                    typeof(Person).GetTypeInfo().Assembly,
-                    typeof(Console).GetTypeInfo().Assembly,
-                    typeof(System.IO.File).GetTypeInfo().Assembly))
-                .SetValue("log", new Action<object>(Console.WriteLine))
-                .SetValue("assert", new Action<bool>(x => { }))
-                .SetValue("equal", new Action<object, object>((x, y) => { }));
+            _engine.SetValue("square", new Func<double, double>(x => x * x));
+            _engine.Execute("assert(square(10) === 100);");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void DelegatesCanBeSet()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void ExtraParametersAreIgnored()
+    {
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("square", new Func<double, double>(x => x * x));
-                _engine.Execute("assert(square(10) === 100);");
-            }
+            _engine.SetValue("passNumber", new Func<int, int>(x => x));
+            _engine.Execute("assert(passNumber(123,'test',{},[],null) === 123);");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void ExtraParametersAreIgnored()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void GetObjectProperties()
+    {
+        var p = new Person
         {
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("passNumber", new Func<int, int>(x => x));
-                _engine.Execute("assert(passNumber(123,'test',{},[],null) === 123);");
-            }
-        }
+            Name = "Mickey Mouse"
+        };
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void GetObjectProperties()
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var p = new Person
-            {
-                Name = "Mickey Mouse"
-            };
-
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute("assert(p.Name === 'Mickey Mouse');");
-            }
+            _engine.SetValue("p", p);
+            _engine.Execute("assert(p.Name === 'Mickey Mouse');");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void InvokeObjectMethods()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void InvokeObjectMethods()
+    {
+        var p = new Person
         {
-            var p = new Person
-            {
-                Name = "Mickey Mouse"
-            };
+            Name = "Mickey Mouse"
+        };
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute(@"assert(p.ToString() === 'Mickey Mouse');");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("p", p);
+            _engine.Execute(@"assert(p.ToString() === 'Mickey Mouse');");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void SetObjectProperties()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void SetObjectProperties()
+    {
+        var p = new Person
         {
-            var p = new Person
-            {
-                Name = "Mickey Mouse"
-            };
+            Name = "Mickey Mouse"
+        };
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute("p.Name = 'Donald Duck'; assert(p.Name === 'Donald Duck');");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("p", p);
+            _engine.Execute("p.Name = 'Donald Duck'; assert(p.Name === 'Donald Duck');");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void GetIndexUsingStringKey()
-        {
-            var dictionary = new Dictionary<string, Person>();
-            dictionary.Add("person1", new Person {Name = "Mickey Mouse"});
-            dictionary.Add("person2", new Person {Name = "Goofy"});
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void GetIndexUsingStringKey()
+    {
+        var dictionary = new Dictionary<string, Person>();
+        dictionary.Add("person1", new Person {Name = "Mickey Mouse"});
+        dictionary.Add("person2", new Person {Name = "Goofy"});
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("dictionary", dictionary);
-                _engine.Execute("assert(dictionary['person1'].Name === 'Mickey Mouse'); assert(dictionary['person2'].Name === 'Goofy');");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("dictionary", dictionary);
+            _engine.Execute("assert(dictionary['person1'].Name === 'Mickey Mouse'); assert(dictionary['person2'].Name === 'Goofy');");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void GenericMethods()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void GenericMethods()
+    {
+        var dictionary = new Dictionary<int, string>
         {
-            var dictionary = new Dictionary<int, string>
-            {
-                {1, "Mickey Mouse"}
-            };
+            {1, "Mickey Mouse"}
+        };
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("dictionary", dictionary);
-                _engine.Execute("dictionary.Clear(); dictionary.Add(2, 'Goofy'); assert(dictionary[2] === 'Goofy');");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("dictionary", dictionary);
+            _engine.Execute("dictionary.Clear(); dictionary.Add(2, 'Goofy'); assert(dictionary[2] === 'Goofy');");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void MultiGenericTypes()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void MultiGenericTypes()
+    {
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.Execute(@"
+            _engine.Execute(@"
                 var type = System.Collections.Generic.Dictionary(System.Int32, System.String);
                 var dictionary = new type();
                 dictionary.Add(1, 'Mickey Mouse');
                 dictionary.Add(2, 'Goofy');
                 assert(dictionary[2] === 'Goofy');
             ");
-            }
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void IndexOnList()
-        {
-            var list = new List<object>(2);
-            list.Add("Mickey Mouse");
-            list.Add("Goofy");
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void IndexOnList()
+    {
+        var list = new List<object>(2);
+        list.Add("Mickey Mouse");
+        list.Add("Goofy");
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("list", list);
-                _engine.Execute("list[1] = 'Donald Duck'; assert(list[1] === 'Donald Duck');");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("list", list);
+            _engine.Execute("list[1] = 'Donald Duck'; assert(list[1] === 'Donald Duck');");
         }
+    }
 
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void EcmaValuesAreAutomaticallyConvertedWhenSetInPoco()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void EcmaValuesAreAutomaticallyConvertedWhenSetInPoco()
+    {
+        var p = new Person
         {
-            var p = new Person
-            {
-                Name = "foo",
-            };
+            Name = "foo",
+        };
 
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute(@"
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("p", p);
+            _engine.Execute(@"
                 assert(p.Name === 'foo');
                 assert(p.Age === 0);
                 p.Name = 'bar';
                 p.Age = 10;
             ");
-            }
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void Trim()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void Trim()
+    {
+        var p = new Person
         {
-            var p = new Person
-            {
-                Name = "Mickey Mouse "
-            };
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute(@"
+            Name = "Mickey Mouse "
+        };
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("p", p);
+            _engine.Execute(@"
                 assert(p.Name === 'Mickey Mouse ');
                 p.Name = p.Name.trim();
                 assert(p.Name === 'Mickey Mouse');
             ");
-            }
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void MathFloor()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void MathFloor()
+    {
+        var p = new Person();
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var p = new Person();
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("p", p);
-                _engine.Execute("p.Age = Math.floor(1.6); assert(p.Age === 1);");
-            }
+            _engine.SetValue("p", p);
+            _engine.Execute("p.Age = Math.floor(1.6); assert(p.Age === 1);");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void DelegateAsFunction()
-        {
-            var even = new Func<int, bool>(x => x % 2 == 0);
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void DelegateAsFunction()
+    {
+        var even = new Func<int, bool>(x => x % 2 == 0);
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("even", even);
-                _engine.Execute("assert(even(2) === true);");
-            }
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("even", even);
+            _engine.Execute("assert(even(2) === true);");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void ConvertArrayToArrayInstance()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void ConvertArrayToArrayInstance()
+    {
+        var ints = new[] {1, 2, 3, 4, 5, 6};
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var ints = new[] {1, 2, 3, 4, 5, 6};
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine
-                    .SetValue("values", ints)
-                    .Execute("values.filter(function(x){ return x % 2 == 0; })");
-            }
+            _engine
+                .SetValue("values", ints)
+                .Execute("values.filter(function(x){ return x % 2 == 0; })");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void ConvertListsToArrayInstance()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void ConvertListsToArrayInstance()
+    {
+        var ints = new List<object> {1, 2, 3, 4, 5, 6};
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var ints = new List<object> {1, 2, 3, 4, 5, 6};
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine
-                    .SetValue("values", ints)
-                    .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
-            }
+            _engine
+                .SetValue("values", ints)
+                .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void ConvertArrayInstanceToArray()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void ConvertArrayInstanceToArray()
+    {
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.Execute("'[email protected]'.split('@');");
-            }
+            _engine.Execute("'[email protected]'.split('@');");
         }
+    }
         
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void ResolvingConsoleWriteLine()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void ResolvingConsoleWriteLine()
+    {
+        var originalOut = Console.Out;
+        Console.SetOut(TextWriter.Null);
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var originalOut = Console.Out;
-            Console.SetOut(TextWriter.Null);
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.Execute("System.Console.WriteLine('value to write');");
-            }
-            Console.SetOut(originalOut);
+            _engine.Execute("System.Console.WriteLine('value to write');");
         }
+        Console.SetOut(originalOut);
+    }
         
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void Setter()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void Setter()
+    {
+        var p = new Person();
+        _engine.SetValue("p", p);
+        for (int i = 0; i < OperationsPerInvoke; ++i)
         {
-            var p = new Person();
-            _engine.SetValue("p", p);
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.Execute("p.Age = 42;");
-            }
+            _engine.Execute("p.Age = 42;");
         }
+    }
 
-        [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
-        public void LoopWithNativeEnumerator()
+    [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
+    public void LoopWithNativeEnumerator()
+    {
+        JsValue Adder(JsValue argValue)
         {
-            JsValue Adder(JsValue argValue)
+            ArrayInstance args = argValue.AsArray();
+            double sum = 0;
+            foreach (var item in args)
             {
-                ArrayInstance args = argValue.AsArray();
-                double sum = 0;
-                foreach (var item in args)
+                if (item.IsNumber())
                 {
-                    if (item.IsNumber())
-                    {
-                        sum += item.AsNumber();
-                    }
+                    sum += item.AsNumber();
                 }
-
-                return sum;
             }
 
-            for (int i = 0; i < OperationsPerInvoke; ++i)
-            {
-                _engine.SetValue("getSum", new Func<JsValue, JsValue>(Adder));
-                _engine.Execute("getSum([1,2,3]);");
-            }
+            return sum;
+        }
+
+        for (int i = 0; i < OperationsPerInvoke; ++i)
+        {
+            _engine.SetValue("getSum", new Func<JsValue, JsValue>(Adder));
+            _engine.Execute("getSum([1,2,3]);");
         }
     }
-}
+}

+ 3 - 2
Jint.Benchmark/Jint.Benchmark.csproj

@@ -25,9 +25,10 @@
     <ProjectReference Include="..\Jint\Jint.csproj" />
   </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
-    <PackageReference Include="Jurassic" Version="3.2.4" />
+    <PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
+    <PackageReference Include="Jurassic" Version="3.2.6" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
     <PackageReference Include="NiL.JS.NetCore" Version="2.5.1419" />
+    <PackageReference Include="YantraJS.Core" Version="1.2.47" />
   </ItemGroup>
 </Project>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5 - 6
Jint.Benchmark/LinqJsBenchmark.cs


+ 6 - 7
Jint.Benchmark/MinimalScriptBenchmark.cs

@@ -1,10 +1,9 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class MinimalScriptBenchmark : SingleScriptBenchmark
 {
-    [MemoryDiagnoser]
-    public class MinimalScriptBenchmark : SingleScriptBenchmark
-    {
-        protected override string Script => "var done = true;";
-    }
-}
+    protected override string Script => "var done = 1 + 1 === 2;";
+}

+ 8 - 7
Jint.Benchmark/Program.cs

@@ -1,13 +1,14 @@
 using System.Reflection;
 using BenchmarkDotNet.Running;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+public static class Program
 {
-    public static class Program
+    public static void Main(string[] args)
     {
-        public static void Main(string[] args)
-        {
-            BenchmarkSwitcher.FromAssembly(typeof(Program).GetTypeInfo().Assembly).Run(args);
-        }
+        BenchmarkSwitcher
+            .FromAssembly(typeof(Program).GetTypeInfo().Assembly)
+            .Run(args);
     }
-}
+}

+ 5 - 0
Jint.Benchmark/README.md

@@ -0,0 +1,5 @@
+To run tests comparing engines, use:
+
+```
+dotnet run -c Release --allCategories EngineComparison
+```

+ 52 - 59
Jint.Benchmark/SingleScriptBenchmark.cs

@@ -1,71 +1,64 @@
 using BenchmarkDotNet.Attributes;
+using Esprima;
+using Esprima.Ast;
 
-namespace Jint.Benchmark
-{
-    [MemoryDiagnoser]
-    public abstract class SingleScriptBenchmark
-    {
-        private Engine sharedJint;
+namespace Jint.Benchmark;
 
-#if ENGINE_COMPARISON
-        private Jurassic.ScriptEngine sharedJurassic;
-        private NiL.JS.Core.Context sharedNilJs;
-#endif
-
-        protected abstract string Script { get; }
+[RankColumn]
+[MemoryDiagnoser]
+[HideColumns("Error", "StdDev", "Gen0", "Gen1", "Gen2")]
+[BenchmarkCategory("EngineComparison")]
+public abstract class SingleScriptBenchmark
+{
+    private Script _parsedScript;
 
-        [Params(10)]
-        public virtual int N { get; set; }
+    protected abstract string Script { get; }
 
-        [GlobalSetup]
-        public void Setup()
-        {
-            sharedJint = new Engine();
-#if ENGINE_COMPARISON
-            sharedJurassic = new Jurassic.ScriptEngine();
-            sharedNilJs = new NiL.JS.Core.Context();
-#endif
-        }
+    public virtual int N => 10;
 
-        [Benchmark]
-        public bool Jint()
-        {
-            bool done = false;
-            for (var i = 0; i < N; i++)
-            {
-                sharedJint.Execute(Script);
-                done |= sharedJint.GetValue("done").AsBoolean();
-            }
+    [GlobalSetup]
+    public void Setup()
+    {
+        _parsedScript = new JavaScriptParser().ParseScript(Script);
+    }
 
-            return done;
-        }
+    [Benchmark]
+    public bool Jint()
+    {
+        var engine = new Engine();
+        engine.Execute(Script);
+        return engine.GetValue("done").AsBoolean();
+    }
 
-#if ENGINE_COMPARISON
-        [Benchmark]
-        public bool Jurassic()
-        {
-            bool done = false;
-            for (var i = 0; i < N; i++)
-            {
-                sharedJurassic.Execute(Script);
-                done |= sharedJurassic.GetGlobalValue<bool>("done");
-            }
+    [Benchmark]
+    public bool Jint_ParsedScript()
+    {
+        var engine = new Engine();
+        engine.Execute(_parsedScript);
+        return engine.GetValue("done").AsBoolean();
+    }
 
-            return done;
-        }
+    [Benchmark]
+    public bool Jurassic()
+    {
+        var engine = new Jurassic.ScriptEngine();
+        engine.Execute(Script);
+        return engine.GetGlobalValue<bool>("done");
+    }
 
-        [Benchmark]
-        public bool NilJS()
-        {
-            bool done = false;
-            for (var i = 0; i < N; i++)
-            {
-                sharedNilJs.Eval(Script);
-                done |= (bool) sharedNilJs.GetVariable("done");
-            }
+    [Benchmark]
+    public bool NilJS()
+    {
+        var engine = new NiL.JS.Core.Context();
+        engine.Eval(Script);
+        return (bool) engine.GetVariable("done");
+    }
 
-            return done;
-        }
-#endif
+    [Benchmark]
+    public bool YantraJS()
+    {
+        var engine = new YantraJS.Core.JSContext();
+        engine.Eval(Script);
+        return engine["done"].BooleanValue;
     }
-}
+}

+ 6 - 8
Jint.Benchmark/StopwatchBenchmark.cs

@@ -1,14 +1,13 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class StopwatchBenchmark : SingleScriptBenchmark
 {
-    [MemoryDiagnoser]
-    public class StopwatchBenchmark : SingleScriptBenchmark
-    {
-        [Params(1)]
-        public override int N { get; set; }
+    public override int N => 10;
 
-        protected override string Script => @"
+    protected override string Script => @"
 function Stopwatch() {
     var sw = this;
     var start = null;
@@ -68,5 +67,4 @@ sw.Stop();
 
 var done = true;
 ";
-    }
 }

+ 26 - 27
Jint.Benchmark/StringBuilderBenchmark.cs

@@ -1,39 +1,38 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class StringBuilderBenchmark
 {
-    [MemoryDiagnoser]
-    public class StringBuilderBenchmark
-    {
-        private const string script = @"
+    private const string script = @"
 var x = 'some string';
 ";
 
-        private Engine engine;
+    private Engine engine;
 
-        [GlobalSetup]
-        public void Setup()
-        {
-            engine = new Engine();
-            engine.Execute(script);
-        }
+    [GlobalSetup]
+    public void Setup()
+    {
+        engine = new Engine();
+        engine.Execute(script);
+    }
 
-        [Benchmark]
-        public void One()
-        {
-            engine.Execute("`hello ${x}`");
-        }
+    [Benchmark]
+    public void One()
+    {
+        engine.Execute("`hello ${x}`");
+    }
 
-        [Benchmark]
-        public void Two()
-        {
-            engine.Execute("`hello ${x}, hello ${x}`");
-        }
+    [Benchmark]
+    public void Two()
+    {
+        engine.Execute("`hello ${x}, hello ${x}`");
+    }
 
-        [Benchmark]
-        public void Three()
-        {
-            engine.Execute("`hello ${x}, hello ${x}, hello ${x}`");
-        }
+    [Benchmark]
+    public void Three()
+    {
+        engine.Execute("`hello ${x}, hello ${x}, hello ${x}`");
     }
 }

+ 55 - 56
Jint.Benchmark/SunSpiderBenchmark.cs

@@ -1,71 +1,70 @@
 using BenchmarkDotNet.Attributes;
 using Jint;
 
-namespace Esprima.Benchmark
+namespace Esprima.Benchmark;
+
+[MemoryDiagnoser]
+public class SunSpiderBenchmark
 {
-    [MemoryDiagnoser]
-    public class SunSpiderBenchmark
+    private static readonly Dictionary<string, string> files = new Dictionary<string, string>
     {
-        private static readonly Dictionary<string, string> files = new Dictionary<string, string>
-        {
-            {"3d-cube", null},
-            {"3d-morph", null},
-            {"3d-raytrace", null},
-            {"access-binary-trees", null},
-            {"access-fannkuch", null},
-            {"access-nbody", null},
-            {"access-nsieve", null},
-            {"bitops-3bit-bits-in-byte", null},
-            {"bitops-bits-in-byte", null},
-            {"bitops-bitwise-and", null},
-            {"bitops-nsieve-bits", null},
-            {"controlflow-recursive", null},
-            {"crypto-aes", null},
-            {"crypto-md5", null},
-            {"crypto-sha1", null},
-            {"date-format-tofte", null},
-            {"date-format-xparb", null},
-            {"math-cordic", null},
-            {"math-partial-sums", null},
-            {"math-spectral-norm", null},
-            {"regexp-dna", null},
-            {"string-base64", null},
-            {"string-fasta", null},
-            {"string-tagcloud", null},
-            {"string-unpack-code", null},
-            {"string-validate-input", null}
-        };
+        {"3d-cube", null},
+        {"3d-morph", null},
+        {"3d-raytrace", null},
+        {"access-binary-trees", null},
+        {"access-fannkuch", null},
+        {"access-nbody", null},
+        {"access-nsieve", null},
+        {"bitops-3bit-bits-in-byte", null},
+        {"bitops-bits-in-byte", null},
+        {"bitops-bitwise-and", null},
+        {"bitops-nsieve-bits", null},
+        {"controlflow-recursive", null},
+        {"crypto-aes", null},
+        {"crypto-md5", null},
+        {"crypto-sha1", null},
+        {"date-format-tofte", null},
+        {"date-format-xparb", null},
+        {"math-cordic", null},
+        {"math-partial-sums", null},
+        {"math-spectral-norm", null},
+        {"regexp-dna", null},
+        {"string-base64", null},
+        {"string-fasta", null},
+        {"string-tagcloud", null},
+        {"string-unpack-code", null},
+        {"string-validate-input", null}
+    };
 
-        private Engine engine;
+    private Engine engine;
 
-        [GlobalSetup]
-        public void Setup()
+    [GlobalSetup]
+    public void Setup()
+    {
+        foreach (var fileName in files.Keys.ToList())
         {
-            foreach (var fileName in files.Keys.ToList())
-            {
-                files[fileName] = File.ReadAllText($"SunSpider/{fileName}.js");
-            }
-
-            engine = new Engine()
-                .SetValue("log", new Action<object>(Console.WriteLine))
-                .SetValue("assert", new Action<bool>(b => { }));
+            files[fileName] = File.ReadAllText($"SunSpider/{fileName}.js");
         }
 
-        [ParamsSource(nameof(FileNames))]
-        public string FileName { get; set; }
+        engine = new Engine()
+            .SetValue("log", new Action<object>(Console.WriteLine))
+            .SetValue("assert", new Action<bool>(b => { }));
+    }
 
-        public IEnumerable<string> FileNames()
-        {
-            foreach (var entry in files)
-            {
-                yield return entry.Key;
-            }
-        }
+    [ParamsSource(nameof(FileNames))]
+    public string FileName { get; set; }
 
-        [Benchmark]
-        public void Run()
+    public IEnumerable<string> FileNames()
+    {
+        foreach (var entry in files)
         {
-            engine.Execute(files[FileName]);
+            yield return entry.Key;
         }
     }
-}
+
+    [Benchmark]
+    public void Run()
+    {
+        engine.Execute(files[FileName]);
+    }
+}

+ 39 - 40
Jint.Benchmark/TimeoutBenchmark.cs

@@ -1,55 +1,54 @@
 using BenchmarkDotNet.Attributes;
 using Jint.Constraints;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class TimeoutBenchmark
 {
-    [MemoryDiagnoser]
-    public class TimeoutBenchmark
-    {
-        private const string Script = "var ret=[],tmp,num=100,i=256;for(var j1=0;j1<i*15;j1++){ret=[];ret.length=i}for(var j2=0;j2<i*10;j2++){ret=new Array(i)}ret=[];for(var j3=0;j3<i;j3++){ret.unshift(j3)}ret=[];for(var j4=0;j4<i;j4++){ret.splice(0,0,j4)}var a=ret.slice();for(var j5=0;j5<i;j5++){tmp=a.shift()}var b=ret.slice();for(var j6=0;j6<i;j6++){tmp=b.splice(0,1)}ret=[];for(var j7=0;j7<i*25;j7++){ret.push(j7)}var c=ret.slice();for(var j8=0;j8<i*25;j8++){tmp=c.pop()}var done = true;";
+    private const string Script = "var ret=[],tmp,num=100,i=256;for(var j1=0;j1<i*15;j1++){ret=[];ret.length=i}for(var j2=0;j2<i*10;j2++){ret=new Array(i)}ret=[];for(var j3=0;j3<i;j3++){ret.unshift(j3)}ret=[];for(var j4=0;j4<i;j4++){ret.splice(0,0,j4)}var a=ret.slice();for(var j5=0;j5<i;j5++){tmp=a.shift()}var b=ret.slice();for(var j6=0;j6<i;j6++){tmp=b.splice(0,1)}ret=[];for(var j7=0;j7<i*25;j7++){ret.push(j7)}var c=ret.slice();for(var j8=0;j8<i*25;j8++){tmp=c.pop()}var done = true;";
 
-        private Engine engineTimeout1;
-        private Engine engineTimeout2;
+    private Engine engineTimeout1;
+    private Engine engineTimeout2;
 
-        [GlobalSetup]
-        public void Setup()
+    [GlobalSetup]
+    public void Setup()
+    {
+        engineTimeout1 = new Engine(options =>
         {
-            engineTimeout1 = new Engine(options =>
-            {
-                options.Constraint(new TimeConstraint(TimeSpan.FromSeconds(5)));
-            });
-
-            engineTimeout2 = new Engine(options =>
-            {
-                options.Constraint(new TimeConstraint2(TimeSpan.FromSeconds(5)));
-            });
-        }
+            options.Constraint(new TimeConstraint(TimeSpan.FromSeconds(5)));
+        });
 
-        [Params(10)]
-        public virtual int N { get; set; }
-
-        [Benchmark]
-        public bool Timeout1()
+        engineTimeout2 = new Engine(options =>
         {
-            bool done = false;
-            for (var i = 0; i < N; i++)
-            {
-                engineTimeout1.Execute(Script);
-            }
+            options.Constraint(new TimeConstraint2(TimeSpan.FromSeconds(5)));
+        });
+    }
 
-            return done;
-        }
+    [Params(10)]
+    public virtual int N { get; set; }
 
-        [Benchmark]
-        public bool Timeout2()
+    [Benchmark]
+    public bool Timeout1()
+    {
+        bool done = false;
+        for (var i = 0; i < N; i++)
         {
-            bool done = false;
-            for (var i = 0; i < N; i++)
-            {
-                engineTimeout2.Execute(Script);
-            }
+            engineTimeout1.Execute(Script);
+        }
+
+        return done;
+    }
 
-            return done;
+    [Benchmark]
+    public bool Timeout2()
+    {
+        bool done = false;
+        for (var i = 0; i < N; i++)
+        {
+            engineTimeout2.Execute(Script);
         }
+
+        return done;
     }
-}
+}

+ 56 - 57
Jint.Benchmark/TypedArrayBenchmark.cs

@@ -1,98 +1,97 @@
 using BenchmarkDotNet.Attributes;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+[MemoryDiagnoser]
+public class TypedArrayBenchmark
 {
-    [MemoryDiagnoser]
-    public class TypedArrayBenchmark
-    {
-        private const string script = @"
+    private const string script = @"
 var testArray = new Int32Array([29, 27, 28, 838, 22, 2882, 2, 93, 84, 74, 7, 933, 3754, 3874, 22838, 38464, 3837, 82424, 2927, 2625, 63, 27, 28, 838, 22, 2882, 2, 93, 84, 74, 7, 933, 3754, 3874, 22838, 38464, 3837, 82424, 2927, 2625, 63, 27, 28, 838, 22, 2882, 2, 93, 84, 74, 7, 933, 3754, 3874, 22838, 38464, 3837, 82424, 2927, 2625, 63, 27, 28, 838, 22, 2882, 2, 93, 84, 74, 7, 933, 3754, 3874, 22838, 38464, 3837, 82424, 2927, 2625, 63]);
 ";
 
-        private Engine engine;
+    private Engine engine;
 
 
-        [GlobalSetup]
-        public void Setup()
-        {
-            engine = new Engine();
-            engine.Execute(script);
-        }
+    [GlobalSetup]
+    public void Setup()
+    {
+        engine = new Engine();
+        engine.Execute(script);
+    }
 
-        [Params(100)]
-        public int N { get; set; }
+    [Params(100)]
+    public int N { get; set; }
 
-        [Benchmark]
-        public void Slice()
+    [Benchmark]
+    public void Slice()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute("testArray.slice();");
-            }
+            engine.Execute("testArray.slice();");
         }
+    }
 
-        [Benchmark]
-        public void Concat()
+    [Benchmark]
+    public void Concat()
+    {
+        // tests conversion performance as TypedArray does not have concat
+        for (var i = 0; i < N; ++i)
         {
-            // tests conversion performance as TypedArray does not have concat
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute("[].concat(testArray);");
-            }
+            engine.Execute("[].concat(testArray);");
         }
+    }
 
-        [Benchmark]
-        public void Index()
+    [Benchmark]
+    public void Index()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute(@"
+            engine.Execute(@"
 var obj2 = new Int32Array(testArray.length);
 for (var i = 0, l = testArray.length; i < l; i++) {
   obj2[i] = testArray[i];
 }
 ");
-            }
         }
+    }
 
-        [Benchmark]
-        public void Map()
+    [Benchmark]
+    public void Map()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute(@"
+            engine.Execute(@"
 var obj2 = testArray.map(function(i) {
   return i;
 });
 ");
-            }
         }
+    }
 
-        [Benchmark]
-        public void Apply()
+    [Benchmark]
+    public void Apply()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute("Array.apply(undefined, testArray);");
-            }
+            engine.Execute("Array.apply(undefined, testArray);");
         }
+    }
 
-        [Benchmark]
-        public void JsonStringifyParse()
+    [Benchmark]
+    public void JsonStringifyParse()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute("JSON.parse(JSON.stringify(testArray));");
-            }
+            engine.Execute("JSON.parse(JSON.stringify(testArray));");
         }
+    }
 
-        [Benchmark]
-        public void FilterWithNumber()
+    [Benchmark]
+    public void FilterWithNumber()
+    {
+        for (var i = 0; i < N; ++i)
         {
-            for (var i = 0; i < N; ++i)
-            {
-                engine.Execute("testArray.filter(function(i) { return i > 55; });");
-            }
+            engine.Execute("testArray.filter(function(i) { return i > 55; });");
         }
     }
 }

+ 73 - 74
Jint.Benchmark/UncacheableExpressionsBenchmark.cs

@@ -4,111 +4,110 @@ using Jint.Native;
 using Newtonsoft.Json;
 using Undefined = Jint.Native.Undefined;
 
-namespace Jint.Benchmark
+namespace Jint.Benchmark;
+
+/// <summary>
+/// Test case for situation where object is projected via filter and map, Jint deems code as uncacheable.
+/// </summary>
+[MemoryDiagnoser]
+public class UncacheableExpressionsBenchmark
 {
-    /// <summary>
-    /// Test case for situation where object is projected via filter and map, Jint deems code as uncacheable.
-    /// </summary>
-    [MemoryDiagnoser]
-    public class UncacheableExpressionsBenchmark
-    {
-        private Document doc;
+    private Document doc;
 
-        private string targetObject;
-        private JsValue[] targetJsObject;
+    private string targetObject;
+    private JsValue[] targetJsObject;
 
-        private const string NonArrowFunctionScript = @"
+    private const string NonArrowFunctionScript = @"
 function output(d) {
     var doc = d.SubDocuments.find(function(x){return x.Id==='testing';});
     return { Id : d.Id, Deleted : d.Deleted, SubTestId : (doc!==null&&doc!==undefined)?doc.Id:null, Values : d.SubDocuments.map(function(x){return {TargetId:x.TargetId,TargetValue:x.TargetValue,SubDocuments:x.SubDocuments.filter(function(s){return (s!==null&&s!==undefined);}).map(function(s){return {TargetId:s.TargetId,TargetValue:s.TargetValue};})};}) };
 }
 ";
 
-        private const string ArrowFunctionScript = @"
+    private const string ArrowFunctionScript = @"
 function output(d) {
     let doc = d.SubDocuments.find(x => x.Id==='testing');
     return { Id : d.Id, Deleted : d.Deleted, SubTestId : (doc!==null&&doc!==undefined)?doc.Id:null, Values : d.SubDocuments.map(x => ({ TargetId:x.TargetId,TargetValue:x.TargetValue,SubDocuments:x.SubDocuments.filter(s => (s!==null&&s!==undefined)).map(s => ({ TargetId: s.TargetId, TargetValue: s.TargetValue}))})) };
 }
 ";
 
-        private Engine engine;
+    private Engine engine;
 
-        public class Document
-        {
-            public string Id { get; set; }
-            public string TargetId { get; set; }
-            public decimal TargetValue { get; set; }
-            public bool Deleted { get; set; }
-            public IEnumerable<Document> SubDocuments { get; set; }
-        }
+    public class Document
+    {
+        public string Id { get; set; }
+        public string TargetId { get; set; }
+        public decimal TargetValue { get; set; }
+        public bool Deleted { get; set; }
+        public IEnumerable<Document> SubDocuments { get; set; }
+    }
 
-        [GlobalSetup]
-        public void Setup()
+    [GlobalSetup]
+    public void Setup()
+    {
+        doc = new Document
         {
-            doc = new Document
+            Deleted = false,
+            SubDocuments = new List<Document>
             {
-                Deleted = false,
-                SubDocuments = new List<Document>
+                new Document
                 {
-                    new Document
-                    {
-                        TargetId = "id1",
-                        SubDocuments = Enumerable.Range(1, 200).Select(x => new Document()).ToList()
-                    },
-                    new Document
-                    {
-                        TargetId = "id2",
-                        SubDocuments = Enumerable.Range(1, 200).Select(x => new Document()).ToList()
-                    }
+                    TargetId = "id1",
+                    SubDocuments = Enumerable.Range(1, 200).Select(x => new Document()).ToList()
+                },
+                new Document
+                {
+                    TargetId = "id2",
+                    SubDocuments = Enumerable.Range(1, 200).Select(x => new Document()).ToList()
                 }
-            };
+            }
+        };
 
-            using (var stream = new MemoryStream())
+        using (var stream = new MemoryStream())
+        {
+            using (var writer = new StreamWriter(stream))
             {
-                using (var writer = new StreamWriter(stream))
-                {
-                    JsonSerializer.CreateDefault().Serialize(writer, doc);
-                    writer.Flush();
+                JsonSerializer.CreateDefault().Serialize(writer, doc);
+                writer.Flush();
 
-                    var targetObjectJson = Encoding.UTF8.GetString(stream.ToArray());
-                    targetObject = $"var d = {targetObjectJson};";
-                }
+                var targetObjectJson = Encoding.UTF8.GetString(stream.ToArray());
+                targetObject = $"var d = {targetObjectJson};";
             }
-
-            CreateEngine(Arrow ? ArrowFunctionScript : NonArrowFunctionScript);
         }
 
-        private static void InitializeEngine(Options options)
-        {
-            options
-                .LimitRecursion(64)
-                .MaxStatements(int.MaxValue)
-                .Strict()
-                .LocalTimeZone(TimeZoneInfo.Utc);
-        }
+        CreateEngine(Arrow ? ArrowFunctionScript : NonArrowFunctionScript);
+    }
 
-        [Params(500)]
-        public int N { get; set; }
+    private static void InitializeEngine(Options options)
+    {
+        options
+            .LimitRecursion(64)
+            .MaxStatements(int.MaxValue)
+            .Strict()
+            .LocalTimeZone(TimeZoneInfo.Utc);
+    }
 
-        [Params(true, false)]
-        public bool Arrow { get; set; }
+    [Params(500)]
+    public int N { get; set; }
 
-        [Benchmark]
-        public void Benchmark()
-        {
-            var call = engine.GetValue("output").TryCast<ICallable>();
-            for (int i = 0; i < N; ++i)
-            {
-                call.Call(Undefined.Instance, targetJsObject);
-            }
-        }
+    [Params(true, false)]
+    public bool Arrow { get; set; }
 
-        private void CreateEngine(string script)
+    [Benchmark]
+    public void Benchmark()
+    {
+        var call = engine.GetValue("output").TryCast<ICallable>();
+        for (int i = 0; i < N; ++i)
         {
-            engine = new Engine(InitializeEngine);
-            engine.Execute(script);
-            engine.Execute(targetObject);
-            targetJsObject = new[] {engine.GetValue("d")};
+            call.Call(Undefined.Instance, targetJsObject);
         }
     }
-}
+
+    private void CreateEngine(string script)
+    {
+        engine = new Engine(InitializeEngine);
+        engine.Execute(script);
+        engine.Execute(targetObject);
+        targetJsObject = new[] {engine.GetValue("d")};
+    }
+}

+ 2 - 2
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -46,8 +46,8 @@ namespace Jint.Native.Function
                 && function.Function is not ArrowFunctionExpression
                 && !function.Function.Generator)
             {
-                DefineOwnProperty(CommonProperties.Arguments, new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(engine, PropertyFlag.Configurable | PropertyFlag.CustomJsValue));
-                DefineOwnProperty(CommonProperties.Caller, new PropertyDescriptor(Undefined, PropertyFlag.Configurable));
+                SetProperty(KnownKeys.Arguments, new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(engine, PropertyFlag.Configurable | PropertyFlag.CustomJsValue));
+                SetProperty(KnownKeys.Caller, new PropertyDescriptor(Undefined, PropertyFlag.Configurable));
             }
         }
 

+ 6 - 16
Jint/Runtime/Interpreter/Statements/JintForStatement.cs

@@ -121,14 +121,13 @@ namespace Jint.Runtime.Interpreter.Statements
                 CreatePerIterationEnvironment(context);
             }
 
+            var debugHandler = context.DebugMode ? context.Engine.DebugHandler : null;
+
             while (true)
             {
                 if (_test != null)
                 {
-                    if (context.DebugMode)
-                    {
-                        context.Engine.DebugHandler.OnStep(_test._expression);
-                    }
+                    debugHandler?.OnStep(_test._expression);
 
                     if (!TypeConverter.ToBoolean(_test.GetValue(context).Value))
                     {
@@ -162,30 +161,21 @@ namespace Jint.Runtime.Interpreter.Statements
 
                 if (_increment != null)
                 {
-                    if (context.DebugMode)
-                    {
-                        context.Engine.DebugHandler.OnStep(_increment._expression);
-                    }
-
-                    _increment.GetValue(context);
+                    debugHandler?.OnStep(_increment._expression);
+                    _increment.Evaluate(context);
                 }
             }
         }
 
         private void CreatePerIterationEnvironment(EvaluationContext context)
         {
-            if (_boundNames == null || _boundNames.Count == 0)
-            {
-                return;
-            }
-
             var engine = context.Engine;
             var lastIterationEnv = engine.ExecutionContext.LexicalEnvironment;
             var lastIterationEnvRec = lastIterationEnv;
             var outer = lastIterationEnv._outerEnv;
             var thisIterationEnv = JintEnvironment.NewDeclarativeEnvironment(engine, outer);
 
-            for (var j = 0; j < _boundNames.Count; j++)
+            for (var j = 0; j < _boundNames!.Count; j++)
             {
                 var bn = _boundNames[j];
                 var lastValue = lastIterationEnvRec.GetBindingValue(bn, true);

+ 1 - 0
Jint/Runtime/KnownKeys.cs

@@ -3,6 +3,7 @@ namespace Jint.Runtime
     internal static class KnownKeys
     {
         internal static readonly Key Arguments = "arguments";
+        internal static readonly Key Caller = "caller";
         internal static readonly Key Eval = "eval";
         internal static readonly Key Length = "length";
         internal static readonly Key Done = "done";

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است