diff --git a/Jint/Native/JsProxy.cs b/Jint/Native/JsProxy.cs index 11010a180..da9896890 100644 --- a/Jint/Native/JsProxy.cs +++ b/Jint/Native/JsProxy.cs @@ -669,24 +669,54 @@ internal override bool SetPrototypeOf(JsValue value) return callable; } + // trap argument arrays are rented and returned after the call completes, following the + // interpreter call-site pattern (no finally: an exception lets the array fall to the GC, + // and JsArguments.Materialize protects arrays captured by the callee) + private JsValue CallTrap(ICallable trap, JsValue arg0) { - return trap.Call(_handler!, [arg0]); + var pool = _engine._jsValueArrayPool; + var args = pool.RentArray(1); + args[0] = arg0; + var result = trap.Call(_handler!, args); + pool.ReturnArray(args); + return result; } private JsValue CallTrap(ICallable trap, JsValue arg0, JsValue arg1) { - return trap.Call(_handler!, [arg0, arg1]); + var pool = _engine._jsValueArrayPool; + var args = pool.RentArray(2); + args[0] = arg0; + args[1] = arg1; + var result = trap.Call(_handler!, args); + pool.ReturnArray(args); + return result; } private JsValue CallTrap(ICallable trap, JsValue arg0, JsValue arg1, JsValue arg2) { - return trap.Call(_handler!, [arg0, arg1, arg2]); + var pool = _engine._jsValueArrayPool; + var args = pool.RentArray(3); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + var result = trap.Call(_handler!, args); + pool.ReturnArray(args); + return result; } private JsValue CallTrap(ICallable trap, JsValue arg0, JsValue arg1, JsValue arg2, JsValue arg3) { - return trap.Call(_handler!, [arg0, arg1, arg2, arg3]); + var pool = _engine._jsValueArrayPool; + var args = pool.RentArray(4); + args[0] = arg0; + args[1] = arg1; + args[2] = arg2; + args[3] = arg3; + var result = trap.Call(_handler!, args); + pool.ReturnArray(args); + return result; } private void AssertNotRevoked(JsValue key) diff --git a/Jint/Pooling/JsValueArrayPool.cs b/Jint/Pooling/JsValueArrayPool.cs index bd3b5ceee..4b7716390 100644 --- a/Jint/Pooling/JsValueArrayPool.cs +++ b/Jint/Pooling/JsValueArrayPool.cs @@ -12,12 +12,14 @@ internal sealed class JsValueArrayPool private readonly ObjectPool _poolArray1; private readonly ObjectPool _poolArray2; private readonly ObjectPool _poolArray3; + private readonly ObjectPool _poolArray4; public JsValueArrayPool() { _poolArray1 = new ObjectPool(Factory1, PoolSize); _poolArray2 = new ObjectPool(Factory2, PoolSize); _poolArray3 = new ObjectPool(Factory3, PoolSize); + _poolArray4 = new ObjectPool(Factory4, PoolSize); } private static JsValue[] Factory1() @@ -35,6 +37,11 @@ private static JsValue[] Factory3() return new JsValue[3]; } + private static JsValue[] Factory4() + { + return new JsValue[4]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public JsValue[] RentArray(int size) { @@ -54,6 +61,10 @@ public JsValue[] RentArray(int size) { return _poolArray3.Allocate(); } + if (size == 4) + { + return _poolArray4.Allocate(); + } return new JsValue[size]; } @@ -83,5 +94,13 @@ public void ReturnArray(JsValue[] array) array[2] = null!; _poolArray3.Free(array); } + else if (array.Length == 4) + { + array[0] = null!; + array[1] = null!; + array[2] = null!; + array[3] = null!; + _poolArray4.Free(array); + } } }