[compiler] Reimplement AsElementsKind transition walk

MapRef::AsElementsKind can now concurrently walk transitions to find a
map of the requested elements kind.

Note this implementation is still less powerful than what we had before
crrev.com/c/3021175, since we never allocate new maps. When the
transition walk fails to find an appropriate map, we bail out.

I don't expect this to be a problem - when optimizing, the code has
already run multiple times and transitioned maps should exist.

Bug: v8:7790, v8:11988
Change-Id: Ic767b40c29bb86f7c4167097c76c5417985420fb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3086471
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76216}
This commit is contained in:
Jakob Gruber 2021-08-11 08:43:15 +02:00 committed by V8 LUCI CQ
parent 5612424a13
commit db8b90283a
3 changed files with 32 additions and 7 deletions

View File

@ -1816,17 +1816,29 @@ INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER
base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
// TODO(jgruber): Consider supporting transitions other than for JSArray
// initial maps (e.g. by walking transitions concurrently and finding an
// existing map that fits).
const ElementsKind current_kind = elements_kind();
if (kind == current_kind) return *this;
NativeContextRef native_context = broker()->target_native_context();
if (!equals(native_context.GetInitialJSArrayMap(current_kind))) return {};
base::Optional<Map> maybe_result = Map::TryAsElementsKind(
broker()->isolate(), object(), kind, ConcurrencyMode::kConcurrent);
return native_context.GetInitialJSArrayMap(kind);
#ifdef DEBUG
// If starting from an initial JSArray map, TryAsElementsKind must succeed
// and return the expected transitioned JSArray map.
NativeContextRef native_context = broker()->target_native_context();
if (equals(native_context.GetInitialJSArrayMap(current_kind))) {
CHECK_EQ(Map::TryAsElementsKind(broker()->isolate(), object(), kind,
ConcurrencyMode::kConcurrent)
.value(),
*native_context.GetInitialJSArrayMap(kind).object());
}
#endif // DEBUG
if (!maybe_result.has_value()) {
TRACE_BROKER_MISSING(broker(), "MapRef::AsElementsKind " << *this);
return {};
}
return MakeRefAssumeMemoryFence(broker(), maybe_result.value());
}
void MapRef::SerializeForElementStore(NotConcurrentInliningTag tag) {

View File

@ -1127,6 +1127,15 @@ static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
return current_map;
}
// static
base::Optional<Map> Map::TryAsElementsKind(Isolate* isolate, Handle<Map> map,
ElementsKind kind,
ConcurrencyMode cmode) {
Map closest_map = FindClosestElementsTransition(isolate, *map, kind, cmode);
if (closest_map.elements_kind() != kind) return {};
return closest_map;
}
// static
Handle<Map> Map::AsElementsKind(Isolate* isolate, Handle<Map> map,
ElementsKind kind) {

View File

@ -701,6 +701,10 @@ class Map : public TorqueGeneratedMap<Map, HeapObject> {
static Handle<Map> TransitionElementsTo(Isolate* isolate, Handle<Map> map,
ElementsKind to_kind);
static base::Optional<Map> TryAsElementsKind(Isolate* isolate,
Handle<Map> map,
ElementsKind kind,
ConcurrencyMode cmode);
V8_EXPORT_PRIVATE static Handle<Map> AsElementsKind(Isolate* isolate,
Handle<Map> map,
ElementsKind kind);