Browse Source

Reduce virtual calls and optimize JsValue equality checks (#497)

Marko Lahma 7 years ago
parent
commit
5d408955dc
50 changed files with 551 additions and 506 deletions
  1. 51 49
      Jint/Engine.cs
  2. 9 7
      Jint/Native/Argument/ArgumentsInstance.cs
  3. 6 5
      Jint/Native/Array/ArrayInstance.cs
  4. 7 7
      Jint/Native/Array/ArrayPrototype.cs
  5. 4 16
      Jint/Native/Boolean/BooleanInstance.cs
  6. 6 10
      Jint/Native/Boolean/BooleanPrototype.cs
  7. 1 1
      Jint/Native/Error/ErrorConstructor.cs
  8. 1 1
      Jint/Native/Error/ErrorPrototype.cs
  9. 3 4
      Jint/Native/Function/FunctionConstructor.cs
  10. 4 4
      Jint/Native/Function/FunctionInstance.cs
  11. 6 6
      Jint/Native/Function/FunctionPrototype.cs
  12. 4 3
      Jint/Native/Function/ScriptFunctionInstance.cs
  13. 7 6
      Jint/Native/JsBoolean.cs
  14. 1 3
      Jint/Native/JsNull.cs
  15. 3 5
      Jint/Native/JsNumber.cs
  16. 2 4
      Jint/Native/JsString.cs
  17. 1 3
      Jint/Native/JsSymbol.cs
  18. 1 3
      Jint/Native/JsUndefined.cs
  19. 99 37
      Jint/Native/JsValue.cs
  20. 3 9
      Jint/Native/Json/JsonInstance.cs
  21. 3 3
      Jint/Native/Json/JsonSerializer.cs
  22. 7 17
      Jint/Native/Number/NumberInstance.cs
  23. 6 4
      Jint/Native/Number/NumberPrototype.cs
  24. 15 15
      Jint/Native/Object/ObjectConstructor.cs
  25. 45 111
      Jint/Native/Object/ObjectInstance.cs
  26. 1 1
      Jint/Native/Object/ObjectPrototype.cs
  27. 12 13
      Jint/Native/RegExp/RegExpConstructor.cs
  28. 3 3
      Jint/Native/RegExp/RegExpPrototype.cs
  29. 15 11
      Jint/Native/String/StringPrototype.cs
  30. 3 15
      Jint/Native/Symbol/SymbolInstance.cs
  31. 2 2
      Jint/Native/Symbol/SymbolPrototype.cs
  32. 16 3
      Jint/Options.cs
  33. 1 1
      Jint/Pooling/ArgumentsInstancePool.cs
  34. 24 4
      Jint/Runtime/Completion.cs
  35. 2 2
      Jint/Runtime/Debugger/DebugHandler.cs
  36. 75 29
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  37. 3 1
      Jint/Runtime/Descriptors/PropertyFlag.cs
  38. 1 1
      Jint/Runtime/Descriptors/Specialized/ClrAccessDescriptor.cs
  39. 3 7
      Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs
  40. 7 0
      Jint/Runtime/Descriptors/Specialized/GetSetPropertyDescriptor.cs
  41. 5 6
      Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs
  42. 3 7
      Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs
  43. 1 1
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  44. 19 17
      Jint/Runtime/ExpressionIntepreter.cs
  45. 1 1
      Jint/Runtime/Interop/NamespaceReference.cs
  46. 1 1
      Jint/Runtime/Interop/TypeReference.cs
  47. 2 2
      Jint/Runtime/JavaScriptException.cs
  48. 8 1
      Jint/Runtime/References/Reference.cs
  49. 22 23
      Jint/Runtime/StatementInterpreter.cs
  50. 26 21
      Jint/Runtime/TypeConverter.cs

+ 51 - 49
Jint/Engine.cs

@@ -206,7 +206,7 @@ namespace Jint
 
 
         public GlobalSymbolRegistry GlobalSymbolRegistry { get; }
         public GlobalSymbolRegistry GlobalSymbolRegistry { get; }
 
 
-        internal Options Options { get; }
+        internal Options Options { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }
 
 
         internal ReferencePool ReferencePool { get; }
         internal ReferencePool ReferencePool { get; }
         internal CompletionPool CompletionPool { get; }
         internal CompletionPool CompletionPool { get; }
@@ -382,64 +382,64 @@ namespace Jint
             switch (statement.Type)
             switch (statement.Type)
             {
             {
                 case Nodes.BlockStatement:
                 case Nodes.BlockStatement:
-                    return _statements.ExecuteBlockStatement(statement.As<BlockStatement>());
+                    return _statements.ExecuteBlockStatement((BlockStatement) statement);
 
 
                 case Nodes.ReturnStatement:
                 case Nodes.ReturnStatement:
-                    return _statements.ExecuteReturnStatement(statement.As<ReturnStatement>());
+                    return _statements.ExecuteReturnStatement((ReturnStatement) statement);
 
 
                 case Nodes.VariableDeclaration:
                 case Nodes.VariableDeclaration:
-                    return _statements.ExecuteVariableDeclaration(statement.As<VariableDeclaration>());
+                    return _statements.ExecuteVariableDeclaration((VariableDeclaration) statement);
 
 
                 case Nodes.BreakStatement:
                 case Nodes.BreakStatement:
-                    return _statements.ExecuteBreakStatement(statement.As<BreakStatement>());
+                    return _statements.ExecuteBreakStatement((BreakStatement) statement);
 
 
                 case Nodes.ContinueStatement:
                 case Nodes.ContinueStatement:
-                    return _statements.ExecuteContinueStatement(statement.As<ContinueStatement>());
+                    return _statements.ExecuteContinueStatement((ContinueStatement) statement);
 
 
                 case Nodes.DoWhileStatement:
                 case Nodes.DoWhileStatement:
-                    return _statements.ExecuteDoWhileStatement(statement.As<DoWhileStatement>());
+                    return _statements.ExecuteDoWhileStatement((DoWhileStatement) statement);
 
 
                 case Nodes.EmptyStatement:
                 case Nodes.EmptyStatement:
-                    return _statements.ExecuteEmptyStatement(statement.As<EmptyStatement>());
+                    return _statements.ExecuteEmptyStatement((EmptyStatement) statement);
 
 
                 case Nodes.ExpressionStatement:
                 case Nodes.ExpressionStatement:
-                    return _statements.ExecuteExpressionStatement(statement.As<ExpressionStatement>());
+                    return _statements.ExecuteExpressionStatement((ExpressionStatement) statement);
 
 
                 case Nodes.ForStatement:
                 case Nodes.ForStatement:
-                    return _statements.ExecuteForStatement(statement.As<ForStatement>());
+                    return _statements.ExecuteForStatement((ForStatement) statement);
 
 
                 case Nodes.ForInStatement:
                 case Nodes.ForInStatement:
-                    return _statements.ExecuteForInStatement(statement.As<ForInStatement>());
+                    return _statements.ExecuteForInStatement((ForInStatement) statement);
 
 
                 case Nodes.IfStatement:
                 case Nodes.IfStatement:
-                    return _statements.ExecuteIfStatement(statement.As<IfStatement>());
+                    return _statements.ExecuteIfStatement((IfStatement) statement);
 
 
                 case Nodes.LabeledStatement:
                 case Nodes.LabeledStatement:
-                    return _statements.ExecuteLabeledStatement(statement.As<LabeledStatement>());
+                    return _statements.ExecuteLabeledStatement((LabeledStatement) statement);
 
 
                 case Nodes.SwitchStatement:
                 case Nodes.SwitchStatement:
-                    return _statements.ExecuteSwitchStatement(statement.As<SwitchStatement>());
+                    return _statements.ExecuteSwitchStatement((SwitchStatement) statement);
 
 
                 case Nodes.FunctionDeclaration:
                 case Nodes.FunctionDeclaration:
                     return Completion.Empty;
                     return Completion.Empty;
 
 
                 case Nodes.ThrowStatement:
                 case Nodes.ThrowStatement:
-                    return _statements.ExecuteThrowStatement(statement.As<ThrowStatement>());
+                    return _statements.ExecuteThrowStatement((ThrowStatement) statement);
 
 
                 case Nodes.TryStatement:
                 case Nodes.TryStatement:
-                    return _statements.ExecuteTryStatement(statement.As<TryStatement>());
+                    return _statements.ExecuteTryStatement((TryStatement) statement);
 
 
                 case Nodes.WhileStatement:
                 case Nodes.WhileStatement:
-                    return _statements.ExecuteWhileStatement(statement.As<WhileStatement>());
+                    return _statements.ExecuteWhileStatement((WhileStatement) statement);
 
 
                 case Nodes.WithStatement:
                 case Nodes.WithStatement:
-                    return _statements.ExecuteWithStatement(statement.As<WithStatement>());
+                    return _statements.ExecuteWithStatement((WithStatement) statement);
 
 
                 case Nodes.DebuggerStatement:
                 case Nodes.DebuggerStatement:
-                    return _statements.ExecuteDebuggerStatement(statement.As<DebuggerStatement>());
+                    return _statements.ExecuteDebuggerStatement((DebuggerStatement) statement);
 
 
                 case Nodes.Program:
                 case Nodes.Program:
-                    return _statements.ExecuteProgram(statement.As<Program>());
+                    return _statements.ExecuteProgram((Program) statement);
 
 
                 default:
                 default:
                     throw new ArgumentOutOfRangeException();
                     throw new ArgumentOutOfRangeException();
@@ -453,52 +453,52 @@ namespace Jint
             switch (expression.Type)
             switch (expression.Type)
             {
             {
                 case Nodes.AssignmentExpression:
                 case Nodes.AssignmentExpression:
-                    return _expressions.EvaluateAssignmentExpression(expression.As<AssignmentExpression>());
+                    return _expressions.EvaluateAssignmentExpression((AssignmentExpression) expression);
 
 
                 case Nodes.ArrayExpression:
                 case Nodes.ArrayExpression:
-                    return _expressions.EvaluateArrayExpression(expression.As<ArrayExpression>());
+                    return _expressions.EvaluateArrayExpression((ArrayExpression) expression);
 
 
                 case Nodes.BinaryExpression:
                 case Nodes.BinaryExpression:
-                    return _expressions.EvaluateBinaryExpression(expression.As<BinaryExpression>());
+                    return _expressions.EvaluateBinaryExpression((BinaryExpression) expression);
 
 
                 case Nodes.CallExpression:
                 case Nodes.CallExpression:
-                    return _expressions.EvaluateCallExpression(expression.As<CallExpression>());
+                    return _expressions.EvaluateCallExpression((CallExpression) expression);
 
 
                 case Nodes.ConditionalExpression:
                 case Nodes.ConditionalExpression:
-                    return _expressions.EvaluateConditionalExpression(expression.As<ConditionalExpression>());
+                    return _expressions.EvaluateConditionalExpression((ConditionalExpression) expression);
 
 
                 case Nodes.FunctionExpression:
                 case Nodes.FunctionExpression:
-                    return _expressions.EvaluateFunctionExpression(expression.As<IFunction>());
+                    return _expressions.EvaluateFunctionExpression((IFunction) expression);
 
 
                 case Nodes.Identifier:
                 case Nodes.Identifier:
-                    return _expressions.EvaluateIdentifier(expression.As<Identifier>());
+                    return _expressions.EvaluateIdentifier((Identifier) expression);
 
 
                 case Nodes.Literal:
                 case Nodes.Literal:
-                    return _expressions.EvaluateLiteral(expression.As<Literal>());
+                    return _expressions.EvaluateLiteral((Literal) expression);
 
 
                 case Nodes.LogicalExpression:
                 case Nodes.LogicalExpression:
-                    return _expressions.EvaluateLogicalExpression(expression.As<BinaryExpression>());
+                    return _expressions.EvaluateLogicalExpression((BinaryExpression) expression);
 
 
                 case Nodes.MemberExpression:
                 case Nodes.MemberExpression:
-                    return _expressions.EvaluateMemberExpression(expression.As<MemberExpression>());
+                    return _expressions.EvaluateMemberExpression((MemberExpression) expression);
 
 
                 case Nodes.NewExpression:
                 case Nodes.NewExpression:
-                    return _expressions.EvaluateNewExpression(expression.As<NewExpression>());
+                    return _expressions.EvaluateNewExpression((NewExpression) expression);
 
 
                 case Nodes.ObjectExpression:
                 case Nodes.ObjectExpression:
-                    return _expressions.EvaluateObjectExpression(expression.As<ObjectExpression>());
+                    return _expressions.EvaluateObjectExpression((ObjectExpression) expression);
 
 
                 case Nodes.SequenceExpression:
                 case Nodes.SequenceExpression:
-                    return _expressions.EvaluateSequenceExpression(expression.As<SequenceExpression>());
+                    return _expressions.EvaluateSequenceExpression((SequenceExpression) expression);
 
 
                 case Nodes.ThisExpression:
                 case Nodes.ThisExpression:
-                    return _expressions.EvaluateThisExpression(expression.As<ThisExpression>());
+                    return _expressions.EvaluateThisExpression((ThisExpression) expression);
 
 
                 case Nodes.UpdateExpression:
                 case Nodes.UpdateExpression:
-                    return _expressions.EvaluateUpdateExpression(expression.As<UpdateExpression>());
+                    return _expressions.EvaluateUpdateExpression((UpdateExpression) expression);
 
 
                 case Nodes.UnaryExpression:
                 case Nodes.UnaryExpression:
-                    return _expressions.EvaluateUnaryExpression(expression.As<UnaryExpression>());
+                    return _expressions.EvaluateUnaryExpression((UnaryExpression) expression);
 
 
                 default:
                 default:
                     throw new ArgumentOutOfRangeException();
                     throw new ArgumentOutOfRangeException();
@@ -519,7 +519,8 @@ namespace Jint
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal JsValue GetValue(object value, bool returnReferenceToPool)
         internal JsValue GetValue(object value, bool returnReferenceToPool)
         {
         {
-            if (value is JsValue jsValue)
+            var jsValue = value as JsValue;
+            if (!ReferenceEquals(jsValue, null))
             {
             {
                 return jsValue;
                 return jsValue;
             }
             }
@@ -590,7 +591,7 @@ namespace Jint
             }
             }
 
 
             var record = (EnvironmentRecord) baseValue;
             var record = (EnvironmentRecord) baseValue;
-            if (record == null)
+            if (ReferenceEquals(record, null))
             {
             {
                 throw new ArgumentException();
                 throw new ArgumentException();
             }
             }
@@ -638,7 +639,7 @@ namespace Jint
                 var baseValue = reference.GetBase();
                 var baseValue = reference.GetBase();
                 var record = baseValue as EnvironmentRecord;
                 var record = baseValue as EnvironmentRecord;
 
 
-                if (record == null)
+                if (ReferenceEquals(record, null))
                 {
                 {
                     throw new ArgumentNullException();
                     throw new ArgumentNullException();
                 }
                 }
@@ -837,19 +838,20 @@ namespace Jint
                 }
                 }
                 else
                 else
                 {
                 {
-                    if (env == GlobalEnvironment.Record)
+                    if (ReferenceEquals(env, GlobalEnvironment.Record))
                     {
                     {
                         var go = Global;
                         var go = Global;
                         var existingProp = go.GetProperty(fn);
                         var existingProp = go.GetProperty(fn);
                         if (existingProp.Configurable)
                         if (existingProp.Configurable)
                         {
                         {
-                            go.DefineOwnProperty(fn,
-                                new PropertyDescriptor(
-                                    value: Undefined.Instance,
-                                    writable: true,
-                                    enumerable: true,
-                                    configurable: configurableBindings
-                                ), true);
+                            var flags = PropertyFlag.Writable | PropertyFlag.Enumerable;
+                            if (configurableBindings)
+                            {
+                                flags |= PropertyFlag.Configurable;
+                            }
+
+                            var descriptor = new PropertyDescriptor(Undefined.Instance, flags);
+                            go.DefineOwnProperty(fn, descriptor, true);
                         }
                         }
                         else
                         else
                         {
                         {
@@ -874,7 +876,7 @@ namespace Jint
                 {
                 {
                     var declEnv = env as DeclarativeEnvironmentRecord;
                     var declEnv = env as DeclarativeEnvironmentRecord;
 
 
-                    if (declEnv == null)
+                    if (ReferenceEquals(declEnv, null))
                     {
                     {
                         throw new ArgumentException();
                         throw new ArgumentException();
                     }
                     }
@@ -896,7 +898,7 @@ namespace Jint
                 for (var j = 0; j < declarationsCount; j++)
                 for (var j = 0; j < declarationsCount; j++)
                 {
                 {
                     var d = variableDeclaration.Declarations[j];
                     var d = variableDeclaration.Declarations[j];
-                    var dn = d.Id.As<Identifier>().Name;
+                    var dn = ((Identifier) d.Id).Name;
                     var varAlreadyDeclared = env.HasBinding(dn);
                     var varAlreadyDeclared = env.HasBinding(dn);
                     if (!varAlreadyDeclared)
                     if (!varAlreadyDeclared)
                     {
                     {

+ 9 - 7
Jint/Native/Argument/ArgumentsInstance.cs

@@ -93,8 +93,9 @@ namespace Jint.Native.Argument
             else
             else
             {
             {
                 var thrower = Engine.Function.ThrowTypeError;
                 var thrower = Engine.Function.ThrowTypeError;
-                self.DefineOwnProperty("caller", new GetSetPropertyDescriptor(get: thrower, set: thrower, enumerable: false, configurable: false), false);
-                self.DefineOwnProperty("callee", new GetSetPropertyDescriptor(get: thrower, set: thrower, enumerable: false, configurable: false), false);
+                const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
+                self.DefineOwnProperty("caller", new GetSetPropertyDescriptor(get: thrower, set: thrower, flags), false);
+                self.DefineOwnProperty("callee", new GetSetPropertyDescriptor(get: thrower, set: thrower, flags), false);
             }
             }
         }
         }
 
 
@@ -106,7 +107,7 @@ namespace Jint.Native.Argument
         {
         {
             EnsureInitialized();
             EnsureInitialized();
 
 
-            if (!Strict && ParameterMap != null)
+            if (!Strict && !ReferenceEquals(ParameterMap, null))
             {
             {
                 var desc = base.GetOwnProperty(propertyName);
                 var desc = base.GetOwnProperty(propertyName);
                 if (desc == PropertyDescriptor.Undefined)
                 if (desc == PropertyDescriptor.Undefined)
@@ -171,7 +172,7 @@ namespace Jint.Native.Argument
         {
         {
             EnsureInitialized();
             EnsureInitialized();
 
 
-            if (!Strict && ParameterMap != null)
+            if (!Strict && !ReferenceEquals(ParameterMap, null))
             {
             {
                 var map = ParameterMap;
                 var map = ParameterMap;
                 var isMapped = map.GetOwnProperty(propertyName);
                 var isMapped = map.GetOwnProperty(propertyName);
@@ -192,9 +193,10 @@ namespace Jint.Native.Argument
                     }
                     }
                     else
                     else
                     {
                     {
-                        if (desc.Value != null && desc.Value != Undefined)
+                        var descValue = desc.Value;
+                        if (!ReferenceEquals(descValue, null) && !ReferenceEquals(descValue, Undefined))
                         {
                         {
-                            map.Put(propertyName, desc.Value, throwOnError);
+                            map.Put(propertyName, descValue, throwOnError);
                         }
                         }
 
 
                         if (desc.WritableSet && !desc.Writable)
                         if (desc.WritableSet && !desc.Writable)
@@ -214,7 +216,7 @@ namespace Jint.Native.Argument
         {
         {
             EnsureInitialized();
             EnsureInitialized();
 
 
-            if (!Strict && ParameterMap != null)
+            if (!Strict && !ReferenceEquals(ParameterMap, null))
             {
             {
                 var map = ParameterMap;
                 var map = ParameterMap;
                 var isMapped = map.GetOwnProperty(propertyName);
                 var isMapped = map.GetOwnProperty(propertyName);

+ 6 - 5
Jint/Native/Array/ArrayInstance.cs

@@ -87,14 +87,15 @@ namespace Jint.Native.Array
 
 
             if (propertyName.Length == 6 && propertyName == "length")
             if (propertyName.Length == 6 && propertyName == "length")
             {
             {
-                if (desc.Value == null)
+                var value = desc.Value;
+                if (ReferenceEquals(value, null))
                 {
                 {
                     return base.DefineOwnProperty("length", desc, throwOnError);
                     return base.DefineOwnProperty("length", desc, throwOnError);
                 }
                 }
 
 
                 var newLenDesc = new PropertyDescriptor(desc);
                 var newLenDesc = new PropertyDescriptor(desc);
-                uint newLen = TypeConverter.ToUint32(desc.Value);
-                if (newLen != TypeConverter.ToNumber(desc.Value))
+                uint newLen = TypeConverter.ToUint32(value);
+                if (newLen != TypeConverter.ToNumber(value))
                 {
                 {
                     throw new JavaScriptException(_engine.RangeError);
                     throw new JavaScriptException(_engine.RangeError);
                 }
                 }
@@ -232,7 +233,7 @@ namespace Jint.Native.Array
 
 
                 if (!newWritable)
                 if (!newWritable)
                 {
                 {
-                    DefineOwnProperty("length", new PropertyDescriptor(value: null, writable: false, enumerable: null, configurable: null), false);
+                    DefineOwnProperty("length", new PropertyDescriptor(value: null, PropertyFlag.WritableSet), false);
                 }
                 }
 
 
                 return true;
                 return true;
@@ -490,7 +491,7 @@ namespace Jint.Native.Array
             if (!TryGetDescriptor(index, out var desc)
             if (!TryGetDescriptor(index, out var desc)
                 || desc == null
                 || desc == null
                 || desc == PropertyDescriptor.Undefined
                 || desc == PropertyDescriptor.Undefined
-                || (desc.Value == null && desc.Get == null))
+                || (ReferenceEquals(desc.Value, null) && ReferenceEquals(desc.Get, null)))
             {
             {
                 desc = GetProperty(TypeConverter.ToString(index));
                 desc = GetProperty(TypeConverter.ToString(index));
             }
             }

+ 7 - 7
Jint/Native/Array/ArrayPrototype.cs

@@ -506,7 +506,7 @@ namespace Jint.Native.Array
 
 
             var compareArg = arguments.At(0);
             var compareArg = arguments.At(0);
             ICallable compareFn = null;
             ICallable compareFn = null;
-            if (compareArg != Undefined)
+            if (!ReferenceEquals(compareArg, Undefined))
             {
             {
                 compareFn = compareArg.TryCast<ICallable>(x => throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function"));
                 compareFn = compareArg.TryCast<ICallable>(x => throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function"));
             }
             }
@@ -797,7 +797,7 @@ namespace Jint.Native.Array
             foreach (var e in items)
             foreach (var e in items)
             {
             {
                 var eArray = e.TryCast<ArrayInstance>();
                 var eArray = e.TryCast<ArrayInstance>();
-                if (eArray != null)
+                if (!ReferenceEquals(eArray, null))
                 {
                 {
                     var len = eArray.GetLength();
                     var len = eArray.GetLength();
                     for (uint k = 0; k < len; k++)
                     for (uint k = 0; k < len; k++)
@@ -901,7 +901,7 @@ namespace Jint.Native.Array
             for (var i = 0; i < arguments.Length; i++)
             for (var i = 0; i < arguments.Length; i++)
             {
             {
                 JsValue e = arguments[i];
                 JsValue e = arguments[i];
-                if (arrayInstance != null && n >= 0 && n < uint.MaxValue)
+                if (!ReferenceEquals(arrayInstance, null) && n >= 0 && n < uint.MaxValue)
                 {
                 {
                     // try to optimize a bit
                     // try to optimize a bit
                     arrayInstance.SetIndexValue((uint) n, e, true);
                     arrayInstance.SetIndexValue((uint) n, e, true);
@@ -1004,13 +1004,13 @@ namespace Jint.Native.Array
                 public override uint GetLength()
                 public override uint GetLength()
                 {
                 {
                     var desc = _instance.GetProperty("length");
                     var desc = _instance.GetProperty("length");
-                    if (desc.IsDataDescriptor() && desc.Value != null)
+                    var descValue = desc.Value;
+                    if (desc.IsDataDescriptor() && !ReferenceEquals(descValue, null))
                     {
                     {
-                        return TypeConverter.ToUint32(desc.Value);
+                        return TypeConverter.ToUint32(descValue);
                     }
                     }
 
 
-                    var getter = desc.Get != null ? desc.Get : Undefined;
-
+                    var getter = desc.Get ?? Undefined;
                     if (getter.IsUndefined())
                     if (getter.IsUndefined())
                     {
                     {
                         return 0;
                         return 0;

+ 4 - 16
Jint/Native/Boolean/BooleanInstance.cs

@@ -10,24 +10,12 @@ namespace Jint.Native.Boolean
         {
         {
         }
         }
 
 
-        public override string Class
-        {
-            get
-            {
-                return "Boolean";
-            }
-        }
+        public override string Class => "Boolean";
 
 
-        Types IPrimitiveInstance.Type
-        {
-            get { return Types.Boolean; }
-        }
+        Types IPrimitiveInstance.Type => Types.Boolean;
 
 
-        JsValue IPrimitiveInstance.PrimitiveValue
-        {
-            get { return PrimitiveValue; }
-        }
+        JsValue IPrimitiveInstance.PrimitiveValue => PrimitiveValue;
 
 
         public JsValue PrimitiveValue { get; set; }
         public JsValue PrimitiveValue { get; set; }
     }
     }
-}
+}

+ 6 - 10
Jint/Native/Boolean/BooleanPrototype.cs

@@ -38,18 +38,14 @@ namespace Jint.Native.Boolean
             {
             {
                 return B;
                 return B;
             }
             }
-            else
+
+            var o = B.TryCast<BooleanInstance>();
+            if (!ReferenceEquals(o, null))
             {
             {
-                var o = B.TryCast<BooleanInstance>();
-                if (o != null)
-                {
-                    return o.PrimitiveValue;
-                }
-                else
-                {
-                    throw new JavaScriptException(Engine.TypeError);
-                }
+                return o.PrimitiveValue;
             }
             }
+
+            throw new JavaScriptException(Engine.TypeError);
         }
         }
 
 
         private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)

+ 1 - 1
Jint/Native/Error/ErrorConstructor.cs

@@ -47,7 +47,7 @@ namespace Jint.Native.Error
             instance.Prototype = PrototypeObject;
             instance.Prototype = PrototypeObject;
             instance.Extensible = true;
             instance.Extensible = true;
 
 
-            if (arguments.At(0) != Undefined)
+            if (!ReferenceEquals(arguments.At(0), Undefined))
             {
             {
                 instance.Put("message", TypeConverter.ToString(arguments.At(0)), false);
                 instance.Put("message", TypeConverter.ToString(arguments.At(0)), false);
             }
             }

+ 1 - 1
Jint/Native/Error/ErrorPrototype.cs

@@ -42,7 +42,7 @@ namespace Jint.Native.Error
         public JsValue ToString(JsValue thisObject, JsValue[] arguments)
         public JsValue ToString(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = thisObject.TryCast<ObjectInstance>();
             var o = thisObject.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 3 - 4
Jint/Native/Function/FunctionConstructor.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Linq;
 using Esprima;
 using Esprima;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native.Object;
 using Jint.Native.Object;
@@ -74,7 +73,7 @@ namespace Jint.Native.Function
             {
             {
                 var functionExpression = "function f(" + p + ") { " + body + "}";
                 var functionExpression = "function f(" + p + ") { " + body + "}";
                 var parser = new JavaScriptParser(functionExpression, ParserOptions);
                 var parser = new JavaScriptParser(functionExpression, ParserOptions);
-                function = parser.ParseProgram().Body.First().As<IFunction>();
+                function = (IFunction) parser.ParseProgram().Body[0];
             }
             }
             catch (ParserException)
             catch (ParserException)
             {
             {
@@ -116,7 +115,7 @@ namespace Jint.Native.Function
         {
         {
             get
             get
             {
             {
-                if (_throwTypeError != null)
+                if (!ReferenceEquals(_throwTypeError, null))
                 {
                 {
                     return _throwTypeError;
                     return _throwTypeError;
                 }
                 }
@@ -148,7 +147,7 @@ namespace Jint.Native.Function
             }
             }
 
 
             var argArrayObj = argArray.TryCast<ObjectInstance>();
             var argArrayObj = argArray.TryCast<ObjectInstance>();
-            if (argArrayObj == null)
+            if (ReferenceEquals(argArrayObj, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 4 - 4
Jint/Native/Function/FunctionInstance.cs

@@ -42,7 +42,7 @@ namespace Jint.Native.Function
         public virtual bool HasInstance(JsValue v)
         public virtual bool HasInstance(JsValue v)
         {
         {
             var vObj = v.TryCast<ObjectInstance>();
             var vObj = v.TryCast<ObjectInstance>();
-            if (vObj == null)
+            if (ReferenceEquals(vObj, null))
             {
             {
                 return false;
                 return false;
             }
             }
@@ -50,12 +50,12 @@ namespace Jint.Native.Function
             var po = Get("prototype");
             var po = Get("prototype");
             if (!po.IsObject())
             if (!po.IsObject())
             {
             {
-                throw new JavaScriptException(_engine.TypeError, string.Format("Function has non-object prototype '{0}' in instanceof check", TypeConverter.ToString(po)));
+                throw new JavaScriptException(_engine.TypeError, $"Function has non-object prototype '{TypeConverter.ToString(po)}' in instanceof check");
             }
             }
 
 
             var o = po.AsObject();
             var o = po.AsObject();
 
 
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(_engine.TypeError);
                 throw new JavaScriptException(_engine.TypeError);
             }
             }
@@ -64,7 +64,7 @@ namespace Jint.Native.Function
             {
             {
                 vObj = vObj.Prototype;
                 vObj = vObj.Prototype;
 
 
-                if (vObj == null)
+                if (ReferenceEquals(vObj, null))
                 {
                 {
                     return false;
                     return false;
                 }
                 }

+ 6 - 6
Jint/Native/Function/FunctionPrototype.cs

@@ -52,7 +52,7 @@ namespace Jint.Native.Function
             f.Prototype = Engine.Function.PrototypeObject;
             f.Prototype = Engine.Function.PrototypeObject;
 
 
             var o = target as FunctionInstance;
             var o = target as FunctionInstance;
-            if (o != null)
+            if (!ReferenceEquals(o, null))
             {
             {
                 var l = TypeConverter.ToNumber(o.Get("length")) - (arguments.Length - 1);
                 var l = TypeConverter.ToNumber(o.Get("length")) - (arguments.Length - 1);
                 f.SetOwnProperty("length", new PropertyDescriptor(System.Math.Max(l, 0), PropertyFlag.AllForbidden));
                 f.SetOwnProperty("length", new PropertyDescriptor(System.Math.Max(l, 0), PropertyFlag.AllForbidden));
@@ -64,9 +64,9 @@ namespace Jint.Native.Function
 
 
 
 
             var thrower = Engine.Function.ThrowTypeError;
             var thrower = Engine.Function.ThrowTypeError;
-            f.DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, false, false), false);
-            f.DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, false, false), false);
-
+            const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
+            f.DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
+            f.DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
 
 
             return f;
             return f;
         }
         }
@@ -75,7 +75,7 @@ namespace Jint.Native.Function
         {
         {
             var func = thisObj.TryCast<FunctionInstance>();
             var func = thisObj.TryCast<FunctionInstance>();
 
 
-            if (func == null)
+            if (ReferenceEquals(func, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError, "Function object expected.");
                 throw new JavaScriptException(Engine.TypeError, "Function object expected.");
             }
             }
@@ -100,7 +100,7 @@ namespace Jint.Native.Function
             }
             }
 
 
             var argArrayObj = argArray.TryCast<ObjectInstance>();
             var argArrayObj = argArray.TryCast<ObjectInstance>();
-            if (argArrayObj == null)
+            if (ReferenceEquals(argArrayObj, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 4 - 3
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -55,8 +55,9 @@ namespace Jint.Native.Function
             if (strict)
             if (strict)
             {
             {
                 var thrower = engine.Function.ThrowTypeError;
                 var thrower = engine.Function.ThrowTypeError;
-                DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, false, false), false);
-                DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, false, false), false);
+                const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
+                DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
+                DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
             }
             }
         }
         }
 
 
@@ -226,7 +227,7 @@ namespace Jint.Native.Function
             };
             };
 
 
             var result = Call(obj, arguments).TryCast<ObjectInstance>();
             var result = Call(obj, arguments).TryCast<ObjectInstance>();
-            if (result != null)
+            if (!ReferenceEquals(result, null))
             {
             {
                 return result;
                 return result;
             }
             }

+ 7 - 6
Jint/Native/JsBoolean.cs

@@ -6,18 +6,19 @@ namespace Jint.Native
 {
 {
     public sealed class JsBoolean : JsValue, IEquatable<JsBoolean>
     public sealed class JsBoolean : JsValue, IEquatable<JsBoolean>
     {
     {
-        private readonly bool _value;
-
         public static readonly JsValue False = new JsBoolean(false);
         public static readonly JsValue False = new JsBoolean(false);
         public static readonly JsValue True = new JsBoolean(true);
         public static readonly JsValue True = new JsBoolean(true);
 
 
-        public JsBoolean(bool value)
+        internal static readonly object BoxedTrue = true;
+        internal static readonly object BoxedFalse = false;
+
+        internal readonly bool _value;
+
+        public JsBoolean(bool value) : base(Types.Boolean)
         {
         {
             _value = value;
             _value = value;
         }
         }
 
 
-        public override Types Type => Types.Boolean;
-
         [Pure]
         [Pure]
         public override bool AsBoolean()
         public override bool AsBoolean()
         {
         {
@@ -26,7 +27,7 @@ namespace Jint.Native
 
 
         public override object ToObject()
         public override object ToObject()
         {
         {
-            return _value;
+            return _value ? BoxedTrue : BoxedFalse;
         }
         }
 
 
         public override string ToString()
         public override string ToString()

+ 1 - 3
Jint/Native/JsNull.cs

@@ -5,12 +5,10 @@ namespace Jint.Native
 {
 {
     public sealed class JsNull : JsValue, IEquatable<JsNull>
     public sealed class JsNull : JsValue, IEquatable<JsNull>
     {
     {
-        internal JsNull()
+        internal JsNull() : base(Types.Null)
         {
         {
         }
         }
 
 
-        public override Types Type => Types.Null;
-
         public override object ToObject()
         public override object ToObject()
         {
         {
             return null;
             return null;

+ 3 - 5
Jint/Native/JsNumber.cs

@@ -34,23 +34,21 @@ namespace Jint.Native
             }
             }
         }
         }
 
 
-        public JsNumber(double value)
+        public JsNumber(double value) : base(Types.Number)
         {
         {
             _value = value;
             _value = value;
         }
         }
 
 
-        public JsNumber(int value)
+        public JsNumber(int value) : base(Types.Number)
         {
         {
             _value = value;
             _value = value;
         }
         }
 
 
-        public JsNumber(uint value)
+        public JsNumber(uint value) : base(Types.Number)
         {
         {
             _value = value;
             _value = value;
         }
         }
 
 
-        public override Types Type => Types.Number;
-
         [Pure]
         [Pure]
         public override double AsNumber()
         public override double AsNumber()
         {
         {

+ 2 - 4
Jint/Native/JsString.cs

@@ -28,7 +28,7 @@ namespace Jint.Native
             }
             }
         }
         }
 
 
-        public JsString(string value)
+        public JsString(string value) : base(Types.String)
         {
         {
             _value = value;
             _value = value;
         }
         }
@@ -38,13 +38,11 @@ namespace Jint.Native
             return _value;
             return _value;
         }
         }
 
 
-        public JsString(char value)
+        public JsString(char value) : base(Types.String)
         {
         {
             _value = value.ToString();
             _value = value.ToString();
         }
         }
 
 
-        public override Types Type => Types.String;
-
         [Pure]
         [Pure]
         public override string AsString()
         public override string AsString()
         {
         {

+ 1 - 3
Jint/Native/JsSymbol.cs

@@ -10,13 +10,11 @@ namespace Jint.Native
     {
     {
         private readonly string _value;
         private readonly string _value;
 
 
-        public JsSymbol(string value)
+        public JsSymbol(string value) : base(Types.Symbol)
         {
         {
             _value = value;
             _value = value;
         }
         }
 
 
-        public override Types Type => Types.Symbol;
-
         public override object ToObject()
         public override object ToObject()
         {
         {
             return _value;
             return _value;

+ 1 - 3
Jint/Native/JsUndefined.cs

@@ -5,12 +5,10 @@ namespace Jint.Native
 {
 {
     public sealed class JsUndefined : JsValue, IEquatable<JsUndefined>
     public sealed class JsUndefined : JsValue, IEquatable<JsUndefined>
     {
     {
-        internal JsUndefined()
+        internal JsUndefined() : base(Types.Undefined)
         {
         {
         }
         }
 
 
-        public override Types Type => Types.Undefined;
-
         public override object ToObject()
         public override object ToObject()
         {
         {
             return null;
             return null;

+ 99 - 37
Jint/Native/JsValue.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Diagnostics.Contracts;
 using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading;
 using Jint.Native.Array;
 using Jint.Native.Array;
 using Jint.Native.Date;
 using Jint.Native.Date;
@@ -18,115 +19,158 @@ namespace Jint.Native
     {
     {
         public static readonly JsValue Undefined = new JsUndefined();
         public static readonly JsValue Undefined = new JsUndefined();
         public static readonly JsValue Null = new JsNull();
         public static readonly JsValue Null = new JsNull();
+        private readonly Types _type;
+
+        protected JsValue(Types type)
+        {
+            _type = type;
+        }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsPrimitive()
         public bool IsPrimitive()
         {
         {
-            return Type != Types.Object && Type != Types.None;
+            return _type != Types.Object && Type != Types.None;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsUndefined()
         public bool IsUndefined()
         {
         {
-            return Type == Types.Undefined;
+            return _type == Types.Undefined;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual bool IsArray()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool IsArray()
         {
         {
-            return false;
+            return this is ArrayInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual bool IsDate()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool IsDate()
         {
         {
-            return false;
+            return this is DateInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual bool IsRegExp()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool IsRegExp()
         {
         {
-            return false;
+            return this is RegExpInstance;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsObject()
         public bool IsObject()
         {
         {
-            return Type == Types.Object;
+            return _type == Types.Object;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsString()
         public bool IsString()
         {
         {
-            return Type == Types.String;
+            return _type == Types.String;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsNumber()
         public bool IsNumber()
         {
         {
-            return Type == Types.Number;
+            return _type == Types.Number;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsBoolean()
         public bool IsBoolean()
         {
         {
-            return Type == Types.Boolean;
+            return _type == Types.Boolean;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsNull()
         public bool IsNull()
         {
         {
-            return Type == Types.Null;
+            return _type == Types.Null;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsCompletion()
         public bool IsCompletion()
         {
         {
-            return Type == Types.Completion;
+            return _type == Types.Completion;
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsSymbol()
         public bool IsSymbol()
         {
         {
-            return Type == Types.Symbol;
+            return _type == Types.Symbol;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual ObjectInstance AsObject()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ObjectInstance AsObject()
         {
         {
-            throw new ArgumentException("The value is not an object");
+            if (!IsObject())
+            {
+                ThrowArgumentException("The value is not an object");
+            }
+            return this as ObjectInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual TInstance AsInstance<TInstance>() where TInstance : class
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public TInstance AsInstance<TInstance>() where TInstance : class
         {
         {
-            throw new ArgumentException("The value is not an object");
+            if (!IsObject())
+            {
+                ThrowArgumentException("The value is not an object");
+            }
+            return this as TInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual ArrayInstance AsArray()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public ArrayInstance AsArray()
         {
         {
-            throw new ArgumentException("The value is not an array");
+            if (!IsArray())
+            {
+                ThrowArgumentException("The value is not an array");
+            }
+            return this as ArrayInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual DateInstance AsDate()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public DateInstance AsDate()
         {
         {
-            throw new ArgumentException("The value is not a date");
+            if (!IsDate())
+            {
+                ThrowArgumentException("The value is not a date");
+            }
+            return this as DateInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual RegExpInstance AsRegExp()
+        public RegExpInstance AsRegExp()
         {
         {
-            throw new ArgumentException("The value is not a date");
+            if (!IsRegExp())
+            {
+                ThrowArgumentException("The value is not a regex");
+            }
+
+            return this as RegExpInstance;
         }
         }
 
 
         [Pure]
         [Pure]
-        public virtual Completion AsCompletion()
+        public Completion AsCompletion()
         {
         {
-            if (Type != Types.Completion)
+            if (_type != Types.Completion)
             {
             {
-                throw new ArgumentException("The value is not a completion record");
+                ThrowArgumentException("The value is not a completion record");
             }
             }
 
 
             // TODO not implemented
             // TODO not implemented
@@ -134,15 +178,15 @@ namespace Jint.Native
         }
         }
 
 
         [Pure]
         [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public T TryCast<T>(Action<JsValue> fail = null) where T : class
         public T TryCast<T>(Action<JsValue> fail = null) where T : class
         {
         {
             if (IsObject())
             if (IsObject())
             {
             {
-                var o = AsObject();
-                var t = o as T;
-                if (t != null)
+                var o = this as T;
+                if (o != null)
                 {
                 {
-                    return t;
+                    return o;
                 }
                 }
             }
             }
 
 
@@ -151,13 +195,21 @@ namespace Jint.Native
             return null;
             return null;
         }
         }
 
 
-        public virtual bool Is<T>()
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Is<T>()
         {
         {
-            return false;
+            return IsObject() && this is T;
         }
         }
 
 
-        public virtual T As<T>() where T : ObjectInstance
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T As<T>() where T : ObjectInstance
         {
         {
+            if (IsObject())
+            {
+                return this as T;
+            }
             return null;
             return null;
         }
         }
 
 
@@ -185,7 +237,12 @@ namespace Jint.Native
             throw new ArgumentException("The value is not a number");
             throw new ArgumentException("The value is not a number");
         }
         }
 
 
-        public abstract Types Type { get; }
+        // ReSharper disable once ConvertToAutoPropertyWhenPossible // PERF
+        public Types Type
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return _type; }
+        }
 
 
         /// <summary>
         /// <summary>
         /// Creates a valid <see cref="JsValue"/> instance from any <see cref="Object"/> instance
         /// Creates a valid <see cref="JsValue"/> instance from any <see cref="Object"/> instance
@@ -329,6 +386,11 @@ namespace Jint.Native
             return false;
             return false;
         }
         }
 
 
+        private static void ThrowArgumentException(string message)
+        {
+            throw new ArgumentException(message);
+        }
+
         public override string ToString()
         public override string ToString()
         {
         {
             return "None";
             return "None";
@@ -428,7 +490,7 @@ namespace Jint.Native
 
 
         public override int GetHashCode()
         public override int GetHashCode()
         {
         {
-            return Type.GetHashCode();
+            return _type.GetHashCode();
         }
         }
 
 
         internal class JsValueDebugView
         internal class JsValueDebugView

+ 3 - 9
Jint/Native/Json/JsonInstance.cs

@@ -64,9 +64,7 @@ namespace Jint.Native.Json
                                 new PropertyDescriptor
                                 new PropertyDescriptor
                                 (
                                 (
                                     value: newValue,
                                     value: newValue,
-                                    writable: true,
-                                    enumerable: true,
-                                    configurable: true
+                                    PropertyFlag.ConfigurableEnumerableWritable
                                 ),
                                 ),
                                 false
                                 false
                             );
                             );
@@ -91,9 +89,7 @@ namespace Jint.Native.Json
                                 new PropertyDescriptor
                                 new PropertyDescriptor
                                 (
                                 (
                                     value: newElement,
                                     value: newElement,
-                                    writable: true,
-                                    enumerable: true,
-                                    configurable: true
+                                    PropertyFlag.ConfigurableEnumerableWritable
                                 ),
                                 ),
                                 false
                                 false
                             );
                             );
@@ -116,9 +112,7 @@ namespace Jint.Native.Json
                     "",
                     "",
                     new PropertyDescriptor(
                     new PropertyDescriptor(
                         value: res,
                         value: res,
-                        writable: true,
-                        enumerable: true,
-                        configurable: true
+                        PropertyFlag.ConfigurableEnumerableWritable
                     ),
                     ),
                     false
                     false
                 );
                 );

+ 3 - 3
Jint/Native/Json/JsonSerializer.cs

@@ -135,7 +135,7 @@ namespace Jint.Native.Json
                 }
                 }
             }
             }
 
 
-            if (_replacerFunction != Undefined.Instance)
+            if (!ReferenceEquals(_replacerFunction, Undefined.Instance))
             {
             {
                 var replacerFunctionCallable = (ICallable)_replacerFunction.AsObject();
                 var replacerFunctionCallable = (ICallable)_replacerFunction.AsObject();
                 value = replacerFunctionCallable.Call(holder, Arguments.From(key, value));
                 value = replacerFunctionCallable.Call(holder, Arguments.From(key, value));
@@ -266,7 +266,7 @@ namespace Jint.Native.Json
             for (int i = 0; i < len; i++)
             for (int i = 0; i < len; i++)
             {
             {
                 var strP = Str(TypeConverter.ToString(i), value);
                 var strP = Str(TypeConverter.ToString(i), value);
-                if (strP == JsValue.Undefined)
+                if (ReferenceEquals(strP, JsValue.Undefined))
                     strP = "null";
                     strP = "null";
                 partial.Add(strP.AsString());
                 partial.Add(strP.AsString());
             }
             }
@@ -325,7 +325,7 @@ namespace Jint.Native.Json
             foreach (var p in k)
             foreach (var p in k)
             {
             {
                 var strP = Str(p, value);
                 var strP = Str(p, value);
-                if (strP != JsValue.Undefined)
+                if (!ReferenceEquals(strP, JsValue.Undefined))
                 {
                 {
                     var member = Quote(p) + ":";
                     var member = Quote(p) + ":";
                     if (_gap != "")
                     if (_gap != "")

+ 7 - 17
Jint/Native/Number/NumberInstance.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Runtime.CompilerServices;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime;
 
 
@@ -13,35 +14,24 @@ namespace Jint.Native.Number
         {
         {
         }
         }
 
 
-        public override string Class
-        {
-            get
-            {
-                return "Number";
-            }
-        }
+        public override string Class => "Number";
 
 
-        Types IPrimitiveInstance.Type
-        {
-            get { return Types.Number; }
-        }
+        Types IPrimitiveInstance.Type => Types.Number;
 
 
-        JsValue IPrimitiveInstance.PrimitiveValue
-        {
-            get { return NumberData; }
-        }
+        JsValue IPrimitiveInstance.PrimitiveValue => NumberData;
 
 
         public JsValue NumberData { get; set; }
         public JsValue NumberData { get; set; }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool IsNegativeZero(double x)
         public static bool IsNegativeZero(double x)
         {
         {
             return x == 0 && BitConverter.DoubleToInt64Bits(x) == NegativeZeroBits;
             return x == 0 && BitConverter.DoubleToInt64Bits(x) == NegativeZeroBits;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool IsPositiveZero(double x)
         public static bool IsPositiveZero(double x)
         {
         {
             return x == 0 && BitConverter.DoubleToInt64Bits(x) != NegativeZeroBits;
             return x == 0 && BitConverter.DoubleToInt64Bits(x) != NegativeZeroBits;
         }
         }
-
     }
     }
-}
+}

+ 6 - 4
Jint/Native/Number/NumberPrototype.cs

@@ -43,7 +43,7 @@ namespace Jint.Native.Number
 
 
         private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
         private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!thisObject.IsNumber() && (thisObject.TryCast<NumberInstance>() == null))
+            if (!thisObject.IsNumber() && ReferenceEquals(thisObject.TryCast<NumberInstance>(), null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -81,7 +81,7 @@ namespace Jint.Native.Number
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
         {
             var number = thisObj.TryCast<NumberInstance>();
             var number = thisObj.TryCast<NumberInstance>();
-            if (number == null)
+            if (ReferenceEquals(number, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -167,12 +167,14 @@ namespace Jint.Native.Number
 
 
         private JsValue ToNumberString(JsValue thisObject, JsValue[] arguments)
         private JsValue ToNumberString(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!thisObject.IsNumber() && (thisObject.TryCast<NumberInstance>() == null))
+            if (!thisObject.IsNumber() && (ReferenceEquals(thisObject.TryCast<NumberInstance>(), null)))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
 
 
-            var radix = arguments.At(0) == JsValue.Undefined ? 10 : (int) TypeConverter.ToInteger(arguments.At(0));
+            var radix = ReferenceEquals(arguments.At(0), Undefined) 
+                ? 10 
+                : (int) TypeConverter.ToInteger(arguments.At(0));
 
 
             if (radix < 2 || radix > 36)
             if (radix < 2 || radix > 36)
             {
             {

+ 15 - 15
Jint/Native/Object/ObjectConstructor.cs

@@ -84,7 +84,7 @@ namespace Jint.Native.Object
             {
             {
                 var value = arguments[0];
                 var value = arguments[0];
                 var valueObj = value.TryCast<ObjectInstance>();
                 var valueObj = value.TryCast<ObjectInstance>();
-                if (valueObj != null)
+                if (!ReferenceEquals(valueObj, null))
                 {
                 {
                     return valueObj;
                     return valueObj;
                 }
                 }
@@ -108,7 +108,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -120,7 +120,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -136,7 +136,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -171,7 +171,7 @@ namespace Jint.Native.Object
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
 
 
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null && oArg != Null)
+            if (ReferenceEquals(o, null) && !ReferenceEquals(oArg, Null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -180,7 +180,7 @@ namespace Jint.Native.Object
             obj.Prototype = o;
             obj.Prototype = o;
 
 
             var properties = arguments.At(1);
             var properties = arguments.At(1);
-            if (properties != Undefined)
+            if (!ReferenceEquals(properties, Undefined))
             {
             {
                 DefineProperties(thisObject, new [] {obj, properties});
                 DefineProperties(thisObject, new [] {obj, properties});
             }
             }
@@ -192,7 +192,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -211,7 +211,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -242,7 +242,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -269,7 +269,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -305,7 +305,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -319,7 +319,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -344,7 +344,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -377,7 +377,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -389,7 +389,7 @@ namespace Jint.Native.Object
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
             var o = oArg.TryCast<ObjectInstance>();
             var o = oArg.TryCast<ObjectInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 45 - 111
Jint/Native/Object/ObjectInstance.cs

@@ -1,6 +1,5 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Diagnostics.Contracts;
 using System.Dynamic;
 using System.Dynamic;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using Jint.Native.Array;
 using Jint.Native.Array;
@@ -22,7 +21,7 @@ namespace Jint.Native.Object
         private Dictionary<string, PropertyDescriptor> _intrinsicProperties;
         private Dictionary<string, PropertyDescriptor> _intrinsicProperties;
         private MruPropertyCache2<PropertyDescriptor> _properties;
         private MruPropertyCache2<PropertyDescriptor> _properties;
 
 
-        public ObjectInstance(Engine engine)
+        public ObjectInstance(Engine engine) : base(Types.Object)
         {
         {
             Engine = engine;
             Engine = engine;
         }
         }
@@ -37,7 +36,7 @@ namespace Jint.Native.Object
                 return true;
                 return true;
             }
             }
 
 
-            if (Prototype == null)
+            if (ReferenceEquals(Prototype, null))
             {
             {
                 value = Undefined;
                 value = Undefined;
                 return false;
                 return false;
@@ -210,7 +209,7 @@ namespace Jint.Native.Object
                 return prop;
                 return prop;
             }
             }
 
 
-            if (Prototype == null)
+            if (ReferenceEquals(Prototype, null))
             {
             {
                 return PropertyDescriptor.Undefined;
                 return PropertyDescriptor.Undefined;
             }
             }
@@ -229,14 +228,14 @@ namespace Jint.Native.Object
                     return false;
                     return false;
                 }
                 }
 
 
-                if (desc.IsDataDescriptor() && desc.Value != null)
+                var descValue = desc.Value;
+                if (desc.WritableSet && !ReferenceEquals(descValue, null))
                 {
                 {
-                    value = desc.Value;
+                    value = descValue;
                     return true;
                     return true;
                 }
                 }
 
 
-                var getter = desc.Get != null ? desc.Get : Undefined;
-
+                var getter = desc.Get ??  Undefined;
                 if (getter.IsUndefined())
                 if (getter.IsUndefined())
                 {
                 {
                     value = Undefined;
                     value = Undefined;
@@ -249,7 +248,7 @@ namespace Jint.Native.Object
                 return true;
                 return true;
             }
             }
 
 
-            if (Prototype == null)
+            if (ReferenceEquals(Prototype, null))
             {
             {
                 return false;
                 return false;
             }
             }
@@ -321,7 +320,8 @@ namespace Jint.Native.Object
             {
             {
                 if (desc.IsAccessorDescriptor())
                 if (desc.IsAccessorDescriptor())
                 {
                 {
-                    if (desc.Set == null || desc.Set.IsUndefined())
+                    var set = desc.Set;
+                    if (ReferenceEquals(set, null) || set.IsUndefined())
                     {
                     {
                         return false;
                         return false;
                     }
                     }
@@ -332,7 +332,7 @@ namespace Jint.Native.Object
                 return desc.Writable;
                 return desc.Writable;
             }
             }
 
 
-            if (Prototype == null)
+            if (ReferenceEquals(Prototype, null))
             {
             {
                 return Extensible;
                 return Extensible;
             }
             }
@@ -346,7 +346,8 @@ namespace Jint.Native.Object
 
 
             if (inherited.IsAccessorDescriptor())
             if (inherited.IsAccessorDescriptor())
             {
             {
-                if (inherited.Set == null || inherited.Set.IsUndefined())
+                var set = inherited.Set;
+                if (ReferenceEquals(set, null) || set.IsUndefined())
                 {
                 {
                     return false;
                     return false;
                 }
                 }
@@ -489,6 +490,7 @@ namespace Jint.Native.Object
                 return true;
                 return true;
             }
             }
 
 
+            var descValue = desc.Value;
             if (current == PropertyDescriptor.Undefined)
             if (current == PropertyDescriptor.Undefined)
             {
             {
                 if (!Extensible)
                 if (!Extensible)
@@ -507,17 +509,17 @@ namespace Jint.Native.Object
                         PropertyDescriptor propertyDescriptor;
                         PropertyDescriptor propertyDescriptor;
                         if (desc.Configurable && desc.Enumerable && desc.Writable)
                         if (desc.Configurable && desc.Enumerable && desc.Writable)
                         {
                         {
-                            propertyDescriptor = new PropertyDescriptor(desc.Value != null ? desc.Value : Undefined, PropertyFlag.ConfigurableEnumerableWritable);
+                            propertyDescriptor = new PropertyDescriptor(descValue ?? Undefined, PropertyFlag.ConfigurableEnumerableWritable);
                         }
                         }
                         else if (!desc.Configurable && !desc.Enumerable && !desc.Writable)
                         else if (!desc.Configurable && !desc.Enumerable && !desc.Writable)
                         {
                         {
-                            propertyDescriptor = new PropertyDescriptor(desc.Value != null ? desc.Value : Undefined, PropertyFlag.AllForbidden);
+                            propertyDescriptor = new PropertyDescriptor(descValue ?? Undefined, PropertyFlag.AllForbidden);
                         }
                         }
                         else
                         else
                         {
                         {
                             propertyDescriptor = new PropertyDescriptor(desc)
                             propertyDescriptor = new PropertyDescriptor(desc)
                             {
                             {
-                                Value = desc.Value != null ? desc.Value : Undefined
+                                Value = descValue ?? Undefined
                             };
                             };
                         }
                         }
 
 
@@ -533,24 +535,30 @@ namespace Jint.Native.Object
             }
             }
 
 
             // Step 5
             // Step 5
+            var currentGet = current.Get;
+            var currentSet = current.Set;
+            var currentValue = current.Value;
+            
             if (!current.ConfigurableSet &&
             if (!current.ConfigurableSet &&
                 !current.EnumerableSet &&
                 !current.EnumerableSet &&
                 !current.WritableSet &&
                 !current.WritableSet &&
-                current.Get == null &&
-                current.Set == null &&
-                current.Value == null)
+                ReferenceEquals(currentGet, null) &&
+                ReferenceEquals(currentSet, null) &&
+                ReferenceEquals(currentValue, null))
             {
             {
                 return true;
                 return true;
             }
             }
 
 
             // Step 6
             // Step 6
+            var descGet = desc.Get;
+            var descSet = desc.Set;
             if (
             if (
                 current.Configurable == desc.Configurable && current.ConfigurableSet == desc.ConfigurableSet &&
                 current.Configurable == desc.Configurable && current.ConfigurableSet == desc.ConfigurableSet &&
                 current.Writable == desc.Writable && current.WritableSet == desc.WritableSet &&
                 current.Writable == desc.Writable && current.WritableSet == desc.WritableSet &&
                 current.Enumerable == desc.Enumerable && current.EnumerableSet == desc.EnumerableSet &&
                 current.Enumerable == desc.Enumerable && current.EnumerableSet == desc.EnumerableSet &&
-                ((current.Get == null && desc.Get == null) || (current.Get != null && desc.Get != null && ExpressionInterpreter.SameValue(current.Get, desc.Get))) &&
-                ((current.Set == null && desc.Set == null) || (current.Set != null && desc.Set != null && ExpressionInterpreter.SameValue(current.Set, desc.Set))) &&
-                ((current.Value == null && desc.Value == null) || (current.Value != null && desc.Value != null && ExpressionInterpreter.StrictlyEqual(current.Value, desc.Value)))
+                ((ReferenceEquals(currentGet, null) && ReferenceEquals(descGet, null)) || (!ReferenceEquals(currentGet, null) && !ReferenceEquals(descGet, null) && ExpressionInterpreter.SameValue(currentGet, descGet))) &&
+                ((ReferenceEquals(currentSet, null) && ReferenceEquals(descSet, null)) || (!ReferenceEquals(currentSet, null) && !ReferenceEquals(descSet, null) && ExpressionInterpreter.SameValue(currentSet, descSet))) &&
+                ((ReferenceEquals(currentValue, null) && ReferenceEquals(descValue, null)) || (!ReferenceEquals(currentValue, null) && !ReferenceEquals(descValue, null) && ExpressionInterpreter.StrictlyEqual(currentValue, descValue)))
             )
             )
             {
             {
                 return true;
                 return true;
@@ -595,20 +603,19 @@ namespace Jint.Native.Object
 
 
                     if (current.IsDataDescriptor())
                     if (current.IsDataDescriptor())
                     {
                     {
+                        var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet);
                         SetOwnProperty(propertyName, current = new GetSetPropertyDescriptor(
                         SetOwnProperty(propertyName, current = new GetSetPropertyDescriptor(
                             get: JsValue.Undefined,
                             get: JsValue.Undefined,
                             set: JsValue.Undefined,
                             set: JsValue.Undefined,
-                            enumerable: current.Enumerable,
-                            configurable: current.Configurable
+                            flags
                         ));
                         ));
                     }
                     }
                     else
                     else
                     {
                     {
+                        var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet);
                         SetOwnProperty(propertyName, current = new PropertyDescriptor(
                         SetOwnProperty(propertyName, current = new PropertyDescriptor(
                             value: JsValue.Undefined,
                             value: JsValue.Undefined,
-                            writable: null,
-                            enumerable: current.Enumerable,
-                            configurable: current.Configurable
+                            flags
                         ));
                         ));
                     }
                     }
                 }
                 }
@@ -628,7 +635,7 @@ namespace Jint.Native.Object
 
 
                         if (!current.Writable)
                         if (!current.Writable)
                         {
                         {
-                            if (desc.Value != null && !ExpressionInterpreter.SameValue(desc.Value, current.Value))
+                            if (!ReferenceEquals(descValue, null) && !ExpressionInterpreter.SameValue(descValue, currentValue))
                             {
                             {
                                 if (throwOnError)
                                 if (throwOnError)
                                 {
                                 {
@@ -644,9 +651,9 @@ namespace Jint.Native.Object
                 {
                 {
                     if (!current.Configurable)
                     if (!current.Configurable)
                     {
                     {
-                        if ((desc.Set != null && !ExpressionInterpreter.SameValue(desc.Set, current.Set != null ? current.Set : Undefined))
+                        if ((!ReferenceEquals(descSet, null) && !ExpressionInterpreter.SameValue(descSet, currentSet ?? Undefined))
                             ||
                             ||
-                            (desc.Get != null && !ExpressionInterpreter.SameValue(desc.Get, current.Get != null ? current.Get : Undefined)))
+                            (!ReferenceEquals(descGet, null) && !ExpressionInterpreter.SameValue(descGet, currentGet ?? Undefined)))
                         {
                         {
                             if (throwOnError)
                             if (throwOnError)
                             {
                             {
@@ -659,9 +666,9 @@ namespace Jint.Native.Object
                 }
                 }
             }
             }
 
 
-            if (desc.Value != null)
+            if (!ReferenceEquals(descValue, null))
             {
             {
-                current.Value = desc.Value;
+                current.Value = descValue;
             }
             }
 
 
             if (desc.WritableSet)
             if (desc.WritableSet)
@@ -680,16 +687,16 @@ namespace Jint.Native.Object
             }
             }
 
 
             PropertyDescriptor mutable = null;
             PropertyDescriptor mutable = null;
-            if (desc.Get != null)
+            if (!ReferenceEquals(descGet, null))
             {
             {
                 mutable = new GetSetPropertyDescriptor(mutable ?? current);
                 mutable = new GetSetPropertyDescriptor(mutable ?? current);
-                ((GetSetPropertyDescriptor) mutable).SetGet(desc.Get);
+                ((GetSetPropertyDescriptor) mutable).SetGet(descGet);
             }
             }
 
 
-            if (desc.Set != null)
+            if (!ReferenceEquals(descSet, null))
             {
             {
                 mutable = new GetSetPropertyDescriptor(mutable ?? current);
                 mutable = new GetSetPropertyDescriptor(mutable ?? current);
-                ((GetSetPropertyDescriptor) mutable).SetSet(desc.Set);
+                ((GetSetPropertyDescriptor) mutable).SetSet(descSet);
             }
             }
 
 
             if (mutable != null)
             if (mutable != null)
@@ -733,81 +740,6 @@ namespace Jint.Native.Object
             return TypeConverter.ToString(this);
             return TypeConverter.ToString(this);
         }
         }
 
 
-        public override Types Type => Types.Object;
-
-        [Pure]
-        public override bool IsArray()
-        {
-            return this is ArrayInstance;
-        }
-
-        [Pure]
-        public override bool IsDate()
-        {
-            return this is DateInstance;
-        }
-
-        [Pure]
-        public override bool IsRegExp()
-        {
-            return this is RegExpInstance;
-        }
-
-        [Pure]
-        public override ObjectInstance AsObject()
-        {
-            return this;
-        }
-
-        [Pure]
-        public override TInstance AsInstance<TInstance>()
-        {
-            return this as TInstance;
-        }
-
-        [Pure]
-        public override ArrayInstance AsArray()
-        {
-            if (!IsArray())
-            {
-                throw new ArgumentException("The value is not an array");
-            }
-
-            return this as ArrayInstance;
-        }
-
-        [Pure]
-        public override DateInstance AsDate()
-        {
-            if (!IsDate())
-            {
-                throw new ArgumentException("The value is not a date");
-            }
-
-            return this as DateInstance;
-        }
-
-        [Pure]
-        public override RegExpInstance AsRegExp()
-        {
-            if (!IsRegExp())
-            {
-                throw new ArgumentException("The value is not a regex");
-            }
-
-            return this as RegExpInstance;
-        }
-
-        public override bool Is<T>()
-        {
-            return this is T;
-        }
-
-        public override T As<T>()
-        {
-            return this as T;
-        }
-
         public override object ToObject()
         public override object ToObject()
         {
         {
             if (this is IObjectWrapper wrapper)
             if (this is IObjectWrapper wrapper)
@@ -861,7 +793,9 @@ namespace Jint.Native.Object
                 case "Boolean":
                 case "Boolean":
                     if (this is BooleanInstance booleanInstance)
                     if (this is BooleanInstance booleanInstance)
                     {
                     {
-                        return booleanInstance.PrimitiveValue.AsBoolean();
+                        return booleanInstance.PrimitiveValue.AsBoolean()
+                             ? JsBoolean.BoxedTrue
+                             : JsBoolean.BoxedFalse;
                     }
                     }
 
 
                     break;
                     break;

+ 1 - 1
Jint/Native/Object/ObjectPrototype.cs

@@ -62,7 +62,7 @@ namespace Jint.Native.Object
             {
             {
                 v = v.Prototype;
                 v = v.Prototype;
 
 
-                if (v == null)
+                if (ReferenceEquals(v, null))
                 {
                 {
                     return false;
                     return false;
                 }
                 }

+ 12 - 13
Jint/Native/RegExp/RegExpConstructor.cs

@@ -66,28 +66,27 @@ namespace Jint.Native.RegExp
             var flags = arguments.At(1);
             var flags = arguments.At(1);
 
 
             var r = pattern.TryCast<RegExpInstance>();
             var r = pattern.TryCast<RegExpInstance>();
-            if (ReferenceEquals(flags, Undefined) && r != null)
+            if (ReferenceEquals(flags, Undefined) && !ReferenceEquals(r, null))
             {
             {
                 return r;
                 return r;
             }
             }
-            else if (flags != Undefined && r != null)
+
+            if (!ReferenceEquals(flags, Undefined) && !ReferenceEquals(r, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
+
+            if (ReferenceEquals(pattern, Undefined))
+            {
+                p = "";
+            }
             else
             else
             {
             {
-                if (ReferenceEquals(pattern, Undefined))
-                {
-                    p = "";
-                }
-                else
-                {
-                    p = TypeConverter.ToString(pattern);
-                }
-
-                f = !ReferenceEquals(flags, Undefined) ? TypeConverter.ToString(flags) : "";
+                p = TypeConverter.ToString(pattern);
             }
             }
 
 
+            f = !ReferenceEquals(flags, Undefined) ? TypeConverter.ToString(flags) : "";
+
             r = new RegExpInstance(Engine);
             r = new RegExpInstance(Engine);
             r.Prototype = PrototypeObject;
             r.Prototype = PrototypeObject;
             r.Extensible = true;
             r.Extensible = true;
@@ -105,7 +104,7 @@ namespace Jint.Native.RegExp
             string s;
             string s;
             s = p;
             s = p;
 
 
-            if (System.String.IsNullOrEmpty(s))
+            if (string.IsNullOrEmpty(s))
             {
             {
                 s = "(?:)";
                 s = "(?:)";
             }
             }

+ 3 - 3
Jint/Native/RegExp/RegExpPrototype.cs

@@ -56,13 +56,13 @@ namespace Jint.Native.RegExp
             }
             }
 
 
             var match = Exec(r, arguments);
             var match = Exec(r, arguments);
-            return match != Null;
+            return !ReferenceEquals(match, Null);
         }
         }
 
 
         internal JsValue Exec(JsValue thisObj, JsValue[] arguments)
         internal JsValue Exec(JsValue thisObj, JsValue[] arguments)
         {
         {
             var R = TypeConverter.ToObject(Engine, thisObj) as RegExpInstance;
             var R = TypeConverter.ToObject(Engine, thisObj) as RegExpInstance;
-            if (R == null)
+            if (ReferenceEquals(R, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -82,7 +82,7 @@ namespace Jint.Native.RegExp
             {
             {
                 // "aaa".match() => [ '', index: 0, input: 'aaa' ]
                 // "aaa".match() => [ '', index: 0, input: 'aaa' ]
                 var aa = InitReturnValueArray((ArrayInstance) Engine.Array.Construct(Arguments.Empty), s, 1, 0);
                 var aa = InitReturnValueArray((ArrayInstance) Engine.Array.Construct(Arguments.Empty), s, 1, 0);
-                aa.DefineOwnProperty("0", new PropertyDescriptor("", true, true, true), true);
+                aa.DefineOwnProperty("0", new PropertyDescriptor("", PropertyFlag.ConfigurableEnumerableWritable), true);
                 return aa;
                 return aa;
             }
             }
 
 

+ 15 - 11
Jint/Native/String/StringPrototype.cs

@@ -63,7 +63,7 @@ namespace Jint.Native.String
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         {
         {
             var s = TypeConverter.ToObject(Engine, thisObj) as StringInstance;
             var s = TypeConverter.ToObject(Engine, thisObj) as StringInstance;
-            if (s == null)
+            if (ReferenceEquals(s, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -77,7 +77,7 @@ namespace Jint.Native.String
         const char MONGOLIAN_VOWEL_SEPARATOR = '\u180E';
         const char MONGOLIAN_VOWEL_SEPARATOR = '\u180E';
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private static bool IsWhiteSpaceEx(char c)
+        internal static bool IsWhiteSpaceEx(char c)
         {
         {
             return
             return
                 char.IsWhiteSpace(c) ||
                 char.IsWhiteSpace(c) ||
@@ -86,6 +86,7 @@ namespace Jint.Native.String
                 c == MONGOLIAN_VOWEL_SEPARATOR;
                 c == MONGOLIAN_VOWEL_SEPARATOR;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static string TrimEndEx(string s)
         public static string TrimEndEx(string s)
         {
         {
             if (s.Length == 0)
             if (s.Length == 0)
@@ -108,6 +109,7 @@ namespace Jint.Native.String
                 return string.Empty;
                 return string.Empty;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static string TrimStartEx(string s)
         public static string TrimStartEx(string s)
         {
         {
             if (s.Length == 0)
             if (s.Length == 0)
@@ -130,11 +132,13 @@ namespace Jint.Native.String
                 return s.Substring(i);
                 return s.Substring(i);
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static string TrimEx(string s)
         public static string TrimEx(string s)
         {
         {
             return TrimEndEx(TrimStartEx(s));
             return TrimEndEx(TrimStartEx(s));
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private JsValue Trim(JsValue thisObj, JsValue[] arguments)
         private JsValue Trim(JsValue thisObj, JsValue[] arguments)
         {
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
@@ -225,7 +229,7 @@ namespace Jint.Native.String
         {
         {
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             var start = TypeConverter.ToInteger(arguments.At(0));
             var start = TypeConverter.ToInteger(arguments.At(0));
-            var length = arguments.At(1) == JsValue.Undefined
+            var length = ReferenceEquals(arguments.At(1), Undefined)
                 ? double.PositiveInfinity
                 ? double.PositiveInfinity
                 : TypeConverter.ToInteger(arguments.At(1));
                 : TypeConverter.ToInteger(arguments.At(1));
 
 
@@ -286,7 +290,7 @@ namespace Jint.Native.String
 
 
             const string regExpForMatchingAllCharactere = "(?:)";
             const string regExpForMatchingAllCharactere = "(?:)";
 
 
-            if (rx != null &&
+            if (!ReferenceEquals(rx, null) &&
                 rx.Source != regExpForMatchingAllCharactere // We need pattern to be defined -> for s.split(new RegExp)
                 rx.Source != regExpForMatchingAllCharactere // We need pattern to be defined -> for s.split(new RegExp)
                 )
                 )
             {
             {
@@ -350,7 +354,7 @@ namespace Jint.Native.String
                 segments.Clear();
                 segments.Clear();
                 var sep = TypeConverter.ToString(separator);
                 var sep = TypeConverter.ToString(separator);
 
 
-                if (sep == string.Empty || (rx != null && rx.Source == regExpForMatchingAllCharactere)) // for s.split(new RegExp)
+                if (sep == string.Empty || (!ReferenceEquals(rx, null) && rx.Source == regExpForMatchingAllCharactere)) // for s.split(new RegExp)
                 {
                 {
                     if (s.Length > segments.Capacity)
                     if (s.Length > segments.Capacity)
                     {
                     {
@@ -456,7 +460,7 @@ namespace Jint.Native.String
 
 
             // If the second parameter is not a function we create one
             // If the second parameter is not a function we create one
             var replaceFunction = replaceValue.TryCast<FunctionInstance>();
             var replaceFunction = replaceValue.TryCast<FunctionInstance>();
-            if (replaceFunction == null)
+            if (ReferenceEquals(replaceFunction, null))
             {
             {
                 replaceFunction = new ClrFunctionInstance(Engine, (self, args) =>
                 replaceFunction = new ClrFunctionInstance(Engine, (self, args) =>
                 {
                 {
@@ -548,7 +552,7 @@ namespace Jint.Native.String
             }
             }
 
 
             var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
             var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
-            if (rx != null)
+            if (!ReferenceEquals(rx, null))
             {
             {
                 // Replace the input string with replaceText, recording the last match found.
                 // Replace the input string with replaceText, recording the last match found.
                 string result = rx.Value.Replace(thisString, match =>
                 string result = rx.Value.Replace(thisString, match =>
@@ -630,7 +634,7 @@ namespace Jint.Native.String
                 while (lastMatch)
                 while (lastMatch)
                 {
                 {
                     var result = Engine.RegExp.PrototypeObject.Exec(rx, Arguments.From(s)).TryCast<ObjectInstance>();
                     var result = Engine.RegExp.PrototypeObject.Exec(rx, Arguments.From(s)).TryCast<ObjectInstance>();
-                    if (result == null)
+                    if (ReferenceEquals(result, null))
                     {
                     {
                         lastMatch = false;
                         lastMatch = false;
                     }
                     }
@@ -674,7 +678,7 @@ namespace Jint.Native.String
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             var searchStr = TypeConverter.ToString(arguments.At(0));
             var searchStr = TypeConverter.ToString(arguments.At(0));
             double numPos = double.NaN;
             double numPos = double.NaN;
-            if (arguments.Length > 1 && arguments[1] != Undefined)
+            if (arguments.Length > 1 && !ReferenceEquals(arguments[1], Undefined))
             {
             {
                 numPos = TypeConverter.ToNumber(arguments[1]);
                 numPos = TypeConverter.ToNumber(arguments[1]);
             }
             }
@@ -721,7 +725,7 @@ namespace Jint.Native.String
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             var searchStr = TypeConverter.ToString(arguments.At(0));
             var searchStr = TypeConverter.ToString(arguments.At(0));
             double pos = 0;
             double pos = 0;
-            if (arguments.Length > 1 && arguments[1] != Undefined)
+            if (arguments.Length > 1 && !ReferenceEquals(arguments[1], Undefined))
             {
             {
                 pos = TypeConverter.ToInteger(arguments[1]);
                 pos = TypeConverter.ToInteger(arguments[1]);
             }
             }
@@ -803,7 +807,7 @@ namespace Jint.Native.String
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
         {
             var s = thisObj.TryCast<StringInstance>();
             var s = thisObj.TryCast<StringInstance>();
-            if (s == null)
+            if (ReferenceEquals(s, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 3 - 15
Jint/Native/Symbol/SymbolInstance.cs

@@ -10,23 +10,11 @@ namespace Jint.Native.Symbol
         {
         {
         }
         }
 
 
-        public override string Class
-        {
-            get
-            {
-                return "Symbol";
-            }
-        }
+        public override string Class => "Symbol";
 
 
-        Types IPrimitiveInstance.Type
-        {
-            get { return Types.Symbol; }
-        }
+        Types IPrimitiveInstance.Type => Types.Symbol;
 
 
-        JsValue IPrimitiveInstance.PrimitiveValue
-        {
-            get { return SymbolData; }
-        }
+        JsValue IPrimitiveInstance.PrimitiveValue => SymbolData;
 
 
         public JsSymbol SymbolData { get; set; }
         public JsSymbol SymbolData { get; set; }
     }
     }

+ 2 - 2
Jint/Native/Symbol/SymbolPrototype.cs

@@ -54,7 +54,7 @@ namespace Jint.Native.Symbol
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         {
         {
             var sym = thisObject.TryCast<SymbolInstance>();
             var sym = thisObject.TryCast<SymbolInstance>();
-            if (sym == null)
+            if (ReferenceEquals(sym, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }
@@ -71,7 +71,7 @@ namespace Jint.Native.Symbol
 
 
             // Steps 3. and 4.
             // Steps 3. and 4.
             var o = thisObject.AsInstance<SymbolInstance>();
             var o = thisObject.AsInstance<SymbolInstance>();
-            if (o == null)
+            if (ReferenceEquals(o, null))
             {
             {
                 throw new JavaScriptException(Engine.TypeError);
                 throw new JavaScriptException(Engine.TypeError);
             }
             }

+ 16 - 3
Jint/Options.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.Linq;
 using System.Linq;
 using System.Reflection;
 using System.Reflection;
+using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Native;
 using Jint.Runtime.Interop;
 using Jint.Runtime.Interop;
 
 
@@ -155,11 +156,19 @@ namespace Jint
 
 
         internal bool _IsGlobalDiscarded => _discardGlobal;
         internal bool _IsGlobalDiscarded => _discardGlobal;
 
 
-        internal bool _IsStrict => _strict;
+        internal bool _IsStrict
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return _strict; }
+        }
 
 
         internal bool _IsDebuggerStatementAllowed => _allowDebuggerStatement;
         internal bool _IsDebuggerStatementAllowed => _allowDebuggerStatement;
 
 
-        internal bool _IsDebugMode => _debugMode;
+        internal bool _IsDebugMode
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return _debugMode; }
+        }
 
 
         internal bool _IsClrAllowed => _allowClr;
         internal bool _IsClrAllowed => _allowClr;
 
 
@@ -169,7 +178,11 @@ namespace Jint
 
 
         internal List<IObjectConverter> _ObjectConverters => _objectConverters;
         internal List<IObjectConverter> _ObjectConverters => _objectConverters;
 
 
-        internal int _MaxStatements => _maxStatements;
+        internal int _MaxStatements
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return _maxStatements; }
+        }
 
 
         internal int _MaxRecursionDepth => _maxRecursionDepth;
         internal int _MaxRecursionDepth => _maxRecursionDepth;
 
 

+ 1 - 1
Jint/Pooling/ArgumentsInstancePool.cs

@@ -47,7 +47,7 @@ namespace Jint.Pooling
 
 
         public void Return(ArgumentsInstance instance)
         public void Return(ArgumentsInstance instance)
         {
         {
-            if (instance == null)
+            if (ReferenceEquals(instance, null))
             {
             {
                 return;
                 return;
             }
             }

+ 24 - 4
Jint/Runtime/Completion.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Runtime.CompilerServices;
 using Esprima;
 using Esprima;
 using Jint.Native;
 using Jint.Native;
 
 
@@ -28,15 +29,34 @@ namespace Jint.Runtime
             Location = location;
             Location = location;
         }
         }
 
 
-        public string Type { get; private set; }
-        public JsValue Value { get; private set; }
-        public string Identifier { get; private set; }
+        public string Type
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get;
+            private set;
+        }
+
+        public JsValue Value
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get; 
+            private set;
+        }
+
+        public string Identifier
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get; 
+            private set;
+        }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public JsValue GetValueOrDefault()
         public JsValue GetValueOrDefault()
         {
         {
-            return Value != null ? Value : Undefined.Instance;
+            return Value ?? Undefined.Instance;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsAbrupt()
         public bool IsAbrupt()
         {
         {
             return Type != Normal;
             return Type != Normal;

+ 2 - 2
Jint/Runtime/Debugger/DebugHandler.cs

@@ -161,7 +161,7 @@ namespace Jint.Runtime.Debugger
         private static Dictionary<string, JsValue> GetLocalVariables(LexicalEnvironment lex)
         private static Dictionary<string, JsValue> GetLocalVariables(LexicalEnvironment lex)
         {
         {
             Dictionary<string, JsValue> locals = new Dictionary<string, JsValue>();
             Dictionary<string, JsValue> locals = new Dictionary<string, JsValue>();
-            if (lex != null && lex.Record != null)
+            if (!ReferenceEquals(lex?.Record, null))
             {
             {
                 AddRecordsFromEnvironment(lex, locals);
                 AddRecordsFromEnvironment(lex, locals);
             }
             }
@@ -173,7 +173,7 @@ namespace Jint.Runtime.Debugger
             Dictionary<string, JsValue> globals = new Dictionary<string, JsValue>();
             Dictionary<string, JsValue> globals = new Dictionary<string, JsValue>();
             LexicalEnvironment tempLex = lex;
             LexicalEnvironment tempLex = lex;
 
 
-            while (tempLex != null && tempLex.Record != null)
+            while (tempLex != null && !ReferenceEquals(tempLex.Record, null))
             {
             {
                 AddRecordsFromEnvironment(tempLex, globals);
                 AddRecordsFromEnvironment(tempLex, globals);
                 tempLex = tempLex.Outer;
                 tempLex = tempLex.Outer;

+ 75 - 29
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -1,4 +1,5 @@
-using System.Runtime.CompilerServices;
+using System;
+using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Descriptors.Specialized;
@@ -7,32 +8,43 @@ namespace Jint.Runtime.Descriptors
 {
 {
     public class PropertyDescriptor
     public class PropertyDescriptor
     {
     {
-        public static readonly PropertyDescriptor Undefined = new PropertyDescriptor();
+        public static readonly PropertyDescriptor Undefined = new PropertyDescriptor(PropertyFlag.None);
 
 
         private PropertyFlag _flags;
         private PropertyFlag _flags;
+        private JsValue _value;
 
 
-        protected PropertyDescriptor()
+        protected PropertyDescriptor(PropertyFlag flags)
         {
         {
+            _flags = flags;
+        }
+        
+        
+        protected internal PropertyDescriptor(JsValue value, PropertyFlag flags) : this(flags)
+        {
+            Value = value;
         }
         }
 
 
         public PropertyDescriptor(JsValue value, bool? writable, bool? enumerable, bool? configurable)
         public PropertyDescriptor(JsValue value, bool? writable, bool? enumerable, bool? configurable)
         {
         {
             Value = value;
             Value = value;
 
 
-            Writable = writable.GetValueOrDefault();
-            WritableSet = writable != null;
-
-            Enumerable = enumerable.GetValueOrDefault();
-            EnumerableSet = enumerable != null;
+            if (writable != null)
+            {
+                Writable = writable.Value;
+                WritableSet = true;
+            }
 
 
-            Configurable = configurable.GetValueOrDefault();
-            ConfigurableSet = configurable != null;
-        }
+            if (enumerable != null)
+            {
+                Enumerable = enumerable.Value;
+                EnumerableSet = true;
+            }
 
 
-        internal PropertyDescriptor(JsValue value, PropertyFlag flags)
-        {
-            Value = value;
-            _flags = flags;
+            if (configurable != null)
+            {
+                Configurable = configurable.Value;
+                ConfigurableSet = true;
+            }
         }
         }
 
 
         public PropertyDescriptor(PropertyDescriptor descriptor)
         public PropertyDescriptor(PropertyDescriptor descriptor)
@@ -163,12 +175,45 @@ namespace Jint.Runtime.Descriptors
             }
             }
         }
         }
 
 
-        public virtual JsValue Value { get; set; }
+        public JsValue Value
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                if ((_flags & PropertyFlag.CustomJsValue) != 0)
+                {
+                    return CustomValue;
+                }
+                
+                return _value;
+            }
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            set
+            {
+                if ((_flags & PropertyFlag.CustomJsValue) != 0)
+                {
+                    CustomValue = value;
+                }
+                _value = value;
+            }
+        }
+
+        protected virtual JsValue CustomValue
+        {
+            get => null;
+            set => throw new NotImplementedException();
+        }
+
+        internal PropertyFlag Flags
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return _flags; }
+        }
 
 
         public static PropertyDescriptor ToPropertyDescriptor(Engine engine, JsValue o)
         public static PropertyDescriptor ToPropertyDescriptor(Engine engine, JsValue o)
         {
         {
             var obj = o.TryCast<ObjectInstance>();
             var obj = o.TryCast<ObjectInstance>();
-            if (obj == null)
+            if (ReferenceEquals(obj, null))
             {
             {
                 throw new JavaScriptException(engine.TypeError);
                 throw new JavaScriptException(engine.TypeError);
             }
             }
@@ -185,8 +230,8 @@ namespace Jint.Runtime.Descriptors
             }
             }
 
 
             var desc = hasGetProperty || hasSetProperty
             var desc = hasGetProperty || hasSetProperty
-                ? new GetSetPropertyDescriptor(null, null, null, null)
-                : new PropertyDescriptor();
+                ? new GetSetPropertyDescriptor(null, null, PropertyFlag.None)
+                : new PropertyDescriptor(PropertyFlag.None);
 
 
             var enumerableProperty = obj.GetProperty("enumerable");
             var enumerableProperty = obj.GetProperty("enumerable");
             if (enumerableProperty != Undefined)
             if (enumerableProperty != Undefined)
@@ -218,7 +263,7 @@ namespace Jint.Runtime.Descriptors
             if (hasGetProperty)
             if (hasGetProperty)
             {
             {
                 var getter = obj.UnwrapJsValue(getProperty);
                 var getter = obj.UnwrapJsValue(getProperty);
-                if (getter != JsValue.Undefined && getter.TryCast<ICallable>() == null)
+                if (!ReferenceEquals(getter, JsValue.Undefined) && getter.TryCast<ICallable>() == null)
                 {
                 {
                     throw new JavaScriptException(engine.TypeError);
                     throw new JavaScriptException(engine.TypeError);
                 }
                 }
@@ -229,7 +274,7 @@ namespace Jint.Runtime.Descriptors
             if (hasSetProperty)
             if (hasSetProperty)
             {
             {
                 var setter = obj.UnwrapJsValue(setProperty);
                 var setter = obj.UnwrapJsValue(setProperty);
-                if (setter != Native.Undefined.Instance && setter.TryCast<ICallable>() == null)
+                if (!ReferenceEquals(setter, JsValue.Undefined) && setter.TryCast<ICallable>() == null)
                 {
                 {
                     throw new JavaScriptException(engine.TypeError);
                     throw new JavaScriptException(engine.TypeError);
                 }
                 }
@@ -237,9 +282,9 @@ namespace Jint.Runtime.Descriptors
                 ((GetSetPropertyDescriptor) desc).SetSet(setter);
                 ((GetSetPropertyDescriptor) desc).SetSet(setter);
             }
             }
 
 
-            if (desc.Get != null || desc.Get != null)
+            if (!ReferenceEquals(desc.Get, null) || !ReferenceEquals(desc.Get, null))
             {
             {
-                if (desc.Value != null || desc.WritableSet)
+                if (!ReferenceEquals(desc.Value, null) || desc.WritableSet)
                 {
                 {
                     throw new JavaScriptException(engine.TypeError);
                     throw new JavaScriptException(engine.TypeError);
                 }
                 }
@@ -259,7 +304,7 @@ namespace Jint.Runtime.Descriptors
 
 
             if (desc.IsDataDescriptor())
             if (desc.IsDataDescriptor())
             {
             {
-                obj.SetOwnProperty("value", new PropertyDescriptor(desc.Value != null ? desc.Value : Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable));
+                obj.SetOwnProperty("value", new PropertyDescriptor(desc.Value ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable));
                 obj.SetOwnProperty("writable", new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable));
                 obj.SetOwnProperty("writable", new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable));
             }
             }
             else
             else
@@ -277,13 +322,13 @@ namespace Jint.Runtime.Descriptors
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsAccessorDescriptor()
         public bool IsAccessorDescriptor()
         {
         {
-            return Get != null || Set != null;
+            return !ReferenceEquals(Get, null) || !ReferenceEquals(Set, null);
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsDataDescriptor()
         public bool IsDataDescriptor()
         {
         {
-            return WritableSet || Value != null;
+            return WritableSet || !ReferenceEquals(Value, null);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -310,17 +355,18 @@ namespace Jint.Runtime.Descriptors
             if (IsDataDescriptor())
             if (IsDataDescriptor())
             {
             {
                 var val = Value;
                 var val = Value;
-                if (val != null)
+                if (!ReferenceEquals(val, null))
                 {
                 {
                     value = val;
                     value = val;
                     return true;
                     return true;
                 }
                 }
             }
             }
 
 
-            if (Get != null && !Get.IsUndefined())
+            var getter = Get;
+            if (!ReferenceEquals(getter, null) && !getter.IsUndefined())
             {
             {
                 // if getter is not undefined it must be ICallable
                 // if getter is not undefined it must be ICallable
-                var callable = Get.TryCast<ICallable>();
+                var callable = getter.TryCast<ICallable>();
                 value = callable.Call(thisArg, Arguments.Empty);
                 value = callable.Call(thisArg, Arguments.Empty);
             }
             }
 
 

+ 3 - 1
Jint/Runtime/Descriptors/PropertyFlag.cs

@@ -3,7 +3,7 @@
 namespace Jint.Runtime.Descriptors
 namespace Jint.Runtime.Descriptors
 {
 {
     [Flags]
     [Flags]
-    internal enum PropertyFlag
+    public enum PropertyFlag
     {
     {
         None = 0,
         None = 0,
         Enumerable = 1,
         Enumerable = 1,
@@ -13,6 +13,8 @@ namespace Jint.Runtime.Descriptors
         Configurable = 16,
         Configurable = 16,
         ConfigurableSet = 32,
         ConfigurableSet = 32,
         
         
+        CustomJsValue = 256,
+        
         // common helpers
         // common helpers
         AllForbidden = ConfigurableSet | EnumerableSet | WritableSet,
         AllForbidden = ConfigurableSet | EnumerableSet | WritableSet,
         ConfigurableEnumerableWritable = Configurable | Enumerable | Writable,
         ConfigurableEnumerableWritable = Configurable | Enumerable | Writable,

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/ClrAccessDescriptor.cs

@@ -17,7 +17,7 @@ namespace Jint.Runtime.Descriptors.Specialized
             EnvironmentRecord env,
             EnvironmentRecord env,
             Engine engine,
             Engine engine,
             string name)
             string name)
-            : base(value: null, writable: null, enumerable: null, configurable: true)
+            : base(value: null, PropertyFlag.Configurable)
         {
         {
             _env = env;
             _env = env;
             _engine = engine;
             _engine = engine;

+ 3 - 7
Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs

@@ -10,7 +10,7 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly FieldInfo _fieldInfo;
         private readonly FieldInfo _fieldInfo;
         private readonly object _item;
         private readonly object _item;
 
 
-        public FieldInfoDescriptor(Engine engine, FieldInfo fieldInfo, object item)
+        public FieldInfoDescriptor(Engine engine, FieldInfo fieldInfo, object item) : base(PropertyFlag.CustomJsValue)
         {
         {
             _engine = engine;
             _engine = engine;
             _fieldInfo = fieldInfo;
             _fieldInfo = fieldInfo;
@@ -19,13 +19,9 @@ namespace Jint.Runtime.Descriptors.Specialized
             Writable = !fieldInfo.Attributes.HasFlag(FieldAttributes.InitOnly); // don't write to fields marked as readonly
             Writable = !fieldInfo.Attributes.HasFlag(FieldAttributes.InitOnly); // don't write to fields marked as readonly
         }
         }
 
 
-        public override JsValue Value
+        protected override JsValue CustomValue
         {
         {
-            get
-            {
-                return JsValue.FromObject(_engine, _fieldInfo.GetValue(_item));
-            }
-
+            get => JsValue.FromObject(_engine, _fieldInfo.GetValue(_item));
             set
             set
             {
             {
                 var currentValue = value;
                 var currentValue = value;

+ 7 - 0
Jint/Runtime/Descriptors/Specialized/GetSetPropertyDescriptor.cs

@@ -14,6 +14,13 @@ namespace Jint.Runtime.Descriptors.Specialized
             _set = set;
             _set = set;
         }
         }
 
 
+        internal GetSetPropertyDescriptor(JsValue get, JsValue set, PropertyFlag flags)
+            : base(null, flags)
+        {
+            _get = get;
+            _set = set;
+        }
+
         public GetSetPropertyDescriptor(PropertyDescriptor descriptor) : base(descriptor)
         public GetSetPropertyDescriptor(PropertyDescriptor descriptor) : base(descriptor)
         {
         {
             _get = descriptor.Get;
             _get = descriptor.Get;

+ 5 - 6
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -13,7 +13,7 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly PropertyInfo _indexer;
         private readonly PropertyInfo _indexer;
         private readonly MethodInfo _containsKey;
         private readonly MethodInfo _containsKey;
 
 
-        public IndexDescriptor(Engine engine, Type targetType, string key, object item)
+        public IndexDescriptor(Engine engine, Type targetType, string key, object item) : base(PropertyFlag.CustomJsValue)
         {
         {
             _engine = engine;
             _engine = engine;
             _item = item;
             _item = item;
@@ -33,9 +33,8 @@ namespace Jint.Runtime.Descriptors.Specialized
                     {
                     {
                         _indexer = indexer;
                         _indexer = indexer;
                         // get contains key method to avoid index exception being thrown in dictionaries
                         // get contains key method to avoid index exception being thrown in dictionaries
-                        _containsKey = targetType.GetMethod("ContainsKey", new Type[] { paramType });
+                        _containsKey = targetType.GetMethod("ContainsKey", new Type[] {paramType});
                         break;
                         break;
-
                     }
                     }
                 }
                 }
             }
             }
@@ -54,7 +53,7 @@ namespace Jint.Runtime.Descriptors.Specialized
         {
         {
         }
         }
 
 
-        public override JsValue Value
+        protected override JsValue CustomValue
         {
         {
             get
             get
             {
             {
@@ -65,7 +64,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     throw new InvalidOperationException("Indexer has no public getter.");
                     throw new InvalidOperationException("Indexer has no public getter.");
                 }
                 }
 
 
-                object[] parameters = { _key };
+                object[] parameters = {_key};
 
 
                 if (_containsKey != null)
                 if (_containsKey != null)
                 {
                 {
@@ -93,7 +92,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     throw new InvalidOperationException("Indexer has no public setter.");
                     throw new InvalidOperationException("Indexer has no public setter.");
                 }
                 }
 
 
-                object[] parameters = { _key, value != null ? value.ToObject() : null };
+                object[] parameters = {_key, value?.ToObject()};
                 setter.Invoke(_item, parameters);
                 setter.Invoke(_item, parameters);
             }
             }
         }
         }

+ 3 - 7
Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs

@@ -10,7 +10,7 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly PropertyInfo _propertyInfo;
         private readonly PropertyInfo _propertyInfo;
         private readonly object _item;
         private readonly object _item;
 
 
-        public PropertyInfoDescriptor(Engine engine, PropertyInfo propertyInfo, object item)
+        public PropertyInfoDescriptor(Engine engine, PropertyInfo propertyInfo, object item) : base(PropertyFlag.CustomJsValue)
         {
         {
             _engine = engine;
             _engine = engine;
             _propertyInfo = propertyInfo;
             _propertyInfo = propertyInfo;
@@ -19,13 +19,9 @@ namespace Jint.Runtime.Descriptors.Specialized
             Writable = propertyInfo.CanWrite;
             Writable = propertyInfo.CanWrite;
         }
         }
 
 
-        public override JsValue Value
+        protected override JsValue CustomValue
         {
         {
-            get
-            {
-                return JsValue.FromObject(_engine, _propertyInfo.GetValue(_item, null));
-            }
-
+            get => JsValue.FromObject(_engine, _propertyInfo.GetValue(_item, null));
             set
             set
             {
             {
                 var currentValue = value;
                 var currentValue = value;

+ 1 - 1
Jint/Runtime/Environments/ObjectEnvironmentRecord.cs

@@ -73,7 +73,7 @@ namespace Jint.Runtime.Environments
 
 
         public override string[] GetAllBindingNames()
         public override string[] GetAllBindingNames()
         {
         {
-            if (_bindingObject != null)
+            if (!ReferenceEquals(_bindingObject, null))
             {
             {
                 return _bindingObject.GetOwnProperties().Select( x=> x.Key).ToArray();
                 return _bindingObject.GetOwnProperties().Select( x=> x.Key).ToArray();
             }
             }

+ 19 - 17
Jint/Runtime/ExpressionIntepreter.cs

@@ -45,7 +45,7 @@ namespace Jint.Runtime
 
 
         public JsValue EvaluateAssignmentExpression(AssignmentExpression assignmentExpression)
         public JsValue EvaluateAssignmentExpression(AssignmentExpression assignmentExpression)
         {
         {
-            var lref = EvaluateExpression(assignmentExpression.Left.As<Expression>()) as Reference;
+            var lref = EvaluateExpression((Expression) assignmentExpression.Left) as Reference;
             JsValue rval = _engine.GetValue(EvaluateExpression(assignmentExpression.Right), true);
             JsValue rval = _engine.GetValue(EvaluateExpression(assignmentExpression.Right), true);
 
 
             if (lref == null)
             if (lref == null)
@@ -56,7 +56,9 @@ namespace Jint.Runtime
             if (assignmentExpression.Operator == AssignmentOperator.Assign) // "="
             if (assignmentExpression.Operator == AssignmentOperator.Assign) // "="
             {
             {
 
 
-                if(lref.IsStrict() && lref.GetBase().TryCast<EnvironmentRecord>() != null && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
+                if(lref.IsStrict() 
+                   && !ReferenceEquals(lref.GetBase().TryCast<EnvironmentRecord>(), null) 
+                   && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
                 {
                 {
                     throw new JavaScriptException(_engine.SyntaxError);
                     throw new JavaScriptException(_engine.SyntaxError);
                 }
                 }
@@ -76,7 +78,7 @@ namespace Jint.Runtime
                     if (lprim.IsString() || rprim.IsString())
                     if (lprim.IsString() || rprim.IsString())
                     {
                     {
                         var jsString = lprim as JsString;
                         var jsString = lprim as JsString;
-                        if (jsString == null)
+                        if (ReferenceEquals(jsString, null))
                         {
                         {
                             jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim));
                             jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim));
                         }
                         }
@@ -208,7 +210,7 @@ namespace Jint.Runtime
             JsValue left;
             JsValue left;
             if (expression.Left.Type == Nodes.Literal)
             if (expression.Left.Type == Nodes.Literal)
             {
             {
-                left = EvaluateLiteral(expression.Left.As<Literal>());
+                left = EvaluateLiteral((Literal) expression.Left);
             }
             }
             else
             else
             {
             {
@@ -218,7 +220,7 @@ namespace Jint.Runtime
             JsValue right;
             JsValue right;
             if (expression.Right.Type == Nodes.Literal)
             if (expression.Right.Type == Nodes.Literal)
             {
             {
-                right = EvaluateLiteral(expression.Right.As<Literal>());
+                right = EvaluateLiteral((Literal) expression.Right);
             }
             }
             else
             else
             {
             {
@@ -346,12 +348,10 @@ namespace Jint.Runtime
 
 
                 case BinaryOperator.InstanceOf:
                 case BinaryOperator.InstanceOf:
                     var f = right.TryCast<FunctionInstance>();
                     var f = right.TryCast<FunctionInstance>();
-
-                    if (f == null)
+                    if (ReferenceEquals(f, null))
                     {
                     {
                         throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
                         throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
                     }
                     }
-
                     value = f.HasInstance(left);
                     value = f.HasInstance(left);
                     break;
                     break;
 
 
@@ -666,11 +666,13 @@ namespace Jint.Runtime
                 var previous = obj.GetOwnProperty(propName);
                 var previous = obj.GetOwnProperty(propName);
                 PropertyDescriptor propDesc;
                 PropertyDescriptor propDesc;
 
 
+                const PropertyFlag enumerableConfigurable = PropertyFlag.Enumerable | PropertyFlag.Configurable;
+                
                 switch (property.Kind)
                 switch (property.Kind)
                 {
                 {
                     case PropertyKind.Init:
                     case PropertyKind.Init:
                     case PropertyKind.Data:
                     case PropertyKind.Data:
-                        var exprValue = _engine.EvaluateExpression(property.Value.As<Expression>());
+                        var exprValue = _engine.EvaluateExpression(property.Value);
                         var propValue = _engine.GetValue(exprValue, true);
                         var propValue = _engine.GetValue(exprValue, true);
                         propDesc = new PropertyDescriptor(propValue, PropertyFlag.ConfigurableEnumerableWritable);
                         propDesc = new PropertyDescriptor(propValue, PropertyFlag.ConfigurableEnumerableWritable);
                         break;
                         break;
@@ -694,7 +696,7 @@ namespace Jint.Runtime
                             );
                             );
                         }
                         }
 
 
-                        propDesc = new GetSetPropertyDescriptor(get: get, set: null, enumerable: true, configurable: true);
+                        propDesc = new GetSetPropertyDescriptor(get: get, set: null, enumerableConfigurable);
                         break;
                         break;
 
 
                     case PropertyKind.Set:
                     case PropertyKind.Set:
@@ -716,7 +718,7 @@ namespace Jint.Runtime
                             );
                             );
                         }
                         }
 
 
-                        propDesc = new GetSetPropertyDescriptor(get: null, set: set, enumerable: true, configurable: true);
+                        propDesc = new GetSetPropertyDescriptor(get: null, set: set, enumerableConfigurable);
                         break;
                         break;
 
 
                     default:
                     default:
@@ -742,12 +744,12 @@ namespace Jint.Runtime
 
 
                     if (previous.IsAccessorDescriptor() && propDesc.IsAccessorDescriptor())
                     if (previous.IsAccessorDescriptor() && propDesc.IsAccessorDescriptor())
                     {
                     {
-                        if (propDesc.Set != null && previous.Set != null)
+                        if (!ReferenceEquals(propDesc.Set, null) && !ReferenceEquals(previous.Set, null))
                         {
                         {
                             throw new JavaScriptException(_engine.SyntaxError);
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
                         }
 
 
-                        if (propDesc.Get != null && previous.Get != null)
+                        if (!ReferenceEquals(propDesc.Get, null) && !ReferenceEquals(previous.Get, null))
                         {
                         {
                             throw new JavaScriptException(_engine.SyntaxError);
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
                         }
@@ -948,7 +950,7 @@ namespace Jint.Runtime
             for (var i = 0; i < expressionsCount; i++)
             for (var i = 0; i < expressionsCount; i++)
             {
             {
                 var expression = sequenceExpression.Expressions[i];
                 var expression = sequenceExpression.Expressions[i];
-                result = _engine.GetValue(_engine.EvaluateExpression(expression.As<Expression>()), true);
+                result = _engine.GetValue(_engine.EvaluateExpression(expression), true);
             }
             }
 
 
             return result;
             return result;
@@ -965,7 +967,7 @@ namespace Jint.Runtime
                     r = value as Reference;
                     r = value as Reference;
                     if (r != null
                     if (r != null
                         && r.IsStrict()
                         && r.IsStrict()
-                        && (r.GetBase().TryCast<EnvironmentRecord>() != null)
+                        && (!ReferenceEquals(r.GetBase().TryCast<EnvironmentRecord>(), null))
                         && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
                         && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
                     {
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                         throw new JavaScriptException(_engine.SyntaxError);
@@ -982,7 +984,7 @@ namespace Jint.Runtime
                     r = value as Reference;
                     r = value as Reference;
                     if (r != null
                     if (r != null
                         && r.IsStrict()
                         && r.IsStrict()
-                        && (r.GetBase().TryCast<EnvironmentRecord>() != null)
+                        && (!ReferenceEquals(r.GetBase().TryCast<EnvironmentRecord>(), null))
                         && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
                         && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
                     {
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                         throw new JavaScriptException(_engine.SyntaxError);
@@ -1041,7 +1043,7 @@ namespace Jint.Runtime
                 var expr = elements[n];
                 var expr = elements[n];
                 if (expr != null)
                 if (expr != null)
                 {
                 {
-                    var value = _engine.GetValue(EvaluateExpression(expr.As<Expression>()), true);
+                    var value = _engine.GetValue(EvaluateExpression((Expression) expr), true);
                     a.SetIndexValue((uint) n, value, throwOnError: false);
                     a.SetIndexValue((uint) n, value, throwOnError: false);
                 }
                 }
             }
             }

+ 1 - 1
Jint/Runtime/Interop/NamespaceReference.cs

@@ -62,7 +62,7 @@ namespace Jint.Runtime.Interop
 
 
             var typeReference = GetPath(_path + "`" + arguments.Length.ToString(CultureInfo.InvariantCulture)).As<TypeReference>();
             var typeReference = GetPath(_path + "`" + arguments.Length.ToString(CultureInfo.InvariantCulture)).As<TypeReference>();
 
 
-            if (typeReference == null)
+            if (ReferenceEquals(typeReference, null))
             {
             {
                 return Undefined;
                 return Undefined;
             }
             }

+ 1 - 1
Jint/Runtime/Interop/TypeReference.cs

@@ -100,7 +100,7 @@ namespace Jint.Runtime.Interop
         {
         {
             ObjectWrapper wrapper = v.As<ObjectWrapper>();
             ObjectWrapper wrapper = v.As<ObjectWrapper>();
 
 
-            if (wrapper == null)
+            if (ReferenceEquals(wrapper, null))
             {
             {
                 return base.HasInstance(v);
                 return base.HasInstance(v);
             }
             }

+ 2 - 2
Jint/Runtime/JavaScriptException.cs

@@ -95,12 +95,12 @@ namespace Jint.Runtime
             {
             {
                 if (_callStack != null)
                 if (_callStack != null)
                     return _callStack;
                     return _callStack;
-                if (Error == null)
+                if (ReferenceEquals(Error, null))
                     return null;
                     return null;
                 if (Error.IsObject() == false)
                 if (Error.IsObject() == false)
                     return null;
                     return null;
                 var callstack = Error.AsObject().Get("callstack");
                 var callstack = Error.AsObject().Get("callstack");
-                if (callstack == JsValue.Undefined)
+                if (ReferenceEquals(callstack, JsValue.Undefined))
                     return null;
                     return null;
                 return callstack.AsString();
                 return callstack.AsString();
             }
             }

+ 8 - 1
Jint/Runtime/References/Reference.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Native;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Environments;
 
 
@@ -20,35 +21,41 @@ namespace Jint.Runtime.References
             _name = name;
             _name = name;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public JsValue GetBase()
         public JsValue GetBase()
         {
         {
             return _baseValue;
             return _baseValue;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public string GetReferencedName()
         public string GetReferencedName()
         {
         {
             return _name;
             return _name;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsStrict()
         public bool IsStrict()
         {
         {
             return _strict;
             return _strict;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool HasPrimitiveBase()
         public bool HasPrimitiveBase()
         {
         {
             return _baseValue.IsPrimitive();
             return _baseValue.IsPrimitive();
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsUnresolvableReference()
         public bool IsUnresolvableReference()
         {
         {
             return _baseValue.IsUndefined();
             return _baseValue.IsUndefined();
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool IsPropertyReference()
         public bool IsPropertyReference()
         {
         {
             // http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
             // http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
-            return HasPrimitiveBase() || (_baseValue.IsObject() && !(_baseValue is EnvironmentRecord));
+            return _baseValue.IsPrimitive() || (_baseValue.IsObject() && !(_baseValue is EnvironmentRecord));
         }
         }
 
 
         internal Reference Reassign(JsValue baseValue, string name, bool strict)
         internal Reference Reassign(JsValue baseValue, string name, bool strict)

+ 22 - 23
Jint/Runtime/StatementInterpreter.cs

@@ -1,6 +1,5 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
@@ -82,7 +81,7 @@ namespace Jint.Runtime
             do
             do
             {
             {
                 var stmt = ExecuteStatement(doWhileStatement.Body);
                 var stmt = ExecuteStatement(doWhileStatement.Body);
-                if (stmt.Value != null)
+                if (!ReferenceEquals(stmt.Value, null))
                 {
                 {
                     v = stmt.Value;
                     v = stmt.Value;
                 }
                 }
@@ -127,7 +126,7 @@ namespace Jint.Runtime
 
 
                 var stmt = ExecuteStatement(whileStatement.Body);
                 var stmt = ExecuteStatement(whileStatement.Body);
 
 
-                if (stmt.Value != null)
+                if (!ReferenceEquals(stmt.Value, null))
                 {
                 {
                     v = stmt.Value;
                     v = stmt.Value;
                 }
                 }
@@ -157,18 +156,18 @@ namespace Jint.Runtime
         /// <returns></returns>
         /// <returns></returns>
         public Completion ExecuteForStatement(ForStatement forStatement)
         public Completion ExecuteForStatement(ForStatement forStatement)
         {
         {
-
-            if (forStatement.Init != null)
+            var init = forStatement.Init;
+            if (init != null)
             {
             {
-                if (forStatement.Init.Type == Nodes.VariableDeclaration)
+                if (init.Type == Nodes.VariableDeclaration)
                 {
                 {
-                    var c = ExecuteStatement(forStatement.Init.As<Statement>());
+                    var c = ExecuteStatement((Statement) init);
                     _engine.CompletionPool.Return(c);
                     _engine.CompletionPool.Return(c);
 
 
                 }
                 }
                 else
                 else
                 {
                 {
-                    _engine.GetValue(_engine.EvaluateExpression(forStatement.Init.As<Expression>()), true);
+                    _engine.GetValue(_engine.EvaluateExpression(init), true);
                 }
                 }
             }
             }
 
 
@@ -185,7 +184,7 @@ namespace Jint.Runtime
                 }
                 }
 
 
                 var stmt = ExecuteStatement(forStatement.Body);
                 var stmt = ExecuteStatement(forStatement.Body);
-                if (stmt.Value != null)
+                if (!ReferenceEquals(stmt.Value, null))
                 {
                 {
                     v = stmt.Value;
                     v = stmt.Value;
                 }
                 }
@@ -216,9 +215,9 @@ namespace Jint.Runtime
         /// <returns></returns>
         /// <returns></returns>
         public Completion ExecuteForInStatement(ForInStatement forInStatement)
         public Completion ExecuteForInStatement(ForInStatement forInStatement)
         {
         {
-            Identifier identifier = forInStatement.Left.Type == Nodes.VariableDeclaration
-                                        ? forInStatement.Left.As<VariableDeclaration>().Declarations.First().Id.As<Identifier>()
-                                        : forInStatement.Left.As<Identifier>();
+            var identifier = forInStatement.Left.Type == Nodes.VariableDeclaration
+                ? (Identifier) ((VariableDeclaration) forInStatement.Left).Declarations[0].Id
+                : (Identifier) forInStatement.Left;
 
 
             var varRef = _engine.EvaluateExpression(identifier) as Reference;
             var varRef = _engine.EvaluateExpression(identifier) as Reference;
             var experValue = _engine.GetValue(_engine.EvaluateExpression(forInStatement.Right), true);
             var experValue = _engine.GetValue(_engine.EvaluateExpression(forInStatement.Right), true);
@@ -234,7 +233,7 @@ namespace Jint.Runtime
             var cursor = obj;
             var cursor = obj;
             var processedKeys = new HashSet<string>();
             var processedKeys = new HashSet<string>();
 
 
-            while (cursor != null)
+            while (!ReferenceEquals(cursor, null))
             {
             {
                 var keys = _engine.Object.GetOwnPropertyNames(Undefined.Instance, Arguments.From(cursor)).AsArray();
                 var keys = _engine.Object.GetOwnPropertyNames(Undefined.Instance, Arguments.From(cursor)).AsArray();
 
 
@@ -265,7 +264,7 @@ namespace Jint.Runtime
                     _engine.PutValue(varRef, p);
                     _engine.PutValue(varRef, p);
 
 
                     var stmt = ExecuteStatement(forInStatement.Body);
                     var stmt = ExecuteStatement(forInStatement.Body);
-                    if (stmt.Value != null)
+                    if (!ReferenceEquals(stmt.Value, null))
                     {
                     {
                         v = stmt.Value;
                         v = stmt.Value;
                     }
                     }
@@ -409,7 +408,7 @@ namespace Jint.Runtime
                         return r;
                         return r;
                     }
                     }
 
 
-                    v = r.Value != null ? r.Value : Undefined.Instance;
+                    v = r.Value ?? Undefined.Instance;
                 }
                 }
             }
             }
 
 
@@ -422,7 +421,7 @@ namespace Jint.Runtime
                     return r;
                     return r;
                 }
                 }
 
 
-                v = r.Value != null ? r.Value : Undefined.Instance;
+                v = r.Value ?? Undefined.Instance;
             }
             }
 
 
             return _engine.CompletionPool.Rent(Completion.Normal, v, null);
             return _engine.CompletionPool.Rent(Completion.Normal, v, null);
@@ -439,14 +438,13 @@ namespace Jint.Runtime
                 var statementListCount = statementList.Count;
                 var statementListCount = statementList.Count;
                 for (var i = 0; i < statementListCount; i++)
                 for (var i = 0; i < statementListCount; i++)
                 {
                 {
-                    var statement = statementList[i];
-                    s = statement.As<Statement>();
+                    s = (Statement) statementList[i];
                     c = ExecuteStatement(s);
                     c = ExecuteStatement(s);
                     if (c.Type != Completion.Normal)
                     if (c.Type != Completion.Normal)
                     {
                     {
                         var executeStatementList = _engine.CompletionPool.Rent(
                         var executeStatementList = _engine.CompletionPool.Rent(
                             c.Type,
                             c.Type,
-                            c.Value != null ? c.Value : sl.Value,
+                            c.Value ?? sl.Value,
                             c.Identifier,
                             c.Identifier,
                             c.Location);
                             c.Location);
 
 
@@ -502,7 +500,7 @@ namespace Jint.Runtime
                     var c = _engine.GetValue(b);
                     var c = _engine.GetValue(b);
                     var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                     var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                     var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                     var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
-                    catchEnv.Record.CreateMutableBinding(catchClause.Param.As<Identifier>().Name, c);
+                    catchEnv.Record.CreateMutableBinding(((Identifier) catchClause.Param).Name, c);
                     _engine.ExecutionContext.LexicalEnvironment = catchEnv;
                     _engine.ExecutionContext.LexicalEnvironment = catchEnv;
                     b = ExecuteStatement(catchClause.Body);
                     b = ExecuteStatement(catchClause.Body);
                     _engine.ExecutionContext.LexicalEnvironment = oldEnv;
                     _engine.ExecutionContext.LexicalEnvironment = oldEnv;
@@ -536,13 +534,14 @@ namespace Jint.Runtime
                 var declaration = statement.Declarations[i];
                 var declaration = statement.Declarations[i];
                 if (declaration.Init != null)
                 if (declaration.Init != null)
                 {
                 {
-                    if (!(_engine.EvaluateExpression(declaration.Id.As<Identifier>()) is Reference lhs))
+                    if (!(_engine.EvaluateExpression(declaration.Id) is Reference lhs))
                     {
                     {
                         throw new ArgumentException();
                         throw new ArgumentException();
                     }
                     }
 
 
-                    if (lhs.IsStrict() && lhs.GetBase().TryCast<EnvironmentRecord>() != null &&
-                        (lhs.GetReferencedName() == "eval" || lhs.GetReferencedName() == "arguments"))
+                    if (lhs.IsStrict() 
+                        && !ReferenceEquals(lhs.GetBase().TryCast<EnvironmentRecord>(), null) 
+                        && (lhs.GetReferencedName() == "eval" || lhs.GetReferencedName() == "arguments"))
                     {
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
                     }

+ 26 - 21
Jint/Runtime/TypeConverter.cs

@@ -74,18 +74,18 @@ namespace Jint.Runtime
         /// <summary>
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
         /// </summary>
         /// </summary>
-        /// <param name="o"></param>
-        /// <returns></returns>
         public static bool ToBoolean(JsValue o)
         public static bool ToBoolean(JsValue o)
         {
         {
-            if (o.IsObject())
+            var type = o.Type;
+
+            if (type == Types.Object)
             {
             {
                 return true;
                 return true;
             }
             }
 
 
-            if (o.IsBoolean())
+            if (type == Types.Boolean)
             {
             {
-                return o.AsBoolean();
+                return ((JsBoolean) o)._value;
             }
             }
 
 
             if (ReferenceEquals(o, Undefined.Instance) || ReferenceEquals(o, Null.Instance))
             if (ReferenceEquals(o, Undefined.Instance) || ReferenceEquals(o, Null.Instance))
@@ -93,9 +93,9 @@ namespace Jint.Runtime
                 return false;
                 return false;
             }
             }
 
 
-            if (o.IsNumber())
+            if (type == Types.Number)
             {
             {
-                var n = o.AsNumber();
+                var n = ((JsNumber) o)._value;
                 if (n.Equals(0) || double.IsNaN(n))
                 if (n.Equals(0) || double.IsNaN(n))
                 {
                 {
                     return false;
                     return false;
@@ -104,10 +104,10 @@ namespace Jint.Runtime
                 return true;
                 return true;
             }
             }
 
 
-            if (o.IsString())
+            if (type == Types.String)
             {
             {
                 var s = o.AsString();
                 var s = o.AsString();
-                if (String.IsNullOrEmpty(s))
+                if (string.IsNullOrEmpty(s))
                 {
                 {
                     return false;
                     return false;
                 }
                 }
@@ -126,15 +126,15 @@ namespace Jint.Runtime
         public static double ToNumber(JsValue o)
         public static double ToNumber(JsValue o)
         {
         {
             // check number first as this is what is usually expected
             // check number first as this is what is usually expected
-            if (o.IsNumber())
+            var type = o.Type;
+            if (type == Types.Number)
             {
             {
-                return o.AsNumber();
+                return ((JsNumber) o)._value;
             }
             }
 
 
-            if (o.IsObject())
+            if (type == Types.Object)
             {
             {
-                var p = o.AsObject() as IPrimitiveInstance;
-                if (p != null)
+                if (o is IPrimitiveInstance p)
                 {
                 {
                     o = p.PrimitiveValue;
                     o = p.PrimitiveValue;
                 }
                 }
@@ -150,12 +150,12 @@ namespace Jint.Runtime
                 return 0;
                 return 0;
             }
             }
 
 
-            if (o.IsBoolean())
+            if (type == Types.Boolean)
             {
             {
-                return o.AsBoolean() ? 1 : 0;
+                return ((JsBoolean) o)._value ? 1 : 0;
             }
             }
 
 
-            if (o.IsString())
+            if (type == Types.String)
             {
             {
                 return ToNumber(o.AsString());
                 return ToNumber(o.AsString());
             }
             }
@@ -171,7 +171,9 @@ namespace Jint.Runtime
                 return 0;
                 return 0;
             }
             }
 
 
-            var s = StringPrototype.TrimEx(input);
+            var s = StringPrototype.IsWhiteSpaceEx(input[0]) || StringPrototype.IsWhiteSpaceEx(input[input.Length - 1])
+                ? StringPrototype.TrimEx(input)
+                : input;
 
 
             if (string.IsNullOrEmpty(s))
             if (string.IsNullOrEmpty(s))
             {
             {
@@ -361,7 +363,7 @@ namespace Jint.Runtime
                 else
                 else
                 {
                 {
                     var s = o.AsInstance<SymbolInstance>();
                     var s = o.AsInstance<SymbolInstance>();
-                    if (s != null)
+                    if (!ReferenceEquals(s, null))
                     {
                     {
                         // TODO: throw a TypeError
                         // TODO: throw a TypeError
                         // NB: But it requires an Engine reference
                         // NB: But it requires an Engine reference
@@ -454,10 +456,13 @@ namespace Jint.Runtime
             return value.Type;
             return value.Type;
         }
         }
 
 
-        public static void CheckObjectCoercible(Engine engine, JsValue o, MemberExpression expression,
+        public static void CheckObjectCoercible(
+            Engine engine,
+            JsValue o,
+            MemberExpression expression,
             object baseReference)
             object baseReference)
         {
         {
-            if (o != Undefined.Instance && o != Null.Instance)
+            if (!ReferenceEquals(o, Undefined.Instance) && !ReferenceEquals(o, Null.Instance))
             {
             {
                 return;
                 return;
             }
             }