[wasm-gc] Introduce minimum supertype length
We introduce a minimum length for the supertype array of gc maps. When the depth of the rtt is known to be smaller than that length, we can type check without bounds checking the supertype array of the object map. Bug: v8:7748, v8:11510 Change-Id: I88e67871040a8c4dd219e48a84527f7f3f3d0a96 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3312487 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#78280}
This commit is contained in:
parent
6114d09840
commit
dc01b43616
@ -5820,19 +5820,27 @@ void WasmGraphBuilder::TypeCheck(
|
||||
|
||||
DCHECK(config.reference_kind == kArrayOrStruct);
|
||||
|
||||
// First, check if types happen to be equal. This has been shown to give large
|
||||
// speedups.
|
||||
callbacks.succeed_if(gasm_->TaggedEqual(map, rtt), BranchHint::kTrue);
|
||||
|
||||
Node* type_info = gasm_->LoadWasmTypeInfo(map);
|
||||
Node* supertypes = gasm_->LoadSupertypes(type_info);
|
||||
Node* supertypes_length =
|
||||
BuildChangeSmiToIntPtr(gasm_->LoadFixedArrayLengthAsSmi(supertypes));
|
||||
Node* rtt_depth =
|
||||
config.rtt_depth >= 0
|
||||
? gasm_->IntPtrConstant(config.rtt_depth)
|
||||
: BuildChangeSmiToIntPtr(gasm_->LoadFixedArrayLengthAsSmi(
|
||||
gasm_->LoadSupertypes(gasm_->LoadWasmTypeInfo(rtt))));
|
||||
// If the depth of the rtt is known to be less that the minimum supertype
|
||||
// array length, we can access the supertype without bounds-checking the
|
||||
// supertype array.
|
||||
if (config.rtt_depth < 0 || static_cast<uint32_t>(config.rtt_depth) >=
|
||||
wasm::kMinimumSupertypeArraySize) {
|
||||
Node* supertypes_length =
|
||||
BuildChangeSmiToIntPtr(gasm_->LoadFixedArrayLengthAsSmi(supertypes));
|
||||
callbacks.fail_if_not(gasm_->UintLessThan(rtt_depth, supertypes_length),
|
||||
BranchHint::kTrue);
|
||||
}
|
||||
Node* maybe_match = gasm_->LoadFixedArrayElement(
|
||||
supertypes, rtt_depth, MachineType::TaggedPointer());
|
||||
|
||||
|
@ -1474,12 +1474,24 @@ Handle<WasmTypeInfo> Factory::NewWasmTypeInfo(
|
||||
Handle<ArrayList> subtypes = ArrayList::New(isolate(), 0);
|
||||
Handle<FixedArray> supertypes;
|
||||
if (opt_parent.is_null()) {
|
||||
supertypes = NewFixedArray(0);
|
||||
supertypes = NewFixedArray(wasm::kMinimumSupertypeArraySize);
|
||||
for (int i = 0; i < supertypes->length(); i++) {
|
||||
supertypes->set(i, *undefined_value());
|
||||
}
|
||||
} else {
|
||||
supertypes = CopyArrayAndGrow(
|
||||
handle(opt_parent->wasm_type_info().supertypes(), isolate()), 1,
|
||||
AllocationType::kOld);
|
||||
supertypes->set(supertypes->length() - 1, *opt_parent);
|
||||
Handle<FixedArray> parent_supertypes =
|
||||
handle(opt_parent->wasm_type_info().supertypes(), isolate());
|
||||
int last_defined_index = parent_supertypes->length() - 1;
|
||||
while (last_defined_index >= 0 &&
|
||||
parent_supertypes->get(last_defined_index).IsUndefined()) {
|
||||
last_defined_index--;
|
||||
}
|
||||
if (last_defined_index == parent_supertypes->length() - 1) {
|
||||
supertypes = CopyArrayAndGrow(parent_supertypes, 1, AllocationType::kOld);
|
||||
} else {
|
||||
supertypes = CopyFixedArray(parent_supertypes);
|
||||
}
|
||||
supertypes->set(last_defined_index + 1, *opt_parent);
|
||||
}
|
||||
Map map = *wasm_type_info_map();
|
||||
WasmTypeInfo result = WasmTypeInfo::cast(AllocateRawWithImmortalMap(
|
||||
@ -1487,7 +1499,7 @@ Handle<WasmTypeInfo> Factory::NewWasmTypeInfo(
|
||||
DisallowGarbageCollection no_gc;
|
||||
result.AllocateExternalPointerEntries(isolate());
|
||||
result.set_foreign_address(isolate(), type_address);
|
||||
result.set_supertypes(*supertypes, SKIP_WRITE_BARRIER);
|
||||
result.set_supertypes(*supertypes);
|
||||
result.set_subtypes(*subtypes);
|
||||
result.set_instance_size(instance_size_bytes);
|
||||
result.set_instance(*instance);
|
||||
|
@ -5475,12 +5475,14 @@ class LiftoffCompiler {
|
||||
wasm::ObjectAccess::ToTagged(WasmTypeInfo::kSupertypesOffset);
|
||||
__ LoadTaggedPointer(tmp1.gp(), tmp1.gp(), no_reg, kSuperTypesOffset,
|
||||
pinned);
|
||||
// Step 3: check the list's length.
|
||||
if (rtt.type.has_depth()) {
|
||||
// Step 3: check the list's length if needed.
|
||||
if (rtt.type.depth() >= kMinimumSupertypeArraySize) {
|
||||
LiftoffRegister list_length = tmp2;
|
||||
__ LoadFixedArrayLengthAsInt32(list_length, tmp1.gp(), pinned);
|
||||
if (rtt.type.has_depth()) {
|
||||
__ emit_i32_cond_jumpi(kUnsignedLessEqual, no_match, list_length.gp(),
|
||||
rtt.type.depth());
|
||||
}
|
||||
// Step 4: load the candidate list slot into {tmp1}, and compare it.
|
||||
__ LoadTaggedPointer(
|
||||
tmp1.gp(), tmp1.gp(), no_reg,
|
||||
@ -5489,6 +5491,9 @@ class LiftoffCompiler {
|
||||
__ emit_cond_jump(kUnequal, no_match, rtt.type.kind(), tmp1.gp(),
|
||||
rtt_reg.gp());
|
||||
} else {
|
||||
// Step 3: if rtt's depth is unknown, we invoke a builtin to compute the
|
||||
// result, as we might not have enough available registers.
|
||||
|
||||
// Preserve {obj_reg} across the call.
|
||||
LiftoffRegList saved_regs = LiftoffRegList::ForRegs(obj_reg);
|
||||
__ PushRegisters(saved_regs);
|
||||
|
@ -160,6 +160,10 @@ constexpr int kAnonymousFuncIndex = -1;
|
||||
// often enough.
|
||||
constexpr uint32_t kGenericWrapperBudget = 1000;
|
||||
|
||||
// The minimum length of supertype arrays for wasm-gc types. Having a size > 0
|
||||
// gives up some module size for faster access to the supertypes.
|
||||
constexpr uint32_t kMinimumSupertypeArraySize = 3;
|
||||
|
||||
#if V8_TARGET_ARCH_X64
|
||||
constexpr int32_t kOSRTargetOffset = 5 * kSystemPointerSize;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user