Browse Source

Add support for block statement preparation (#2048)

* fix benchmark issues between modern and classic in dromaeo-object-string
Marko Lahma 5 months ago
parent
commit
7ab17c55e5

+ 1 - 1
Jint.Benchmark/Scripts/dromaeo-object-string-modern.js

@@ -2,7 +2,7 @@
 
 // Try to force real results
 let ret;
-const num = 80000;
+const num = 5000;
 
 // TESTS: String concatenation
 

+ 1 - 1
Jint.Benchmark/Scripts/dromaeo-object-string.js

@@ -2,7 +2,7 @@
 
 // Try to force real results
 var ret;
-var num = 80000;
+var num = 5000;
 
 // TESTS: String concatenation
 

+ 5 - 2
Jint/Engine.Ast.cs

@@ -100,8 +100,7 @@ public partial class Engine
                 case NodeType.ArrowFunctionExpression:
                 case NodeType.FunctionDeclaration:
                 case NodeType.FunctionExpression:
-                    var function = (IFunction) node;
-                    node.UserData = JintFunctionDefinition.BuildState(function);
+                    node.UserData = JintFunctionDefinition.BuildState((IFunction) node);
                     break;
 
                 case NodeType.Program:
@@ -151,6 +150,10 @@ public partial class Engine
                         }
                     }
                     break;
+
+                case NodeType.BlockStatement:
+                    node.UserData = JintBlockStatement.BuildState((BlockStatement) node);
+                    break;
             }
         }
     }

+ 8 - 3
Jint/Engine.cs

@@ -1149,11 +1149,14 @@ public sealed partial class Engine : IDisposable
 
         UpdateLexicalEnvironment(lexEnv);
 
-        if (configuration.LexicalDeclarations?.Declarations.Count > 0)
+        var declarations = configuration.LexicalDeclarations;
+        if (declarations?.Declarations.Count > 0)
         {
-            var lexicalDeclarations = configuration.LexicalDeclarations.Value.Declarations;
-            var dictionary = lexEnv._dictionary ??= new HybridDictionary<Binding>(lexicalDeclarations.Count, checkExistingKeys: true);
+            var lexicalDeclarations = declarations.Value.Declarations;
+            var checkExistingKeys = (lexEnv._dictionary is not null && lexEnv._dictionary.Count > 0) || !declarations.Value.AllLexicalScoped;
+            var dictionary = lexEnv._dictionary ??= new HybridDictionary<Binding>(lexicalDeclarations.Count, checkExistingKeys);
             dictionary.EnsureCapacity(dictionary.Count + lexicalDeclarations.Count);
+
             for (var i = 0; i < lexicalDeclarations.Count; i++)
             {
                 var declaration = lexicalDeclarations[i];
@@ -1169,6 +1172,8 @@ public sealed partial class Engine : IDisposable
                     }
                 }
             }
+
+            dictionary.CheckExistingKeys = true;
         }
 
         if (configuration.FunctionsToInitialize != null)

+ 6 - 1
Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs

@@ -15,7 +15,7 @@ internal sealed class JintBlockStatement : JintStatement<NestedBlockStatement>
 
     protected override void Initialize(EvaluationContext context)
     {
-        _lexicalDeclarations = DeclarationCacheBuilder.Build(_statement);
+        _lexicalDeclarations = (DeclarationCache) (_statement.UserData ??= BuildState(_statement));
 
         if (_statement.Body.Count == 1)
         {
@@ -27,6 +27,11 @@ internal sealed class JintBlockStatement : JintStatement<NestedBlockStatement>
         }
     }
 
+    internal static DeclarationCache BuildState(BlockStatement blockStatement)
+    {
+        return DeclarationCacheBuilder.Build(blockStatement);
+    }
+
     /// <summary>
     /// Optimized for direct access without virtual dispatch.
     /// </summary>