Skip to content

Commit

Permalink
[dart2wasm] Fix array.new_fixed calls with too large size
Browse files Browse the repository at this point in the history
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 <omersa@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
  • Loading branch information
osa1 authored and Commit Queue committed Apr 10, 2024
1 parent 16a80cd commit c7834b6
Show file tree
Hide file tree
Showing 2 changed files with 883 additions and 4 deletions.
48 changes: 44 additions & 4 deletions pkg/dart2wasm/lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -439,17 +439,57 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?>

List<Constant> elements =
(constant.fieldValues.values.single as ListConstant).entries;
bool lazy = false;
final tooLargeForArrayNewFixed = elements.length > maxArrayNewFixedLength;
bool lazy = tooLargeForArrayNewFixed;
for (Constant element in elements) {
lazy |= ensureConstant(element)?.isLazy ?? false;
}

return createConstant(constant, w.RefType.def(arrayType, nullable: false),
lazy: lazy, (function, b) {
for (Constant element in elements) {
constants.instantiateConstant(function, b, element, elementType);
if (tooLargeForArrayNewFixed) {
// We will initialize the array with one of the elements (using
// `array.new`) and update the fields.
//
// For the initial element pick the one that occurs the most to save
// some work when the array has duplicates.
final Map<Constant, int> occurrences = {};
for (final element in elements) {
occurrences.update(element, (i) => i + 1, ifAbsent: () => 1);
}

var initialElement = elements[0];
var initialElementOccurrences = 1;
for (final entry in occurrences.entries) {
if (entry.value > initialElementOccurrences) {
initialElementOccurrences = entry.value;
initialElement = entry.key;
}
}

w.Local arrayLocal =
function!.addLocal(w.RefType.def(arrayType, nullable: false));
constants.instantiateConstant(function, b, initialElement, elementType);
b.i32_const(elements.length);
b.array_new(arrayType);
b.local_set(arrayLocal);
for (int i = 0; i < elements.length; i++) {
final element = elements[i];
if (element == initialElement) {
continue;
}
b.local_get(arrayLocal);
b.i32_const(i);
constants.instantiateConstant(function, b, element, elementType);
b.array_set(arrayType);
}
b.local_get(arrayLocal);
} else {
for (Constant element in elements) {
constants.instantiateConstant(function, b, element, elementType);
}
b.array_new_fixed(arrayType, elements.length);
}
b.array_new_fixed(arrayType, elements.length);
});
}

Expand Down
Loading

0 comments on commit c7834b6

Please sign in to comment.