@@ -52,27 +52,16 @@ public static RuntimeHash createHash(RuntimeBase value) {
5252 * @return A new RuntimeHash populated with the elements from the list.
5353 */
5454 public static RuntimeHash createHashForAssignment (RuntimeBase value ) {
55- // Check for references in the list before creating the hash
56- boolean hasReference = false ;
55+ // Count elements to check for odd number
5756 int elementCount = 0 ;
5857 Iterator <RuntimeScalar > checkIterator = value .iterator ();
5958 while (checkIterator .hasNext ()) {
60- RuntimeScalar elem = checkIterator .next ();
61- if (elem .type == RuntimeScalarType .ARRAYREFERENCE ||
62- elem .type == RuntimeScalarType .HASHREFERENCE ||
63- elem .type == RuntimeScalarType .REFERENCE ) {
64- hasReference = true ;
65- }
59+ checkIterator .next ();
6660 elementCount ++;
6761 }
6862
69- // Warn about references or odd elements
70- if (hasReference ) {
71- org .perlonjava .operators .WarnDie .warn (
72- new RuntimeScalar ("Reference found where even-sized list expected" ),
73- RuntimeScalarCache .scalarEmptyString );
74- return createHashNoWarn (value );
75- } else if (elementCount % 2 != 0 ) {
63+ // Warn about odd elements (Perl does not warn about references in hash assignment)
64+ if (elementCount % 2 != 0 ) {
7665 return createHashInternal (value , "Odd number of elements in hash assignment" );
7766 } else {
7867 return createHashNoWarn (value );
@@ -194,17 +183,10 @@ public RuntimeArray setFromList(RuntimeList value) {
194183 case PLAIN_HASH -> {
195184 // Store the original list size for scalar context
196185 int originalSize = 0 ;
197- boolean hasReference = false ;
198186 for (RuntimeBase elem : value .elements ) {
199187 if (elem instanceof RuntimeArray ) {
200188 originalSize += ((RuntimeArray ) elem ).elements .size ();
201- } else if (elem instanceof RuntimeScalar scalar ) {
202- // Check if this is a reference (not a simple scalar)
203- if (scalar .type == RuntimeScalarType .ARRAYREFERENCE ||
204- scalar .type == RuntimeScalarType .HASHREFERENCE ||
205- scalar .type == RuntimeScalarType .REFERENCE ) {
206- hasReference = true ;
207- }
189+ } else if (elem instanceof RuntimeScalar ) {
208190 originalSize ++;
209191 } else {
210192 // Count elements by iterating
@@ -216,23 +198,26 @@ public RuntimeArray setFromList(RuntimeList value) {
216198 }
217199 }
218200
219- // Warn about references or odd elements
220- if (hasReference ) {
221- // If we have a reference, always warn about it
222- org .perlonjava .operators .WarnDie .warn (
223- new RuntimeScalar ("Reference found where even-sized list expected" ),
224- RuntimeScalarCache .scalarEmptyString );
225- } else if (originalSize % 2 != 0 ) {
226- // Only warn about odd elements if no reference
201+ // Warn about odd elements (Perl does not warn about references in hash assignment)
202+ if (originalSize % 2 != 0 ) {
227203 org .perlonjava .operators .WarnDie .warn (
228204 new RuntimeScalar ("Odd number of elements in hash assignment" ),
229205 RuntimeScalarCache .scalarEmptyString );
230206 }
231207
232- // Create a new hash from the provided list and replace our elements
233- // Use createHashNoWarn to avoid double warnings
234- RuntimeHash hash = createHashNoWarn (value );
235- this .elements = hash .elements ;
208+ // Clear existing elements but keep the same Map instance to preserve capacity
209+ this .elements .clear ();
210+
211+ // Populate the hash from the provided list
212+ // This reuses the existing StableHashMap and its capacity
213+ Iterator <RuntimeScalar > iter = value .iterator ();
214+ while (iter .hasNext ()) {
215+ RuntimeScalar key = iter .next ();
216+ if (iter .hasNext ()) {
217+ RuntimeScalar val = iter .hasNext () ? iter .next () : RuntimeScalarCache .scalarUndef ;
218+ this .elements .put (key .toString (), val );
219+ }
220+ }
236221
237222 // Create a RuntimeArray that wraps this hash
238223 // In list context: returns the deduplicated key-value pairs
@@ -574,6 +559,24 @@ public RuntimeArray keys() {
574559 return list ;
575560 }
576561
562+ /**
563+ * Preallocates hash bucket capacity.
564+ * This is called when Perl code does: keys %hash = $number
565+ *
566+ * @param capacity The requested capacity (number of elements to preallocate for)
567+ */
568+ public void preallocateCapacity (int capacity ) {
569+ if (this .type == AUTOVIVIFY_HASH ) {
570+ AutovivificationHash .vivify (this );
571+ }
572+
573+ // For PLAIN_HASH, set the minimum capacity in StableHashMap
574+ if (this .type == PLAIN_HASH && elements instanceof StableHashMap ) {
575+ ((StableHashMap <String , RuntimeScalar >) elements ).setMinimumCapacity (capacity );
576+ }
577+ // For TIED_HASH and other types, we can't really preallocate, so just ignore
578+ }
579+
577580 /**
578581 * The values() operator for hashes.
579582 *
@@ -730,7 +733,12 @@ public boolean getBooleanRef() {
730733 * @return The current RuntimeHash instance after undefining its elements.
731734 */
732735 public RuntimeHash undefine () {
733- this .elements .clear ();
736+ // For PLAIN_HASH, reset to a fresh StableHashMap with default capacity
737+ if (this .type == PLAIN_HASH ) {
738+ this .elements = new StableHashMap <>();
739+ } else {
740+ this .elements .clear ();
741+ }
734742 return this ;
735743 }
736744
0 commit comments