Skip to content

Commit 3661fca

Browse files
Version 7.4.1: Performance improvements: .NET method arguments and property/field values are now passed pre-decoded, eliminating decoding hops; property, field, and constructor bind caching accelerates re-invocation. Further refined HeapExpansionMultiplier handling; miscellaneous NuGet package updates. Tested with V8 11.2.214.13.
1 parent 381b548 commit 3661fca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2197
-468
lines changed

ClearScript/Exports/VersionSymbols.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#pragma once
77

8-
#define CLEARSCRIPT_VERSION_STRING "7.4.0"
9-
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,0
10-
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.0"
8+
#define CLEARSCRIPT_VERSION_STRING "7.4.1"
9+
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 7,4,1
10+
#define CLEARSCRIPT_VERSION_STRING_INFORMATIONAL "7.4.1"
1111
#define CLEARSCRIPT_FILE_FLAGS 0L

ClearScript/HostItem.InvokeMethod.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args,
111111
var signature = new BindSignature(AccessContext, bindFlags, Target, name, typeArgs, bindArgs);
112112
MethodBindResult result;
113113

114-
if (Engine.TryGetCachedBindResult(signature, out var rawResult))
114+
if (Engine.TryGetCachedMethodBindResult(signature, out var rawResult))
115115
{
116116
result = MethodBindResult.Create(name, bindFlags, rawResult, Target, args);
117117
}
@@ -154,7 +154,7 @@ private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args,
154154
}
155155
}
156156

157-
Engine.CacheBindResult(signature, result.RawResult);
157+
Engine.CacheMethodBindResult(signature, result.RawResult);
158158
}
159159

160160
return result;
@@ -422,7 +422,7 @@ private IEnumerable<MethodInfo> GetReflectionCandidates(BindingFlags bindFlags,
422422

423423
#region unit test support
424424

425-
internal static void ResetCoreBindCache()
425+
internal static void ClearCoreBindCache()
426426
{
427427
coreBindCache.Clear();
428428
Interlocked.Exchange(ref coreBindCount, 0);

ClearScript/HostItem.cs

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[]
12351235
return DelegateFactory.CreateDelegate(Engine, args[0], specificType);
12361236
}
12371237

1238-
return specificType.CreateInstance(this, AccessContext, DefaultAccess, args, bindArgs);
1238+
return specificType.CreateInstance(this, Target, args, bindArgs);
12391239
}
12401240
}
12411241

@@ -1255,7 +1255,7 @@ private object InvokeHostMember(string name, BindingFlags invokeFlags, object[]
12551255
return DelegateFactory.CreateDelegate(Engine, args[0], type);
12561256
}
12571257

1258-
return type.CreateInstance(this, AccessContext, DefaultAccess, args, bindArgs);
1258+
return type.CreateInstance(this, Target, args, bindArgs);
12591259
}
12601260

12611261
if (TargetDynamicMetaObject != null)
@@ -1386,12 +1386,26 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
13861386
{
13871387
isCacheable = false;
13881388

1389+
var signature = new BindSignature(AccessContext, invokeFlags, Target, name, ArrayHelpers.GetEmptyArray<Type>(), bindArgs);
1390+
if (Engine.TryGetCachedPropertyGetBindResult(signature, out var boundMember))
1391+
{
1392+
if (boundMember is PropertyInfo boundProperty)
1393+
{
1394+
return GetHostPropertyWorker(boundProperty, boundProperty.GetMethod, args);
1395+
}
1396+
1397+
if (boundMember is FieldInfo boundField)
1398+
{
1399+
return GetHostFieldWorker(boundField, out isCacheable);
1400+
}
1401+
}
1402+
13891403
if (name == SpecialMemberNames.Default)
13901404
{
13911405
var defaultProperty = Target.Type.GetScriptableDefaultProperty(invokeFlags, args, bindArgs, AccessContext, DefaultAccess);
13921406
if (defaultProperty != null)
13931407
{
1394-
return GetHostProperty(defaultProperty, invokeFlags, args);
1408+
return GetHostProperty(signature, defaultProperty, invokeFlags, args);
13951409
}
13961410

13971411
if (TargetDynamicMetaObject != null)
@@ -1476,7 +1490,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
14761490
var property = Target.Type.GetScriptableProperty(name, invokeFlags, args, bindArgs, AccessContext, DefaultAccess);
14771491
if (property != null)
14781492
{
1479-
return GetHostProperty(property, invokeFlags, args);
1493+
return GetHostProperty(signature, property, invokeFlags, args);
14801494
}
14811495

14821496
if (args.Length > 0)
@@ -1494,9 +1508,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
14941508
var field = Target.Type.GetScriptableField(name, invokeFlags, AccessContext, DefaultAccess);
14951509
if (field != null)
14961510
{
1497-
var result = field.GetValue(Target.InvokeTarget);
1498-
isCacheable = (TargetDynamicMetaObject == null) && (field.IsLiteral || field.IsInitOnly);
1499-
return Engine.PrepareResult(result, field.FieldType, field.GetScriptMemberFlags(), false);
1511+
return GetHostField(signature, field, out isCacheable);
15001512
}
15011513

15021514
if (includeBoundMembers)
@@ -1539,7 +1551,7 @@ private object GetHostProperty(string name, BindingFlags invokeFlags, object[] a
15391551
return Nonexistent.Value;
15401552
}
15411553

1542-
private object GetHostProperty(PropertyInfo property, BindingFlags invokeFlags, object[] args)
1554+
private object GetHostProperty(BindSignature signature, PropertyInfo property, BindingFlags invokeFlags, object[] args)
15431555
{
15441556
if (reflectionProperties.Contains(property, MemberComparer<PropertyInfo>.Instance))
15451557
{
@@ -1569,11 +1581,46 @@ private object GetHostProperty(PropertyInfo property, BindingFlags invokeFlags,
15691581
throw new UnauthorizedAccessException("The property get method is unavailable or inaccessible");
15701582
}
15711583

1584+
var result = GetHostPropertyWorker(property, getMethod, args);
1585+
Engine.CachePropertyGetBindResult(signature, property);
1586+
return result;
1587+
}
1588+
1589+
private object GetHostPropertyWorker(PropertyInfo property, MethodInfo getMethod, object[] args)
1590+
{
15721591
return InvokeHelpers.InvokeMethod(this, getMethod, Target.InvokeTarget, args, property.GetScriptMemberFlags());
15731592
}
15741593

1594+
private object GetHostField(BindSignature signature, FieldInfo field, out bool isCacheable)
1595+
{
1596+
var result = GetHostFieldWorker(field, out isCacheable);
1597+
Engine.CachePropertyGetBindResult(signature, field);
1598+
return result;
1599+
}
1600+
1601+
private object GetHostFieldWorker(FieldInfo field, out bool isCacheable)
1602+
{
1603+
var result = field.GetValue(Target.InvokeTarget);
1604+
isCacheable = (TargetDynamicMetaObject == null) && (field.IsLiteral || field.IsInitOnly);
1605+
return Engine.PrepareResult(result, field.FieldType, field.GetScriptMemberFlags(), false);
1606+
}
1607+
15751608
private object SetHostProperty(string name, BindingFlags invokeFlags, object[] args, object[] bindArgs)
15761609
{
1610+
var signature = new BindSignature(AccessContext, invokeFlags, Target, name, ArrayHelpers.GetEmptyArray<Type>(), bindArgs);
1611+
if (Engine.TryGetCachedPropertySetBindResult(signature, out var boundMember))
1612+
{
1613+
if (boundMember is PropertyInfo boundProperty)
1614+
{
1615+
return SetHostPropertyWorker(boundProperty, boundProperty.SetMethod, args, bindArgs);
1616+
}
1617+
1618+
if (boundMember is FieldInfo boundField)
1619+
{
1620+
return SetHostFieldWorker(boundField, args);
1621+
}
1622+
}
1623+
15771624
if (name == SpecialMemberNames.Default)
15781625
{
15791626
if (args.Length < 1)
@@ -1586,7 +1633,7 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
15861633
var defaultProperty = Target.Type.GetScriptableDefaultProperty(invokeFlags, args.Take(args.Length - 1).ToArray(), bindArgs.Take(bindArgs.Length - 1).ToArray(), AccessContext, DefaultAccess);
15871634
if (defaultProperty != null)
15881635
{
1589-
return SetHostProperty(defaultProperty, args, bindArgs);
1636+
return SetHostProperty(signature, defaultProperty, args, bindArgs);
15901637
}
15911638

15921639
if (args.Length < 2)
@@ -1641,36 +1688,19 @@ private object SetHostProperty(string name, BindingFlags invokeFlags, object[] a
16411688
var property = Target.Type.GetScriptableProperty(name, invokeFlags, args.Take(args.Length - 1).ToArray(), bindArgs.Take(bindArgs.Length - 1).ToArray(), AccessContext, DefaultAccess);
16421689
if (property != null)
16431690
{
1644-
return SetHostProperty(property, args, bindArgs);
1691+
return SetHostProperty(signature, property, args, bindArgs);
16451692
}
16461693

16471694
var field = Target.Type.GetScriptableField(name, invokeFlags, AccessContext, DefaultAccess);
16481695
if (field != null)
16491696
{
1650-
if (args.Length == 1)
1651-
{
1652-
if (field.IsLiteral || field.IsInitOnly || field.IsReadOnlyForScript(DefaultAccess))
1653-
{
1654-
throw new UnauthorizedAccessException("The field is read-only");
1655-
}
1656-
1657-
var value = args[0];
1658-
if (field.FieldType.IsAssignableFromValue(ref value))
1659-
{
1660-
field.SetValue(Target.InvokeTarget, value);
1661-
return value;
1662-
}
1663-
1664-
throw new ArgumentException("Invalid field assignment");
1665-
}
1666-
1667-
throw new InvalidOperationException("Invalid argument count");
1697+
return SetHostField(signature, field, args);
16681698
}
16691699

16701700
throw new MissingMemberException(MiscHelpers.FormatInvariant("The object has no suitable property or field named '{0}'", name));
16711701
}
16721702

1673-
private object SetHostProperty(PropertyInfo property, object[] args, object[] bindArgs)
1703+
private object SetHostProperty(BindSignature signature, PropertyInfo property, object[] args, object[] bindArgs)
16741704
{
16751705
var scriptAccess = property.GetScriptAccess(DefaultAccess);
16761706
if (scriptAccess == ScriptAccess.ReadOnly)
@@ -1684,6 +1714,13 @@ private object SetHostProperty(PropertyInfo property, object[] args, object[] bi
16841714
throw new UnauthorizedAccessException("The property set method is unavailable or inaccessible");
16851715
}
16861716

1717+
var result = SetHostPropertyWorker(property, setMethod, args, bindArgs);
1718+
Engine.CachePropertySetBindResult(signature, property);
1719+
return result;
1720+
}
1721+
1722+
private object SetHostPropertyWorker(PropertyInfo property, MethodInfo setMethod, object[] args, object[] bindArgs)
1723+
{
16871724
var value = args[args.Length - 1];
16881725

16891726
var argCount = args.Length - 1;
@@ -1741,6 +1778,35 @@ private object SetHostProperty(PropertyInfo property, object[] args, object[] bi
17411778
throw new ArgumentException("Invalid property assignment");
17421779
}
17431780

1781+
private object SetHostField(BindSignature signature, FieldInfo field, object[] args)
1782+
{
1783+
if (args.Length != 1)
1784+
{
1785+
throw new InvalidOperationException("Invalid argument count");
1786+
}
1787+
1788+
if (field.IsLiteral || field.IsInitOnly || field.IsReadOnlyForScript(DefaultAccess))
1789+
{
1790+
throw new UnauthorizedAccessException("The field is read-only");
1791+
}
1792+
1793+
var result = SetHostFieldWorker(field, args);
1794+
Engine.CachePropertySetBindResult(signature, field);
1795+
return result;
1796+
}
1797+
1798+
private object SetHostFieldWorker(FieldInfo field, object[] args)
1799+
{
1800+
var value = args[0];
1801+
if (field.FieldType.IsAssignableFromValue(ref value))
1802+
{
1803+
field.SetValue(Target.InvokeTarget, value);
1804+
return value;
1805+
}
1806+
1807+
throw new ArgumentException("Invalid field assignment");
1808+
}
1809+
17441810
private static object CreateScriptableEnumerator<T>(IEnumerable<T> enumerable)
17451811
{
17461812
return HostObject.Wrap(new ScriptableEnumeratorOnEnumerator<T>(enumerable.GetEnumerator()), typeof(IScriptableEnumerator<T>));

ClearScript/HostObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public override Invocability GetInvocability(BindingFlags bindFlags, Type access
149149

150150
private static class NullWrapper<T>
151151
{
152-
public static HostObject Value { get; } = new HostObject(null, typeof(T));
152+
public static readonly HostObject Value = new HostObject(null, typeof(T));
153153
}
154154

155155
// ReSharper restore UnusedMember.Local

ClearScript/HostSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ public static CustomAttributeLoader CustomAttributeLoader
5151
}
5252
}
5353

54-
internal static CustomAttributeLoader DefaultCustomAttributeLoader { get; } = new CustomAttributeLoader();
54+
internal static readonly CustomAttributeLoader DefaultCustomAttributeLoader = new CustomAttributeLoader();
5555
}
5656
}

ClearScript/Properties/AssemblyInfo.Core.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
[assembly: InternalsVisibleTo("ClearScriptTest")]
1919

2020
[assembly: ComVisible(false)]
21-
[assembly: AssemblyVersion("7.4.0")]
22-
[assembly: AssemblyFileVersion("7.4.0")]
23-
[assembly: AssemblyInformationalVersion("7.4.0")]
21+
[assembly: AssemblyVersion("7.4.1")]
22+
[assembly: AssemblyFileVersion("7.4.1")]
23+
[assembly: AssemblyInformationalVersion("7.4.1")]
2424

2525
namespace Microsoft.ClearScript.Properties
2626
{
2727
internal static class ClearScriptVersion
2828
{
29-
public const string Triad = "7.4.0";
30-
public const string Informational = "7.4.0";
29+
public const string Triad = "7.4.1";
30+
public const string Informational = "7.4.1";
3131
}
3232
}

ClearScript/Properties/AssemblyInfo.V8.ICUData.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
[assembly: InternalsVisibleTo("ClearScript.V8")]
1616

1717
[assembly: ComVisible(false)]
18-
[assembly: AssemblyVersion("7.4.0")]
19-
[assembly: AssemblyFileVersion("7.4.0")]
20-
[assembly: AssemblyInformationalVersion("7.4.0")]
18+
[assembly: AssemblyVersion("7.4.1")]
19+
[assembly: AssemblyFileVersion("7.4.1")]
20+
[assembly: AssemblyInformationalVersion("7.4.1")]

ClearScript/Properties/AssemblyInfo.V8.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
[assembly: InternalsVisibleTo("ClearScriptTest")]
1616

1717
[assembly: ComVisible(false)]
18-
[assembly: AssemblyVersion("7.4.0")]
19-
[assembly: AssemblyFileVersion("7.4.0")]
20-
[assembly: AssemblyInformationalVersion("7.4.0")]
18+
[assembly: AssemblyVersion("7.4.1")]
19+
[assembly: AssemblyFileVersion("7.4.1")]
20+
[assembly: AssemblyInformationalVersion("7.4.1")]

ClearScript/Properties/AssemblyInfo.Windows.Core.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
[assembly: InternalsVisibleTo("ClearScriptTest")]
1717

1818
[assembly: ComVisible(false)]
19-
[assembly: AssemblyVersion("7.4.0")]
20-
[assembly: AssemblyFileVersion("7.4.0")]
21-
[assembly: AssemblyInformationalVersion("7.4.0")]
19+
[assembly: AssemblyVersion("7.4.1")]
20+
[assembly: AssemblyFileVersion("7.4.1")]
21+
[assembly: AssemblyInformationalVersion("7.4.1")]

ClearScript/Properties/AssemblyInfo.Windows.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
[assembly: InternalsVisibleTo("ClearScriptTest")]
1616

1717
[assembly: ComVisible(false)]
18-
[assembly: AssemblyVersion("7.4.0")]
19-
[assembly: AssemblyFileVersion("7.4.0")]
20-
[assembly: AssemblyInformationalVersion("7.4.0")]
18+
[assembly: AssemblyVersion("7.4.1")]
19+
[assembly: AssemblyFileVersion("7.4.1")]
20+
[assembly: AssemblyInformationalVersion("7.4.1")]

0 commit comments

Comments
 (0)