Browse Source

Caching literals

Sebastien Ros 9 years ago
parent
commit
85bf11fc92

+ 6 - 1
Jint/Parser/Ast/CallExpression.cs

@@ -1,3 +1,4 @@
+using Jint.Native;
 using System.Collections.Generic;
 
 namespace Jint.Parser.Ast
@@ -5,6 +6,10 @@ namespace Jint.Parser.Ast
     public class CallExpression : Expression
     {
         public Expression Callee;
-        public IEnumerable<Expression> Arguments;
+        public IList<Expression> Arguments;
+
+        public bool Cached;
+        public bool CanBeCached = true;
+        public JsValue[] CachedArguments;
     }
 }

+ 6 - 0
Jint/Parser/Ast/Literal.cs

@@ -1,3 +1,5 @@
+using Jint.Native;
+
 namespace Jint.Parser.Ast
 {
     public class Literal : Expression, IPropertyKeyExpression
@@ -5,9 +7,13 @@ namespace Jint.Parser.Ast
         public object Value;
         public string Raw;
 
+        public bool Cached;
+        public JsValue CachedValue; 
+
         public string GetKey()
         {
             return Value.ToString();
         }
+
     }
 }

+ 3 - 3
Jint/Parser/JavascriptParser.cs

@@ -1452,7 +1452,7 @@ namespace Jint.Parser
                 };
         }
 
-        public CallExpression CreateCallExpression(Expression callee, IEnumerable<Expression> args)
+        public CallExpression CreateCallExpression(Expression callee, IList<Expression> args)
         {
             return new CallExpression
                 {
@@ -2328,7 +2328,7 @@ namespace Jint.Parser
 
         // 11.2 Left-Hand-Side Expressions
 
-        private IEnumerable<Expression> ParseArguments()
+        private IList<Expression> ParseArguments()
         {
             var args = new List<Expression>();
 
@@ -2406,7 +2406,7 @@ namespace Jint.Parser
             {
                 if (Match("("))
                 {
-                    IEnumerable<Expression> args = ParseArguments();
+                    IList<Expression> args = ParseArguments();
                     expr = CreateCallExpression(expr, args);
                 }
                 else if (Match("["))

+ 36 - 4
Jint/Runtime/ExpressionIntepreter.cs

@@ -625,12 +625,19 @@ namespace Jint.Runtime
 
         public JsValue EvaluateLiteral(Literal literal)
         {
-            if (literal.Type == SyntaxNodes.RegularExpressionLiteral)
+            if(literal.Cached)
             {
-                return _engine.RegExp.Construct(literal.Raw);
+                return literal.CachedValue;
             }
 
-            return JsValue.FromObject(_engine, literal.Value);
+            literal.Cached = true;
+
+            if (literal.Type == SyntaxNodes.RegularExpressionLiteral)
+            {
+                return literal.CachedValue = _engine.RegExp.Construct(literal.Raw);
+            }
+            
+            return literal.CachedValue = JsValue.FromObject(_engine, literal.Value);
         }
 
         public JsValue EvaluateObjectExpression(ObjectExpression objectExpression)
@@ -799,7 +806,32 @@ namespace Jint.Runtime
             JsValue thisObject;
 
             // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4
-            var arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
+
+
+            JsValue[] arguments;
+
+            if (callExpression.Cached)
+            {
+                arguments = callExpression.CachedArguments;
+            }
+            else
+            {
+                arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
+
+                if (callExpression.CanBeCached)
+                {
+                    // The arguments array can be cached if they are all literals
+                    if (callExpression.Arguments.All(x => x is Literal))
+                    {
+                        callExpression.Cached = true;
+                        callExpression.CachedArguments = arguments;
+                    }
+                    else
+                    {
+                        callExpression.CanBeCached = false;
+                    }
+                }
+            }
 
             var func = _engine.GetValue(callee);