[wasm-gc][liftoff] Optimize final-type checks

This is a follow-up to crrev.com/c/v8/v8/+/4096478. Similarly to
Turbofan, we reduce type-checks for final types in Liftoff to type
identity.

Bug: v8:7748
Change-Id: I095880a7718bd2d675dd119f1f14869c97d641b7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4128522
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85135}
This commit is contained in:
Manos Koukoutos 2023-01-02 13:01:40 +01:00 committed by V8 LUCI CQ
parent 521a399d35
commit 0ab8a7a111

View File

@ -5943,44 +5943,50 @@ class LiftoffCompiler {
__ LoadMap(tmp1, obj_reg); __ LoadMap(tmp1, obj_reg);
// {tmp1} now holds the object's map. // {tmp1} now holds the object's map.
// Check for rtt equality, and if not, check if the rtt is a struct/array if (module->types[rtt_type.ref_index()].is_final) {
// rtt. // In this case, simply check for map equality.
__ emit_cond_jump(kEqual, &match, rtt_type.kind(), tmp1, rtt_reg, frozen); __ emit_cond_jump(kUnequal, no_match, rtt_type.kind(), tmp1, rtt_reg,
frozen);
} else {
// Check for rtt equality, and if not, check if the rtt is a struct/array
// rtt.
__ emit_cond_jump(kEqual, &match, rtt_type.kind(), tmp1, rtt_reg, frozen);
if (is_cast_from_any) { if (is_cast_from_any) {
// Check for map being a map for a wasm object (struct, array, func). // Check for map being a map for a wasm object (struct, array, func).
__ Load(LiftoffRegister(scratch2), tmp1, no_reg, __ Load(LiftoffRegister(scratch2), tmp1, no_reg,
wasm::ObjectAccess::ToTagged(Map::kInstanceTypeOffset), wasm::ObjectAccess::ToTagged(Map::kInstanceTypeOffset),
LoadType::kI32Load16U); LoadType::kI32Load16U);
__ emit_i32_subi(scratch2, scratch2, FIRST_WASM_OBJECT_TYPE); __ emit_i32_subi(scratch2, scratch2, FIRST_WASM_OBJECT_TYPE);
__ emit_i32_cond_jumpi(kUnsignedGreaterThan, no_match, scratch2, __ emit_i32_cond_jumpi(kUnsignedGreaterThan, no_match, scratch2,
LAST_WASM_OBJECT_TYPE - FIRST_WASM_OBJECT_TYPE, LAST_WASM_OBJECT_TYPE - FIRST_WASM_OBJECT_TYPE,
frozen); frozen);
} }
// Constant-time subtyping check: load exactly one candidate RTT from the // Constant-time subtyping check: load exactly one candidate RTT from the
// supertypes list. // supertypes list.
// Step 1: load the WasmTypeInfo into {tmp1}. // Step 1: load the WasmTypeInfo into {tmp1}.
constexpr int kTypeInfoOffset = wasm::ObjectAccess::ToTagged( constexpr int kTypeInfoOffset = wasm::ObjectAccess::ToTagged(
Map::kConstructorOrBackPointerOrNativeContextOffset); Map::kConstructorOrBackPointerOrNativeContextOffset);
__ LoadTaggedPointer(tmp1, tmp1, no_reg, kTypeInfoOffset); __ LoadTaggedPointer(tmp1, tmp1, no_reg, kTypeInfoOffset);
// Step 2: check the list's length if needed. // Step 2: check the list's length if needed.
uint32_t rtt_depth = GetSubtypingDepth(module, rtt_type.ref_index()); uint32_t rtt_depth = GetSubtypingDepth(module, rtt_type.ref_index());
if (rtt_depth >= kMinimumSupertypeArraySize) { if (rtt_depth >= kMinimumSupertypeArraySize) {
LiftoffRegister list_length(scratch2); LiftoffRegister list_length(scratch2);
int offset = int offset =
ObjectAccess::ToTagged(WasmTypeInfo::kSupertypesLengthOffset); ObjectAccess::ToTagged(WasmTypeInfo::kSupertypesLengthOffset);
__ LoadSmiAsInt32(list_length, tmp1, offset); __ LoadSmiAsInt32(list_length, tmp1, offset);
__ emit_i32_cond_jumpi(kUnsignedLessEqual, no_match, list_length.gp(), __ emit_i32_cond_jumpi(kUnsignedLessEqual, no_match, list_length.gp(),
rtt_depth, frozen); rtt_depth, frozen);
}
// Step 3: load the candidate list slot into {tmp1}, and compare it.
__ LoadTaggedPointer(
tmp1, tmp1, no_reg,
ObjectAccess::ToTagged(WasmTypeInfo::kSupertypesOffset +
rtt_depth * kTaggedSize));
__ emit_cond_jump(kUnequal, no_match, rtt_type.kind(), tmp1, rtt_reg,
frozen);
} }
// Step 3: load the candidate list slot into {tmp1}, and compare it.
__ LoadTaggedPointer(
tmp1, tmp1, no_reg,
ObjectAccess::ToTagged(WasmTypeInfo::kSupertypesOffset +
rtt_depth * kTaggedSize));
__ emit_cond_jump(kUnequal, no_match, rtt_type.kind(), tmp1, rtt_reg,
frozen);
// Fall through to {match}. // Fall through to {match}.
__ bind(&match); __ bind(&match);