Skip to content

Commit

Permalink
Version 3.6.0-39.0.dev
Browse files Browse the repository at this point in the history
Merge 88b6ee2 into dev
  • Loading branch information
Dart CI committed Jul 13, 2024
2 parents 2bb9b70 + 88b6ee2 commit 8aa5483
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 78 deletions.
164 changes: 139 additions & 25 deletions pkg/dart2wasm/lib/code_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3958,45 +3958,159 @@ enum _VirtualCallKind {
extension MacroAssembler on w.InstructionsBuilder {
/// `[i32] -> [i32]`
///
/// Consumes an `i32` for a class ID, leaves an `i32` as `bool` for whether
/// Consumes a `i32` class ID, leaves an `i32` as `bool` for whether
/// the class ID is in the given list of ranges.
void emitClassIdRangeCheck(List<Range> ranges) {
if (ranges.isEmpty) {
drop();
final rangeValues = ranges.map((r) => (range: r, value: null)).toList();
classIdSearch<Null>(rangeValues, [w.NumType.i32], (_) {
i32_const(1);
}, () {
i32_const(0);
} else if (ranges.length == 1) {
final range = ranges[0];
});
}

i32_const(range.start);
if (range.length == 1) {
i32_eq();
} else {
i32_sub();
i32_const(range.length);
i32_lt_u();
/// `[i32] -> [outputs]`
///
/// Consumes a `i32` class ID and checks whether it lies within one of the
/// given [ranges] using a linear or binary search.
///
/// The [ranges] have to be non-empty, non-overlapping and sorted.
///
/// Calls [match] on a matching value and [miss] if provided and no match was
/// found.
///
/// Assumes [match] and [miss] leave [outputs] on the stack.
void classIdSearch<T>(
List<({Range range, T value})> ranges,
List<w.ValueType> outputs,
void Function(T) match,
void Function()? miss) {
final bool linearSearch = ranges.length <= 3;
if (traceEnabled) {
comment('Class id ${linearSearch ? 'linear' : 'binary'} search:');
for (final (:range, :value) in ranges) {
comment(' - $range -> $value');
}
}
if (linearSearch) {
_linearClassIdSearch<T>(ranges, outputs, match, miss);
} else {
w.Local idLocal = addLocal(w.NumType.i32, isParameter: false);
local_set(idLocal);
w.Label done = block(const [], const [w.NumType.i32]);
i32_const(1);
_binaryClassIdSearch<T>(ranges, outputs, match, miss);
}
}

void _binaryClassIdSearch<T>(
List<({Range range, T value})> ranges,
List<w.ValueType> outputs,
void Function(T) match,
void Function()? miss) {
assert(ranges.isNotEmpty || miss != null);
if (miss != null && ranges.isEmpty) {
drop();
miss();
return;
}

for (Range range in ranges) {
local_get(idLocal);
i32_const(range.start);
w.Local classId = addLocal(w.NumType.i32, isParameter: false);
local_set(classId);

final done = block([], outputs);
final fail = block();
void search(int left, int right, Range searchArea) {
if (left == right) {
final entry = ranges[left];
final range = entry.range;
assert(searchArea.containsRange(range));
if (miss == null || range.containsRange(searchArea)) {
match(entry.value);
br(done);
return;
}
local_get(classId);
if (range.length == 1) {
i32_const(range.start);
i32_eq();
} else {
i32_sub();
i32_const(range.length);
i32_lt_u();
if (searchArea.end <= range.end) {
i32_const(range.start);
i32_ge_u();
} else if (range.start <= searchArea.start) {
i32_const(range.end);
i32_le_u();
} else {
i32_const(range.start);
i32_sub();
i32_const(range.length);
i32_lt_u();
}
}
br_if(done);
if_();
match(entry.value);
br(done);
end();
br(fail);
return;
}
final mid = (left + right) ~/ 2;
final midRange = ranges[mid].range;

local_get(classId);
i32_const(midRange.end);
i32_le_u();
if_();
search(left, mid, Range(searchArea.start, midRange.end));
end();
search(mid + 1, right, Range(midRange.end + 1, searchArea.end));
}

search(0, ranges.length - 1, Range(0, 0xffffffff));
end(); // fail
if (miss != null) {
miss();
br(done);
} else {
unreachable();
}
end(); // done
}

void _linearClassIdSearch<T>(
List<({Range range, T value})> ranges,
List<w.ValueType> outputs,
void Function(T) match,
void Function()? miss) {
assert(ranges.isNotEmpty || miss != null);
if (miss != null && ranges.isEmpty) {
drop();
i32_const(0);
end(); // done
miss();
return;
}

w.Local classId = addLocal(w.NumType.i32, isParameter: false);
local_set(classId);
final done = block([], outputs);
for (final (:range, :value) in ranges) {
local_get(classId);
i32_const(range.start);
if (range.length == 1) {
i32_eq();
} else {
i32_sub();
i32_const(range.length);
i32_lt_u();
}
if_();
match(value);
br(done);
end();
}
if (miss != null) {
miss();
br(done);
} else {
unreachable();
}
end(); // done
}

/// `[ref _Closure] -> [i32]`
Expand Down
52 changes: 0 additions & 52 deletions sdk/lib/_internal/wasm/lib/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1026,58 +1026,6 @@ abstract class _TypeUniverse {
return (-1).toWasmI32();
}

static WasmI32 _searchSubs(WasmArray<WasmI32> table, WasmI32 key) {
for (WasmI32 i = 0.toWasmI32();
i < table.length.toWasmI32();
i += 3.toWasmI32()) {
final start = table[i.toIntSigned()];
final end = table[(i + 1.toWasmI32()).toIntSigned()];
if (start <= key && key <= end)
return table[(i + 2.toWasmI32()).toIntSigned()];
}
return (-1).toWasmI32();
}

static WasmI32 _searchSupers(WasmArray<WasmI32> table, WasmI32 key) {
final WasmI32 end = table.length.toWasmI32() >> 1.toWasmI32();
return (end < 8.toWasmI32())
? _linearSearch(table, end, key)
: _binarySearch(table, end, key);
}

@pragma('wasm:prefer-inline')
static WasmI32 _linearSearch(
WasmArray<WasmI32> table, WasmI32 end, WasmI32 key) {
for (WasmI32 i = 0.toWasmI32(); i < end; i += 1.toWasmI32()) {
if (table[i.toIntSigned()] == key) return end + i;
}
return (-1).toWasmI32();
}

@pragma('wasm:prefer-inline')
static WasmI32 _binarySearch(
WasmArray<WasmI32> table, WasmI32 end, WasmI32 key) {
WasmI32 lower = 0.toWasmI32();
WasmI32 upper = end - 1.toWasmI32();
while (lower <= upper) {
final WasmI32 mid = (lower + upper) >> 1.toWasmI32();
final WasmI32 entry = table[mid.toIntSigned()];
if (key < entry) {
upper = mid - 1.toWasmI32();
continue;
}
if (entry < key) {
lower = mid + 1.toWasmI32();
continue;
}
assert(entry == key);
assert(_linearSearch(table, end, key) == (end + mid));
return end + mid;
}
assert(_linearSearch(table, end, key) == (-1).toWasmI32());
return (-1).toWasmI32();
}

static bool isFunctionSubtype(_FunctionType s, _Environment? sEnv,
_FunctionType t, _Environment? tEnv) {
// Set up environments
Expand Down
2 changes: 1 addition & 1 deletion tools/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ CHANNEL dev
MAJOR 3
MINOR 6
PATCH 0
PRERELEASE 38
PRERELEASE 39
PRERELEASE_PATCH 0

0 comments on commit 8aa5483

Please sign in to comment.