Commit 7f9b2fa6 authored by ishell's avatar ishell Committed by Commit bot

Do not generalize field representations when making elements kind or observed transition.

BUG=chromium:448711
LOG=y

Review URL: https://codereview.chromium.org/861173004

Cr-Commit-Position: refs/heads/master@{#26289}
parent d93c4d19
...@@ -3300,19 +3300,21 @@ static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, ...@@ -3300,19 +3300,21 @@ static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
Handle<Map> current_map = map; Handle<Map> current_map = map;
ElementsKind kind = map->elements_kind(); ElementsKind kind = map->elements_kind();
if (!map->is_prototype_map()) { TransitionFlag flag;
if (map->is_prototype_map()) {
flag = OMIT_TRANSITION;
} else {
flag = INSERT_TRANSITION;
while (kind != to_kind && !IsTerminalElementsKind(kind)) { while (kind != to_kind && !IsTerminalElementsKind(kind)) {
kind = GetNextTransitionElementsKind(kind); kind = GetNextTransitionElementsKind(kind);
current_map = current_map = Map::CopyAsElementsKind(current_map, kind, flag);
Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION);
} }
} }
// In case we are exiting the fast elements kind system, just add the map in // In case we are exiting the fast elements kind system, just add the map in
// the end. // the end.
if (kind != to_kind) { if (kind != to_kind) {
current_map = Map::CopyAsElementsKind( current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
current_map, to_kind, INSERT_TRANSITION);
} }
DCHECK(current_map->elements_kind() == to_kind); DCHECK(current_map->elements_kind() == to_kind);
...@@ -6805,31 +6807,18 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, ...@@ -6805,31 +6807,18 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
map->CanHaveMoreTransitions() && map->CanHaveMoreTransitions() &&
!map->HasElementsTransition(); !map->HasElementsTransition();
if (insert_transition && map->owns_descriptors()) { if (insert_transition) {
// In case the map owned its own descriptors, share the descriptors and Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
// transfer ownership to the new map. new_map->set_elements_kind(kind);
Handle<Map> new_map = CopyDropDescriptors(map);
ConnectElementsTransition(map, new_map); ConnectElementsTransition(map, new_map);
new_map->set_elements_kind(kind);
// The properties did not change, so reuse descriptors.
new_map->InitializeDescriptors(map->instance_descriptors(),
map->GetLayoutDescriptor());
return new_map; return new_map;
} }
// In case the map did not own its own descriptors, a split is forced by
// copying the map; creating a new descriptor array cell.
// Create a new free-floating map only if we are not allowed to store it. // Create a new free-floating map only if we are not allowed to store it.
Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
new_map->set_elements_kind(kind); new_map->set_elements_kind(kind);
if (insert_transition) {
ConnectElementsTransition(map, new_map);
}
return new_map; return new_map;
} }
...@@ -6839,27 +6828,55 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) { ...@@ -6839,27 +6828,55 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) {
Isolate* isolate = map->GetIsolate(); Isolate* isolate = map->GetIsolate();
// In case the map owned its own descriptors, share the descriptors and bool insert_transition =
// transfer ownership to the new map. map->CanHaveMoreTransitions() && !map->is_prototype_map();
Handle<Map> new_map;
if (map->owns_descriptors()) { if (insert_transition) {
new_map = CopyDropDescriptors(map); Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
} else { new_map->set_is_observed();
DCHECK(!map->is_prototype_map());
new_map = Copy(map, "CopyForObserved"); Handle<Name> name = isolate->factory()->observed_symbol();
ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
return new_map;
} }
// Create a new free-floating map only if we are not allowed to store it.
Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
new_map->set_is_observed(); new_map->set_is_observed();
return new_map;
}
Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
DCHECK(!map->is_prototype_map());
Handle<Map> new_map = CopyDropDescriptors(map);
if (map->owns_descriptors()) { if (map->owns_descriptors()) {
// In case the map owned its own descriptors, share the descriptors and
// transfer ownership to the new map.
// The properties did not change, so reuse descriptors. // The properties did not change, so reuse descriptors.
new_map->InitializeDescriptors(map->instance_descriptors(), new_map->InitializeDescriptors(map->instance_descriptors(),
map->GetLayoutDescriptor()); map->GetLayoutDescriptor());
} else {
// In case the map did not own its own descriptors, a split is forced by
// copying the map; creating a new descriptor array cell.
Handle<DescriptorArray> descriptors(map->instance_descriptors());
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
Handle<DescriptorArray> new_descriptors =
DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
map->GetIsolate());
new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
} }
if (map->CanHaveMoreTransitions()) { #if TRACE_MAPS
Handle<Name> name = isolate->factory()->observed_symbol(); if (FLAG_trace_maps) {
ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
reason);
} }
#endif
return new_map; return new_map;
} }
......
...@@ -6141,6 +6141,11 @@ class Map: public HeapObject { ...@@ -6141,6 +6141,11 @@ class Map: public HeapObject {
inline void AppendDescriptor(Descriptor* desc); inline void AppendDescriptor(Descriptor* desc);
// Returns a copy of the map, prepared for inserting into the transition
// tree (if the |map| owns descriptors then the new one will share
// descriptors with |map|).
static Handle<Map> CopyForTransition(Handle<Map> map, const char* reason);
// Returns a copy of the map, with all transitions dropped from the // Returns a copy of the map, with all transitions dropped from the
// instance descriptors. // instance descriptors.
static Handle<Map> Copy(Handle<Map> map, const char* reason); static Handle<Map> Copy(Handle<Map> map, const char* reason);
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
function f() {
this.a = { text: "Hello!" };
}
var v4 = new f();
var v7 = new f();
v7.b = {};
Object.defineProperty(v4, '2', {});
var v6 = new f();
v6.a = {};
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