Commit 8d611a87 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[wasm-gc] Known-depth constant-time subtype checks

Previously, we performed "is A subtype of B?" checks by walking
A's supertypes list and comparing every found type to B.
This CL stores not just A's immediate parent type on A, but its
entire list of supertypes, and uses that list plus compile-time
knowledge of B's distance to the root type in order to compare
only exactly one of A's supertypes to B.

Bug: v8:7748
Change-Id: I0011b72c4b54440b16494918f64d8fb119bef8b0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2527097
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71127}
parent b90aa33e
......@@ -245,22 +245,6 @@ builtin WasmAllocateStructWithRtt(implicit context: Context)(rtt: Map):
return result;
}
builtin WasmIsRttSubtype(implicit context: Context)(sub: Map, super: Map): Smi {
let map = sub;
while (true) {
if (map == super) return SmiConstant(1); // "true"
// This code relies on the fact that we use a non-WasmObject map as the
// end of the chain, e.g. for "rtt any", which then doesn't have a
// WasmTypeInfo.
// TODO(7748): Use a more explicit sentinel mechanism?
const maybeTypeInfo = map.constructor_or_back_pointer_or_native_context;
if (!Is<WasmTypeInfo>(maybeTypeInfo)) return SmiConstant(0); // "false"
const typeInfo = %RawDownCast<WasmTypeInfo>(maybeTypeInfo);
map = typeInfo.parent;
}
unreachable;
}
// Redeclaration with different typing (value is an Object, not JSAny).
extern transitioning runtime
CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, Object);
......
This diff is collapsed.
......@@ -432,12 +432,12 @@ class WasmGraphBuilder {
Node* RttCanon(wasm::HeapType type);
Node* RttSub(wasm::HeapType type, Node* parent_rtt);
Node* RefTest(Node* object, Node* rtt, CheckForNull null_check,
CheckForI31 i31_check, RttIsI31 rtt_is_i31);
CheckForI31 i31_check, RttIsI31 rtt_is_i31, uint8_t depth);
Node* RefCast(Node* object, Node* rtt, CheckForNull null_check,
CheckForI31 i31_check, RttIsI31 rtt_is_i31,
CheckForI31 i31_check, RttIsI31 rtt_is_i31, uint8_t depth,
wasm::WasmCodePosition position);
Node* BrOnCast(Node* object, Node* rtt, CheckForNull null_check,
CheckForI31 i31_check, RttIsI31 rtt_is_i31,
CheckForI31 i31_check, RttIsI31 rtt_is_i31, uint8_t depth,
Node** match_control, Node** match_effect,
Node** no_match_control, Node** no_match_effect);
......
......@@ -1313,6 +1313,15 @@ Handle<Foreign> Factory::NewForeign(Address addr) {
Handle<WasmTypeInfo> Factory::NewWasmTypeInfo(Address type_address,
Handle<Map> parent) {
Handle<ArrayList> subtypes = ArrayList::New(isolate(), 0);
Handle<FixedArray> supertypes;
if (parent->IsWasmStructMap() || parent->IsWasmArrayMap()) {
supertypes = CopyFixedArrayAndGrow(
handle(parent->wasm_type_info().supertypes(), isolate()), 1);
supertypes->set(supertypes->length() - 1, *parent);
} else {
supertypes = NewUninitializedFixedArray(1);
supertypes->set(0, *parent);
}
Map map = *wasm_type_info_map();
HeapObject result = AllocateRawWithImmortalMap(map.instance_size(),
AllocationType::kYoung, map);
......@@ -1320,6 +1329,7 @@ Handle<WasmTypeInfo> Factory::NewWasmTypeInfo(Address type_address,
info->AllocateExternalPointerEntries(isolate());
info->set_foreign_address(isolate(), type_address);
info->set_parent(*parent);
info->set_supertypes(*supertypes);
info->set_subtypes(*subtypes);
return info;
}
......
......@@ -635,6 +635,7 @@ bool Heap::CreateInitialMaps() {
SKIP_WRITE_BARRIER); \
WasmTypeInfo type_info = WasmTypeInfo::cast(obj); \
type_info.set_subtypes(subtypes); \
type_info.set_supertypes(roots.empty_fixed_array()); \
type_info.set_parent(roots.null_map()); \
type_info.clear_foreign_address(isolate()); \
wasm_rttcanon_##which##_map().set_wasm_type_info(type_info); \
......
......@@ -588,6 +588,7 @@ class WasmTypeInfo::BodyDescriptor final : public BodyDescriptorBase {
Foreign::BodyDescriptor::IterateBody<ObjectVisitor>(map, obj, object_size,
v);
IteratePointer(obj, kParentOffset, v);
IteratePointer(obj, kSupertypesOffset, v);
IteratePointer(obj, kSubtypesOffset, v);
}
......
......@@ -806,8 +806,9 @@ class WasmGraphBuildingInterface {
RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
? RttIsI31::kRttIsI31
: RttIsI31::kRttIsNotI31;
uint8_t depth = rtt.type.depth();
result->node = BUILD(RefTest, object.node, rtt.node, null_check, i31_check,
rtt_is_i31);
rtt_is_i31, depth);
}
void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt,
......@@ -824,12 +825,13 @@ class WasmGraphBuildingInterface {
RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
? RttIsI31::kRttIsI31
: RttIsI31::kRttIsNotI31;
uint8_t depth = rtt.type.depth();
result->node = BUILD(RefCast, object.node, rtt.node, null_check, i31_check,
rtt_is_i31, decoder->position());
rtt_is_i31, depth, decoder->position());
}
void BrOnCast(FullDecoder* decoder, const Value& object, const Value& rtt,
Value* value_on_branch, uint32_t depth) {
Value* value_on_branch, uint32_t br_depth) {
using CheckForI31 = compiler::WasmGraphBuilder::CheckForI31;
using RttIsI31 = compiler::WasmGraphBuilder::RttIsI31;
CheckForNull null_check = object.type.is_nullable()
......@@ -842,16 +844,17 @@ class WasmGraphBuildingInterface {
RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
? RttIsI31::kRttIsI31
: RttIsI31::kRttIsNotI31;
uint8_t rtt_depth = rtt.type.depth();
SsaEnv* match_env = Split(decoder->zone(), ssa_env_);
SsaEnv* no_match_env = Steal(decoder->zone(), ssa_env_);
no_match_env->SetNotMerged();
BUILD(BrOnCast, object.node, rtt.node, null_check, i31_check, rtt_is_i31,
&match_env->control, &match_env->effect, &no_match_env->control,
&no_match_env->effect);
rtt_depth, &match_env->control, &match_env->effect,
&no_match_env->control, &no_match_env->effect);
builder_->SetControl(no_match_env->control);
SetEnv(match_env);
value_on_branch->node = object.node;
BrOrRet(decoder, depth);
BrOrRet(decoder, br_depth);
SetEnv(no_match_env);
}
......
......@@ -107,6 +107,7 @@ extern class AsmWasmData extends Struct {
@generateCppClass
extern class WasmTypeInfo extends Foreign {
parent: Map;
supertypes: FixedArray;
subtypes: ArrayList;
}
......
......@@ -427,49 +427,49 @@ KNOWN_OBJECTS = {
("old_space", 0x023bd): "RegExpResultIndicesAccessor",
("old_space", 0x02401): "StringLengthAccessor",
("old_space", 0x02445): "InvalidPrototypeValidityCell",
("old_space", 0x024cd): "EmptyScript",
("old_space", 0x0250d): "ManyClosuresCell",
("old_space", 0x02519): "ArrayConstructorProtector",
("old_space", 0x0252d): "NoElementsProtector",
("old_space", 0x02541): "IsConcatSpreadableProtector",
("old_space", 0x02555): "ArraySpeciesProtector",
("old_space", 0x02569): "TypedArraySpeciesProtector",
("old_space", 0x0257d): "PromiseSpeciesProtector",
("old_space", 0x02591): "RegExpSpeciesProtector",
("old_space", 0x025a5): "StringLengthProtector",
("old_space", 0x025b9): "ArrayIteratorProtector",
("old_space", 0x025cd): "ArrayBufferDetachingProtector",
("old_space", 0x025e1): "PromiseHookProtector",
("old_space", 0x025f5): "PromiseResolveProtector",
("old_space", 0x02609): "MapIteratorProtector",
("old_space", 0x0261d): "PromiseThenProtector",
("old_space", 0x02631): "SetIteratorProtector",
("old_space", 0x02645): "StringIteratorProtector",
("old_space", 0x02659): "SingleCharacterStringCache",
("old_space", 0x02a61): "StringSplitCache",
("old_space", 0x02e69): "RegExpMultipleCache",
("old_space", 0x03271): "BuiltinsConstantsTable",
("old_space", 0x03651): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x03679): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x036a1): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x036c9): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x036f1): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x03719): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x03741): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x03769): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x03791): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x037b9): "PromiseAllResolveElementSharedFun",
("old_space", 0x037e1): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x03809): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x03831): "PromiseAnyRejectElementSharedFun",
("old_space", 0x03859): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x03881): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x038a9): "PromiseCatchFinallySharedFun",
("old_space", 0x038d1): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x038f9): "PromiseThenFinallySharedFun",
("old_space", 0x03921): "PromiseThrowerFinallySharedFun",
("old_space", 0x03949): "PromiseValueThunkFinallySharedFun",
("old_space", 0x03971): "ProxyRevokeSharedFun",
("old_space", 0x024dd): "EmptyScript",
("old_space", 0x0251d): "ManyClosuresCell",
("old_space", 0x02529): "ArrayConstructorProtector",
("old_space", 0x0253d): "NoElementsProtector",
("old_space", 0x02551): "IsConcatSpreadableProtector",
("old_space", 0x02565): "ArraySpeciesProtector",
("old_space", 0x02579): "TypedArraySpeciesProtector",
("old_space", 0x0258d): "PromiseSpeciesProtector",
("old_space", 0x025a1): "RegExpSpeciesProtector",
("old_space", 0x025b5): "StringLengthProtector",
("old_space", 0x025c9): "ArrayIteratorProtector",
("old_space", 0x025dd): "ArrayBufferDetachingProtector",
("old_space", 0x025f1): "PromiseHookProtector",
("old_space", 0x02605): "PromiseResolveProtector",
("old_space", 0x02619): "MapIteratorProtector",
("old_space", 0x0262d): "PromiseThenProtector",
("old_space", 0x02641): "SetIteratorProtector",
("old_space", 0x02655): "StringIteratorProtector",
("old_space", 0x02669): "SingleCharacterStringCache",
("old_space", 0x02a71): "StringSplitCache",
("old_space", 0x02e79): "RegExpMultipleCache",
("old_space", 0x03281): "BuiltinsConstantsTable",
("old_space", 0x03661): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x03689): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x036b1): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x036d9): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x03701): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x03729): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x03751): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x03779): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x037a1): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x037c9): "PromiseAllResolveElementSharedFun",
("old_space", 0x037f1): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x03819): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x03841): "PromiseAnyRejectElementSharedFun",
("old_space", 0x03869): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x03891): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x038b9): "PromiseCatchFinallySharedFun",
("old_space", 0x038e1): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x03909): "PromiseThenFinallySharedFun",
("old_space", 0x03931): "PromiseThrowerFinallySharedFun",
("old_space", 0x03959): "PromiseValueThunkFinallySharedFun",
("old_space", 0x03981): "ProxyRevokeSharedFun",
}
# Lower 32 bits of first page addresses for various heap spaces.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment