Use singleton for zero-element arrays.
Create an easily-inlinable method that accesses the array used by Enumerable.Empty (and hence not just shared within this project but likely with the client assembly or other libraries it uses) and use it anywhere a zero-element array is used, reducing allocations.
This commit is contained in:
@@ -544,7 +544,7 @@ namespace Newtonsoft.Json
|
||||
Guid g;
|
||||
if (s.Length == 0)
|
||||
{
|
||||
data = new byte[0];
|
||||
data = CollectionUtils.ArrayEmpty<byte>();
|
||||
}
|
||||
else if (ConvertUtils.TryConvertGuid(s, out g))
|
||||
{
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Newtonsoft.Json
|
||||
byte[] data;
|
||||
if (_stringReference.Length == 0)
|
||||
{
|
||||
data = new byte[0];
|
||||
data = CollectionUtils.ArrayEmpty<byte>();
|
||||
}
|
||||
else if (_stringReference.Length == 36 && ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g))
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Newtonsoft.Json.Linq.JsonPath
|
||||
return JPath.Evaluate(pathFilters, root, t, false);
|
||||
}
|
||||
|
||||
return new JToken[0];
|
||||
return CollectionUtils.ArrayEmpty<JToken>();
|
||||
}
|
||||
|
||||
public override bool IsMatch(JToken root, JToken t)
|
||||
|
||||
@@ -2274,7 +2274,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id);
|
||||
}
|
||||
|
||||
newObject = objectContract.OverrideCreator(new object[0]);
|
||||
newObject = objectContract.OverrideCreator(CollectionUtils.ArrayEmpty<object>());
|
||||
}
|
||||
else if (objectContract.DefaultCreator != null &&
|
||||
(!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParameterizedCreator == null))
|
||||
|
||||
@@ -745,7 +745,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
|
||||
|
||||
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);
|
||||
SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty<int>());
|
||||
|
||||
if (hasWrittenMetadataObject)
|
||||
{
|
||||
|
||||
@@ -29,12 +29,16 @@ using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Globalization;
|
||||
#if !(NET20 || NET35 || NET40 || PORTABLE40)
|
||||
using System.Runtime.CompilerServices;
|
||||
#endif
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
@@ -340,9 +344,30 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
|
||||
Array multidimensionalArray = Array.CreateInstance(type, dimensions.ToArray());
|
||||
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, new int[0]);
|
||||
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, ArrayEmpty<int>());
|
||||
|
||||
return multidimensionalArray;
|
||||
}
|
||||
|
||||
// 4.6 has Array.Empty<T> to return a cached empty array. Lacking that in other
|
||||
// frameworks, Enumerable.Empty<T> happens to be implemented as a cached empty
|
||||
// array in all versions (in .NET Core the same instance as Array.Empty<T>).
|
||||
// This includes the internal Linq bridge for 2.0.
|
||||
// Since this method is simple and only 11 bytes long in a release build it's
|
||||
// pretty much guaranteed to be inlined, giving us fast access of that cached
|
||||
// array. With 4.5 and up we use AggressiveInlining just to be sure, so it's
|
||||
// effectively the same as calling Array.Empty<T> even when not available.
|
||||
#if !(NET20 || NET35 || NET40 || PORTABLE40)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#endif
|
||||
public static T[] ArrayEmpty<T>()
|
||||
{
|
||||
T[] array = Enumerable.Empty<T>() as T[];
|
||||
Debug.Assert(array != null);
|
||||
// Defensively guard against a version of Linq where Enumerable.Empty<T> doesn't
|
||||
// return an array, but throw in debug versions so a better strategy can be
|
||||
// used if that ever happens.
|
||||
return array ?? new T[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
public virtual IEnumerable<string> GetDynamicMemberNames(T instance)
|
||||
{
|
||||
return new string[0];
|
||||
return CollectionUtils.ArrayEmpty<string>();
|
||||
}
|
||||
|
||||
public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object result)
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
|
||||
|
||||
private static readonly Expression[] NoArgs = new Expression[0];
|
||||
private static Expression[] NoArgs => CollectionUtils.ArrayEmpty<Expression>();
|
||||
|
||||
private static Expression[] GetArgs(params DynamicMetaObject[] args)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty<DynamicMetaObject>());
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
@@ -87,40 +87,45 @@ namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
ParameterInfo[] parametersInfo = method.GetParameters();
|
||||
|
||||
Expression[] argsExpression = new Expression[parametersInfo.Length];
|
||||
IList<ByRefParameter> refParameterMap = new List<ByRefParameter>();
|
||||
|
||||
for (int i = 0; i < parametersInfo.Length; i++)
|
||||
Expression[] argsExpression;
|
||||
IList<ByRefParameter> refParameterMap;
|
||||
if (parametersInfo.Length == 0)
|
||||
{
|
||||
ParameterInfo parameter = parametersInfo[i];
|
||||
Type parameterType = parameter.ParameterType;
|
||||
bool isByRef = false;
|
||||
if (parameterType.IsByRef)
|
||||
argsExpression = CollectionUtils.ArrayEmpty<Expression>();
|
||||
refParameterMap = CollectionUtils.ArrayEmpty<ByRefParameter>();
|
||||
}
|
||||
else
|
||||
{
|
||||
argsExpression = new Expression[parametersInfo.Length];
|
||||
refParameterMap = new List<ByRefParameter>();
|
||||
|
||||
for (int i = 0; i < parametersInfo.Length; i++)
|
||||
{
|
||||
parameterType = parameterType.GetElementType();
|
||||
isByRef = true;
|
||||
}
|
||||
|
||||
Expression indexExpression = Expression.Constant(i);
|
||||
|
||||
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
|
||||
|
||||
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
|
||||
|
||||
if (isByRef)
|
||||
{
|
||||
ParameterExpression variable = Expression.Variable(parameterType);
|
||||
refParameterMap.Add(new ByRefParameter
|
||||
ParameterInfo parameter = parametersInfo[i];
|
||||
Type parameterType = parameter.ParameterType;
|
||||
bool isByRef = false;
|
||||
if (parameterType.IsByRef)
|
||||
{
|
||||
Value = argExpression,
|
||||
Variable = variable,
|
||||
IsOut = parameter.IsOut
|
||||
});
|
||||
parameterType = parameterType.GetElementType();
|
||||
isByRef = true;
|
||||
}
|
||||
|
||||
argExpression = variable;
|
||||
Expression indexExpression = Expression.Constant(i);
|
||||
|
||||
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
|
||||
|
||||
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
|
||||
|
||||
if (isByRef)
|
||||
{
|
||||
ParameterExpression variable = Expression.Variable(parameterType);
|
||||
refParameterMap.Add(new ByRefParameter {Value = argExpression, Variable = variable, IsOut = parameter.IsOut});
|
||||
|
||||
argExpression = variable;
|
||||
}
|
||||
|
||||
argsExpression[i] = argExpression;
|
||||
}
|
||||
|
||||
argsExpression[i] = argExpression;
|
||||
}
|
||||
|
||||
Expression callExpression;
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
EmptyTypes = Type.EmptyTypes;
|
||||
#else
|
||||
EmptyTypes = new Type[0];
|
||||
EmptyTypes = CollectionUtils.ArrayEmpty<Type>();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user