Skip to content

Commit c7834b6

Browse files
osa1Commit Queue
authored and
Commit Queue
committed
[dart2wasm] Fix array.new_fixed calls with too large size
Currently `array.new_fixed` has the upper size limit of 10,000. Larger arrays need to be initialized with `array.new` or `array.new_default`. We handle this correctly in constant list and strings, but we didn't handle it in `WasmArray.literal` consturctor. This CL fixes it. Fixes #55396. Change-Id: Icc79a3596c8ff544464a0142f3e0c9c63e39f63f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/361780 Commit-Queue: Ömer Ağacan <[email protected]> Reviewed-by: Slava Egorov <[email protected]>
1 parent 16a80cd commit c7834b6

File tree

2 files changed

+883
-4
lines changed

2 files changed

+883
-4
lines changed

pkg/dart2wasm/lib/constants.dart

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,17 +439,57 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?>
439439

440440
List<Constant> elements =
441441
(constant.fieldValues.values.single as ListConstant).entries;
442-
bool lazy = false;
442+
final tooLargeForArrayNewFixed = elements.length > maxArrayNewFixedLength;
443+
bool lazy = tooLargeForArrayNewFixed;
443444
for (Constant element in elements) {
444445
lazy |= ensureConstant(element)?.isLazy ?? false;
445446
}
446447

447448
return createConstant(constant, w.RefType.def(arrayType, nullable: false),
448449
lazy: lazy, (function, b) {
449-
for (Constant element in elements) {
450-
constants.instantiateConstant(function, b, element, elementType);
450+
if (tooLargeForArrayNewFixed) {
451+
// We will initialize the array with one of the elements (using
452+
// `array.new`) and update the fields.
453+
//
454+
// For the initial element pick the one that occurs the most to save
455+
// some work when the array has duplicates.
456+
final Map<Constant, int> occurrences = {};
457+
for (final element in elements) {
458+
occurrences.update(element, (i) => i + 1, ifAbsent: () => 1);
459+
}
460+
461+
var initialElement = elements[0];
462+
var initialElementOccurrences = 1;
463+
for (final entry in occurrences.entries) {
464+
if (entry.value > initialElementOccurrences) {
465+
initialElementOccurrences = entry.value;
466+
initialElement = entry.key;
467+
}
468+
}
469+
470+
w.Local arrayLocal =
471+
function!.addLocal(w.RefType.def(arrayType, nullable: false));
472+
constants.instantiateConstant(function, b, initialElement, elementType);
473+
b.i32_const(elements.length);
474+
b.array_new(arrayType);
475+
b.local_set(arrayLocal);
476+
for (int i = 0; i < elements.length; i++) {
477+
final element = elements[i];
478+
if (element == initialElement) {
479+
continue;
480+
}
481+
b.local_get(arrayLocal);
482+
b.i32_const(i);
483+
constants.instantiateConstant(function, b, element, elementType);
484+
b.array_set(arrayType);
485+
}
486+
b.local_get(arrayLocal);
487+
} else {
488+
for (Constant element in elements) {
489+
constants.instantiateConstant(function, b, element, elementType);
490+
}
491+
b.array_new_fixed(arrayType, elements.length);
451492
}
452-
b.array_new_fixed(arrayType, elements.length);
453493
});
454494
}
455495

0 commit comments

Comments
 (0)