Browse Source

Some small performance improvements for JsValue.

ObjectWrapper now caches method descriptors rather than recreating them
each call and JsValue no longer uses nullable types for to avoid the
overhead of nullables.
Alastair 10 years ago
parent
commit
b9f33a731b
2 changed files with 129 additions and 129 deletions
  1. 18 27
      Jint/Native/JsValue.cs
  2. 111 102
      Jint/Runtime/Interop/ObjectWrapper .cs

+ 18 - 27
Jint/Native/JsValue.cs

@@ -14,6 +14,7 @@ using Jint.Native.RegExp;
 using Jint.Native.String;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
+using System.Runtime.CompilerServices;
 
 namespace Jint.Native
 {
@@ -28,25 +29,25 @@ namespace Jint.Native
         public JsValue(bool value)
         {
             _bool = value;
-            _double = null;
+            _double = double.NaN;
             _object = null;
-            _string = null;
+            _string = System.String.Empty;
             _type = Types.Boolean;
         }
 
         public JsValue(double value)
         {
-            _bool = null;
+            _bool = false;
             _double = value;
             _object = null;
-            _string = null;
+            _string = System.String.Empty;
             _type = Types.Number;
         }
 
         public JsValue(string value)
         {
-            _bool = null;
-            _double = null;
+            _bool = false;
+            _double = double.NaN;
             _object = null;
             _string = value;
             _type = Types.String;
@@ -54,25 +55,25 @@ namespace Jint.Native
 
         public JsValue(ObjectInstance value)
         {
-            _bool = null;
-            _double = null;
+            _bool = false;
+            _double = double.NaN;
             _object = value;
-            _string = null;
+            _string = System.String.Empty;
             _type = Types.Object;
         }
 
         private JsValue(Types type)
         {
-            _bool = null;
-            _double = null;
+            _bool = false;
+            _double = double.NaN;
             _object = null;
-            _string = null;
+            _string = System.String.Empty;
             _type = type;
         }
 
-        private readonly bool? _bool;
+        private readonly bool _bool;
 
-        private readonly double? _double;
+        private readonly double _double;
 
         private readonly ObjectInstance _object;
 
@@ -194,12 +195,7 @@ namespace Jint.Native
                 throw new ArgumentException("The value is not a boolean");
             }
 
-            if (!_bool.HasValue)
-            {
-                throw new ArgumentException("The value is not defined");
-            }
-
-            return _bool.Value;
+            return _bool;
         }
 
         [Pure]
@@ -210,7 +206,7 @@ namespace Jint.Native
                 throw new ArgumentException("The value is not a string");
             }
 
-            if (_string == null)
+            if (_string == System.String.Empty)
             {
                 throw new ArgumentException("The value is not defined");
             }
@@ -226,12 +222,7 @@ namespace Jint.Native
                 throw new ArgumentException("The value is not a number");
             }
 
-            if (!_double.HasValue)
-            {
-                throw new ArgumentException("The value is not defined");
-            }
-
-            return _double.Value;
+            return _double;
         }
 
         public bool Equals(JsValue other)

+ 111 - 102
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -1,93 +1,100 @@
-using System;
-using System.Linq;
-using System.Reflection;
-using Jint.Native;
-using Jint.Native.Object;
-using Jint.Runtime.Descriptors;
+using System;
+using System.Linq;
+using System.Reflection;
+using Jint.Native;
+using Jint.Native.Object;
+using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors.Specialized;
-using System.Collections;
-
-namespace Jint.Runtime.Interop
-{
-    /// <summary>
-    /// Wrapps a CLR instance
-    /// </summary>
-    public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper
-    {
-        public Object Target { get; set; }
-
-        public ObjectWrapper(Engine engine, Object obj): base(engine)
-        {
-            Target = obj;
-        }
-
-        public override void Put(string propertyName, JsValue value, bool throwOnError)
-        {
-            if (!CanPut(propertyName))
-            {
-                if (throwOnError)
-                {
-                    throw new JavaScriptException(Engine.TypeError);
-                }
-
-                return;
-            }
-
-            var ownDesc = GetOwnProperty(propertyName);
-
-            if (ownDesc == null)
-            {
-                if (throwOnError)
-                {
-                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
-                }
-                else
-                {
-                    return;
-                }
-            }
-
-            ownDesc.Value = value;
-        }
-
-        public override PropertyDescriptor GetOwnProperty(string propertyName)
-        {
-            PropertyDescriptor x;
-            if (Properties.TryGetValue(propertyName, out x))
-            {
-                return x;
-            }
-
-            var type = Target.GetType();
-
-            // look for a property
-            var property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
-
-            if (property != null)
-            {
-                var descriptor = new PropertyInfoDescriptor(Engine, property, Target);
-                Properties.Add(propertyName, descriptor);
-                return descriptor;
-            }
-
-            // look for a field
-            var field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public);
-
-            if (field != null)
-            {
-                var descriptor = new FieldInfoDescriptor(Engine, field, Target);
-                Properties.Add(propertyName, descriptor);
-                return descriptor;
-            }
-
-            // if no properties were found then look for a method 
-            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
-                .Where(m => m.Name == propertyName)
-                .ToArray();
-
-            if (methods.Any())
-            {
-                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, methods), false, true, false);
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Jint.Runtime.Interop
+{
+    /// <summary>
+    /// Wraps a CLR instance
+    /// </summary>
+    public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper
+    {
+        public Object Target { get; set; }
+
+        /// <summary>
+        /// A private instance to cache methods
+        /// </summary>
+        private Dictionary<string, Delegate> DelegateCache = new Dictionary<string, Delegate>();
+
+        public ObjectWrapper(Engine engine, Object obj)
+            : base(engine)
+        {
+            Target = obj;
+        }
+
+        public override void Put(string propertyName, JsValue value, bool throwOnError)
+        {
+            if (!CanPut(propertyName))
+            {
+                if (throwOnError)
+                {
+                    throw new JavaScriptException(Engine.TypeError);
+                }
+
+                return;
+            }
+
+            var ownDesc = GetOwnProperty(propertyName);
+
+            if (ownDesc == null)
+            {
+                if (throwOnError)
+                {
+                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
+                }
+                else
+                {
+                    return;
+                }
+            }
+
+            ownDesc.Value = value;
+        }
+
+        public override PropertyDescriptor GetOwnProperty(string propertyName)
+        {
+            PropertyDescriptor x;
+            if (Properties.TryGetValue(propertyName, out x))
+                return x;
+
+            var type = Target.GetType();
+
+            // look for a property
+            var property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
+
+            if (property != null)
+            {
+                var descriptor = new PropertyInfoDescriptor(Engine, property, Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // look for a field
+            var field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public);
+
+            if (field != null)
+            {
+                var descriptor = new FieldInfoDescriptor(Engine, field, Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // if no properties were found then look for a method 
+            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
+                .Where(m => m.Name == propertyName)
+                .ToArray();
+
+            if (methods.Any())
+            {
+                var descriptor = new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, methods), false, true, false);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
             }
 
             // if no methods are found check if target implemented indexing
@@ -102,9 +109,9 @@ namespace Jint.Runtime.Interop
             var explicitProperties = (from iface in interfaces
                                       from iprop in iface.GetProperties()
                                       where propertyName.Equals(iprop.Name)
-                                      select iprop).ToList();
+                                      select iprop).ToArray();
 
-            if (explicitProperties.Count == 1)
+            if (explicitProperties.Length == 1)
             {
                 var descriptor = new PropertyInfoDescriptor(Engine, explicitProperties[0], Target);
                 Properties.Add(propertyName, descriptor);
@@ -115,11 +122,13 @@ namespace Jint.Runtime.Interop
             var explicitMethods = (from iface in interfaces
                                    from imethod in iface.GetMethods()
                                    where propertyName.Equals(imethod.Name)
-                                   select imethod).ToList();
+                                   select imethod).ToArray();
 
-            if (explicitMethods.Count > 0)
+            if (explicitMethods.Length > 0)
             {
-                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, explicitMethods.ToArray()), false, true, false);
+                var descriptor = new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, explicitMethods), false, true, false);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
             }
 
             // try to find explicit indexer implementations
@@ -127,14 +136,14 @@ namespace Jint.Runtime.Interop
                 (from iface in interfaces
                  from iprop in iface.GetProperties()
                  where iprop.GetIndexParameters().Length != 0
-                 select iprop).ToList();
+                 select iprop).ToArray();
 
-            if (explicitIndexers.Count == 1)
+            if (explicitIndexers.Length == 1)
             {
                 return new IndexDescriptor(Engine, explicitIndexers[0].DeclaringType, propertyName, Target);
-            }
-
-            return PropertyDescriptor.Undefined;
-        }
-    }
-}
+            }
+
+            return PropertyDescriptor.Undefined;
+        }
+    }
+}