diff --git a/Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs b/Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs
index 020e6049d..2be32daff 100644
--- a/Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs
+++ b/Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs
@@ -79,7 +79,7 @@ public Completion ExecuteBlock(EvaluationContext context)
{
// Reuse environment: update outer reference and reset slots
cachedEnv._outerEnv = oldEnv;
- blockState.SlotTemplates.AsSpan().CopyTo(cachedEnv._slots);
+ ResetSlots(cachedEnv._slots!, blockState.SlotTemplates!);
blockEnv = cachedEnv;
}
else
@@ -244,6 +244,28 @@ protected override Completion ExecuteInternal(EvaluationContext context)
return ExecuteBlock(context);
}
+ ///
+ /// Reset the slots of a reused block environment to the pre-computed templates.
+ /// Hand-rolled small-array fast path: typical block scopes hold 1-3 bindings, where the
+ /// JIT can unroll this loop and avoid the Span construction + generic copy of CopyTo.
+ ///
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ private static void ResetSlots(Binding[] slots, Binding[] templates)
+ {
+ var len = slots.Length;
+ if (len == templates.Length && len <= 4)
+ {
+ for (var i = 0; i < len; i++)
+ {
+ slots[i] = templates[i];
+ }
+ }
+ else
+ {
+ templates.AsSpan().CopyTo(slots);
+ }
+ }
+
///
/// Pre-computed block scope state, cached on AST node UserData.
///