Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: src/objects.cc

Issue 768633002: Add infrastructure to keep track of references to prototypes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: use WeakCellForMap() when appropriate Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <sstream> 5 #include <sstream>
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/allocation-site-scopes.h" 10 #include "src/allocation-site-scopes.h"
(...skipping 3067 matching lines...) Expand 10 before | Expand all | Expand 10 after
3078 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot 3078 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3079 // have own properties. 3079 // have own properties.
3080 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 3080 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3081 3081
3082 // Store on the holder which may be hidden behind the receiver. 3082 // Store on the holder which may be hidden behind the receiver.
3083 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); 3083 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3084 3084
3085 // Old value for the observation change record. 3085 // Old value for the observation change record.
3086 // Fetch before transforming the object since the encoding may become 3086 // Fetch before transforming the object since the encoding may become
3087 // incompatible with what's cached in |it|. 3087 // incompatible with what's cached in |it|.
3088 bool is_observed = 3088 bool is_observed = receiver->map()->is_observed() &&
3089 receiver->map()->is_observed() && 3089 !it->isolate()->IsInternallyUsedPropertyName(it->name());
3090 !it->name().is_identical_to(it->factory()->hidden_string());
3091 MaybeHandle<Object> maybe_old; 3090 MaybeHandle<Object> maybe_old;
3092 if (is_observed) maybe_old = it->GetDataValue(); 3091 if (is_observed) maybe_old = it->GetDataValue();
3093 3092
3094 // Possibly migrate to the most up-to-date map that will be able to store 3093 // Possibly migrate to the most up-to-date map that will be able to store
3095 // |value| under it->name(). 3094 // |value| under it->name().
3096 it->PrepareForDataProperty(value); 3095 it->PrepareForDataProperty(value);
3097 3096
3098 // Write the property value. 3097 // Write the property value.
3099 value = it->WriteDataValue(value); 3098 value = it->WriteDataValue(value);
3100 3099
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3150 // TODO(verwaest): Probably should ensure this is done beforehand. 3149 // TODO(verwaest): Probably should ensure this is done beforehand.
3151 it->InternalizeName(); 3150 it->InternalizeName();
3152 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); 3151 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3153 } else { 3152 } else {
3154 // Write the property value. 3153 // Write the property value.
3155 value = it->WriteDataValue(value); 3154 value = it->WriteDataValue(value);
3156 } 3155 }
3157 3156
3158 // Send the change record if there are observers. 3157 // Send the change record if there are observers.
3159 if (receiver->map()->is_observed() && 3158 if (receiver->map()->is_observed() &&
3160 !it->name().is_identical_to(it->factory()->hidden_string())) { 3159 !it->isolate()->IsInternallyUsedPropertyName(it->name())) {
3161 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( 3160 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3162 receiver, "add", it->name(), 3161 receiver, "add", it->name(),
3163 it->factory()->the_hole_value()), 3162 it->factory()->the_hole_value()),
3164 Object); 3163 Object);
3165 } 3164 }
3166 3165
3167 return value; 3166 return value;
3168 } 3167 }
3169 3168
3170 3169
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
3954 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 3953 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3955 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); 3954 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
3956 #ifdef DEBUG 3955 #ifdef DEBUG
3957 uint32_t index; 3956 uint32_t index;
3958 DCHECK(!object->IsJSProxy()); 3957 DCHECK(!object->IsJSProxy());
3959 DCHECK(!name->AsArrayIndex(&index)); 3958 DCHECK(!name->AsArrayIndex(&index));
3960 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 3959 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
3961 DCHECK(maybe.has_value); 3960 DCHECK(maybe.has_value);
3962 DCHECK(!it.IsFound()); 3961 DCHECK(!it.IsFound());
3963 DCHECK(object->map()->is_extensible() || 3962 DCHECK(object->map()->is_extensible() ||
3964 name.is_identical_to(it.isolate()->factory()->hidden_string())); 3963 it.isolate()->IsInternallyUsedPropertyName(name));
3965 #endif 3964 #endif
3966 AddDataProperty(&it, value, attributes, STRICT, 3965 AddDataProperty(&it, value, attributes, STRICT,
3967 CERTAINLY_NOT_STORE_FROM_KEYED).Check(); 3966 CERTAINLY_NOT_STORE_FROM_KEYED).Check();
3968 } 3967 }
3969 3968
3970 3969
3971 // Reconfigures a property to a data property with attributes, even if it is not 3970 // Reconfigures a property to a data property with attributes, even if it is not
3972 // reconfigurable. 3971 // reconfigurable.
3973 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 3972 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
3974 Handle<JSObject> object, 3973 Handle<JSObject> object,
3975 Handle<Name> name, 3974 Handle<Name> name,
3976 Handle<Object> value, 3975 Handle<Object> value,
3977 PropertyAttributes attributes, 3976 PropertyAttributes attributes,
3978 ExecutableAccessorInfoHandling handling) { 3977 ExecutableAccessorInfoHandling handling) {
3979 DCHECK(!value->IsTheHole()); 3978 DCHECK(!value->IsTheHole());
3980 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 3979 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3981 bool is_observed = object->map()->is_observed() && 3980 bool is_observed = object->map()->is_observed() &&
3982 *name != it.isolate()->heap()->hidden_string(); 3981 !it.isolate()->IsInternallyUsedPropertyName(name);
3983 for (; it.IsFound(); it.Next()) { 3982 for (; it.IsFound(); it.Next()) {
3984 switch (it.state()) { 3983 switch (it.state()) {
3985 case LookupIterator::INTERCEPTOR: 3984 case LookupIterator::INTERCEPTOR:
3986 case LookupIterator::JSPROXY: 3985 case LookupIterator::JSPROXY:
3987 case LookupIterator::NOT_FOUND: 3986 case LookupIterator::NOT_FOUND:
3988 case LookupIterator::TRANSITION: 3987 case LookupIterator::TRANSITION:
3989 UNREACHABLE(); 3988 UNREACHABLE();
3990 3989
3991 case LookupIterator::ACCESS_CHECK: 3990 case LookupIterator::ACCESS_CHECK:
3992 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { 3991 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after
5102 } 5101 }
5103 5102
5104 // Skip interceptors on FORCE_DELETION. 5103 // Skip interceptors on FORCE_DELETION.
5105 LookupIterator::Configuration config = 5104 LookupIterator::Configuration config =
5106 delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR 5105 delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR
5107 : LookupIterator::HIDDEN; 5106 : LookupIterator::HIDDEN;
5108 5107
5109 LookupIterator it(object, name, config); 5108 LookupIterator it(object, name, config);
5110 5109
5111 bool is_observed = object->map()->is_observed() && 5110 bool is_observed = object->map()->is_observed() &&
5112 *name != it.isolate()->heap()->hidden_string(); 5111 !it.isolate()->IsInternallyUsedPropertyName(name);
5113 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); 5112 Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
5114 5113
5115 for (; it.IsFound(); it.Next()) { 5114 for (; it.IsFound(); it.Next()) {
5116 switch (it.state()) { 5115 switch (it.state()) {
5117 case LookupIterator::JSPROXY: 5116 case LookupIterator::JSPROXY:
5118 case LookupIterator::NOT_FOUND: 5117 case LookupIterator::NOT_FOUND:
5119 case LookupIterator::TRANSITION: 5118 case LookupIterator::TRANSITION:
5120 UNREACHABLE(); 5119 UNREACHABLE();
5121 case LookupIterator::ACCESS_CHECK: 5120 case LookupIterator::ACCESS_CHECK:
5122 if (it.HasAccess(v8::ACCESS_DELETE)) break; 5121 if (it.HasAccess(v8::ACCESS_DELETE)) break;
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after
6363 AssertNoContextChange ncc(isolate); 6362 AssertNoContextChange ncc(isolate);
6364 6363
6365 // Try to flatten before operating on the string. 6364 // Try to flatten before operating on the string.
6366 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); 6365 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6367 6366
6368 uint32_t index = 0; 6367 uint32_t index = 0;
6369 bool is_element = name->AsArrayIndex(&index); 6368 bool is_element = name->AsArrayIndex(&index);
6370 6369
6371 Handle<Object> old_value = isolate->factory()->the_hole_value(); 6370 Handle<Object> old_value = isolate->factory()->the_hole_value();
6372 bool is_observed = object->map()->is_observed() && 6371 bool is_observed = object->map()->is_observed() &&
6373 *name != isolate->heap()->hidden_string(); 6372 !isolate->IsInternallyUsedPropertyName(name);
6374 bool preexists = false; 6373 bool preexists = false;
6375 if (is_observed) { 6374 if (is_observed) {
6376 if (is_element) { 6375 if (is_element) {
6377 Maybe<bool> maybe = HasOwnElement(object, index); 6376 Maybe<bool> maybe = HasOwnElement(object, index);
6378 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used 6377 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6379 // uninitialized in this function". 6378 // uninitialized in this function".
6380 if (!maybe.has_value) { 6379 if (!maybe.has_value) {
6381 DCHECK(false); 6380 DCHECK(false);
6382 return isolate->factory()->undefined_value(); 6381 return isolate->factory()->undefined_value();
6383 } 6382 }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
6622 return GetHeap()->undefined_value(); 6621 return GetHeap()->undefined_value();
6623 } else { 6622 } else {
6624 return property_dictionary()->SlowReverseLookup(value); 6623 return property_dictionary()->SlowReverseLookup(value);
6625 } 6624 }
6626 } 6625 }
6627 6626
6628 6627
6629 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) { 6628 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6630 Handle<Map> result = map->GetIsolate()->factory()->NewMap( 6629 Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6631 map->instance_type(), instance_size); 6630 map->instance_type(), instance_size);
6632 result->set_prototype(map->prototype()); 6631 result->SetPrototype(handle(map->prototype(), map->GetIsolate()));
6633 result->set_constructor(map->constructor()); 6632 result->set_constructor(map->constructor());
6634 result->set_bit_field(map->bit_field()); 6633 result->set_bit_field(map->bit_field());
6635 result->set_bit_field2(map->bit_field2()); 6634 result->set_bit_field2(map->bit_field2());
6636 int new_bit_field3 = map->bit_field3(); 6635 int new_bit_field3 = map->bit_field3();
6637 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 6636 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6638 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); 6637 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6639 new_bit_field3 = EnumLengthBits::update(new_bit_field3, 6638 new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6640 kInvalidEnumCacheSentinel); 6639 kInvalidEnumCacheSentinel);
6641 new_bit_field3 = Deprecated::update(new_bit_field3, false); 6640 new_bit_field3 = Deprecated::update(new_bit_field3, false);
6642 if (!map->is_dictionary_map()) { 6641 if (!map->is_dictionary_map()) {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
6818 Map::TraceTransition("NoTransition", *parent, *child, *name); 6817 Map::TraceTransition("NoTransition", *parent, *child, *name);
6819 #endif 6818 #endif
6820 } else { 6819 } else {
6821 Handle<TransitionArray> transitions = 6820 Handle<TransitionArray> transitions =
6822 TransitionArray::Insert(parent, name, child, flag); 6821 TransitionArray::Insert(parent, name, child, flag);
6823 if (!parent->HasTransitionArray() || 6822 if (!parent->HasTransitionArray() ||
6824 *transitions != parent->transitions()) { 6823 *transitions != parent->transitions()) {
6825 parent->set_transitions(*transitions); 6824 parent->set_transitions(*transitions);
6826 } 6825 }
6827 child->SetBackPointer(*parent); 6826 child->SetBackPointer(*parent);
6827 if (child->prototype()->IsJSObject()) {
6828 Handle<JSObject> proto(JSObject::cast(child->prototype()));
6829 if (!child->ShouldRegisterAsPrototypeUser(proto)) {
6830 JSObject::UnregisterPrototypeUser(proto, child);
6831 }
6832 }
6828 #if TRACE_MAPS 6833 #if TRACE_MAPS
6829 Map::TraceTransition("Transition", *parent, *child, *name); 6834 Map::TraceTransition("Transition", *parent, *child, *name);
6830 #endif 6835 #endif
6831 } 6836 }
6832 } 6837 }
6833 6838
6834 6839
6835 Handle<Map> Map::CopyReplaceDescriptors( 6840 Handle<Map> Map::CopyReplaceDescriptors(
6836 Handle<Map> map, Handle<DescriptorArray> descriptors, 6841 Handle<Map> map, Handle<DescriptorArray> descriptors,
6837 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, 6842 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after
8128 bool FixedArray::IsEqualTo(FixedArray* other) { 8133 bool FixedArray::IsEqualTo(FixedArray* other) {
8129 if (length() != other->length()) return false; 8134 if (length() != other->length()) return false;
8130 for (int i = 0 ; i < length(); ++i) { 8135 for (int i = 0 ; i < length(); ++i) {
8131 if (get(i) != other->get(i)) return false; 8136 if (get(i) != other->get(i)) return false;
8132 } 8137 }
8133 return true; 8138 return true;
8134 } 8139 }
8135 #endif 8140 #endif
8136 8141
8137 8142
8143 // static
8144 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
8145 Handle<HeapObject> value) {
8146 DCHECK(array->IsEmptySlot(index)); // Don't overwrite anything.
8147 Handle<WeakCell> cell =
8148 value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
8149 : array->GetIsolate()->factory()->NewWeakCell(value);
8150 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
8151 if (FLAG_trace_weak_arrays) {
8152 PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8153 }
8154 array->set_last_used_index(index);
8155 }
8156
8157
8158 // static
8159 Handle<WeakFixedArray> WeakFixedArray::Add(
8160 Handle<Object> maybe_array, Handle<HeapObject> value,
8161 SearchForDuplicates search_for_duplicates) {
8162 Handle<WeakFixedArray> array =
8163 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8164 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8165 : Handle<WeakFixedArray>::cast(maybe_array);
8166
8167 if (search_for_duplicates == kAddIfNotFound) {
8168 for (int i = 0; i < array->Length(); ++i) {
8169 if (array->Get(i) == *value) return array;
8170 }
8171 } else {
8172 #ifdef DEBUG
8173 for (int i = 0; i < array->Length(); ++i) {
8174 DCHECK_NE(*value, array->Get(i));
8175 }
8176 #endif
8177 }
8178
8179 // Try to store the new entry if there's room. Optimize for consecutive
8180 // accesses.
8181 int first_index = array->last_used_index();
8182 for (int i = first_index;;) {
8183 if (array->IsEmptySlot((i))) {
8184 WeakFixedArray::Set(array, i, value);
8185 return array;
8186 }
8187 if (FLAG_trace_weak_arrays) {
8188 PrintF("[WeakFixedArray: searching for free slot]\n");
8189 }
8190 i = (i + 1) % array->Length();
8191 if (i == first_index) break;
8192 }
8193
8194 // No usable slot found, grow the array.
8195 int new_length = array->Length() + (array->Length() >> 1) + 4;
8196 Handle<WeakFixedArray> new_array =
8197 Allocate(array->GetIsolate(), new_length, array);
8198 if (FLAG_trace_weak_arrays) {
8199 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8200 }
8201 WeakFixedArray::Set(new_array, array->Length(), value);
8202 return new_array;
8203 }
8204
8205
8206 void WeakFixedArray::Remove(Handle<HeapObject> value) {
8207 // Optimize for the most recently added element to be removed again.
8208 int first_index = last_used_index();
8209 for (int i = first_index;;) {
8210 if (Get(i) == *value) {
8211 clear(i);
8212 // Users of WeakFixedArray should make sure that there are no duplicates,
8213 // they can use Add(..., kAddIfNotFound) if necessary.
8214 return;
8215 }
8216 i = (i + 1) % Length();
8217 if (i == first_index) break;
8218 }
8219 }
8220
8221
8222 // static
8223 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8224 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8225 DCHECK(0 <= size);
8226 Handle<FixedArray> result =
8227 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8228 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
8229 if (initialize_from.is_null()) {
8230 for (int i = 0; i < result->length(); ++i) {
8231 result->set(i, Smi::FromInt(0));
8232 }
8233 } else {
8234 DCHECK(initialize_from->Length() <= size);
8235 Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
8236 int target_index = kFirstIndex;
8237 for (int source_index = kFirstIndex; source_index < raw_source->length();
8238 ++source_index) {
8239 // The act of allocating might have caused entries in the source array
8240 // to be cleared. Copy only what's needed.
8241 if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
8242 result->set(target_index++, raw_source->get(source_index));
8243 }
8244 casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
8245 for (; target_index < result->length(); ++target_index) {
8246 result->set(target_index, Smi::FromInt(0));
8247 }
8248 }
8249 return casted_result;
8250 }
8251
8252
8138 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, 8253 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8139 int number_of_descriptors, 8254 int number_of_descriptors,
8140 int slack) { 8255 int slack) {
8141 DCHECK(0 <= number_of_descriptors); 8256 DCHECK(0 <= number_of_descriptors);
8142 Factory* factory = isolate->factory(); 8257 Factory* factory = isolate->factory();
8143 // Do not use DescriptorArray::cast on incomplete object. 8258 // Do not use DescriptorArray::cast on incomplete object.
8144 int size = number_of_descriptors + slack; 8259 int size = number_of_descriptors + slack;
8145 if (size == 0) return factory->empty_descriptor_array(); 8260 if (size == 0) return factory->empty_descriptor_array();
8146 // Allocate the array of keys. 8261 // Allocate the array of keys.
8147 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); 8262 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
(...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after
9709 } 9824 }
9710 } 9825 }
9711 9826
9712 9827
9713 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 9828 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9714 if (!object->map()->is_prototype_map()) return; 9829 if (!object->map()->is_prototype_map()) return;
9715 OptimizeAsPrototype(object, FAST_PROTOTYPE); 9830 OptimizeAsPrototype(object, FAST_PROTOTYPE);
9716 } 9831 }
9717 9832
9718 9833
9834 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
9835 Handle<HeapObject> user) {
9836 DCHECK(FLAG_track_prototype_users);
9837 Isolate* isolate = prototype->GetIsolate();
9838 Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
9839
9840 // Get prototype users array, create it if it doesn't exist yet.
9841 Handle<Object> maybe_array =
9842 JSObject::GetProperty(prototype, symbol).ToHandleChecked();
9843
9844 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user);
9845 if (!maybe_array.is_identical_to(new_array)) {
9846 JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array,
9847 DONT_ENUM).Assert();
9848 }
9849 }
9850
9851
9852 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9853 Handle<HeapObject> user) {
9854 Isolate* isolate = prototype->GetIsolate();
9855 Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
9856
9857 Handle<Object> maybe_array =
9858 JSObject::GetProperty(prototype, symbol).ToHandleChecked();
9859 if (!maybe_array->IsWeakFixedArray()) return;
9860 Handle<WeakFixedArray>::cast(maybe_array)->Remove(user);
9861 }
9862
9863
9864 void Map::SetPrototype(Handle<Object> prototype,
9865 PrototypeOptimizationMode proto_mode) {
9866 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
9867 Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
9868 JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
9869 }
9870 if (prototype->IsJSObject()) {
9871 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9872 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
9873 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
9874 }
9875 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9876 }
9877 WriteBarrierMode wb_mode =
9878 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9879 set_prototype(*prototype, wb_mode);
9880 }
9881
9882
9883 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
9884 if (!FLAG_track_prototype_users) return false;
9885 if (this->is_prototype_map()) return true;
9886 if (this->is_dictionary_map()) return false;
9887 Object* back = GetBackPointer();
9888 if (!back->IsMap()) return true;
9889 if (Map::cast(back)->prototype() != *prototype) return true;
9890 return false;
9891 }
9892
9893
9894 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
9895 if (!FLAG_track_prototype_users) return false;
9896 if (this->is_prototype_map()) return true;
9897 if (GetBackPointer()->IsMap()) return true;
9898 return false;
9899 }
9900
9901
9719 Handle<Object> CacheInitialJSArrayMaps( 9902 Handle<Object> CacheInitialJSArrayMaps(
9720 Handle<Context> native_context, Handle<Map> initial_map) { 9903 Handle<Context> native_context, Handle<Map> initial_map) {
9721 // Replace all of the cached initial array maps in the native context with 9904 // Replace all of the cached initial array maps in the native context with
9722 // the appropriate transitioned elements kind maps. 9905 // the appropriate transitioned elements kind maps.
9723 Factory* factory = native_context->GetIsolate()->factory(); 9906 Factory* factory = native_context->GetIsolate()->factory();
9724 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 9907 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9725 kElementsKindCount, TENURED); 9908 kElementsKindCount, TENURED);
9726 9909
9727 Handle<Map> current_map = initial_map; 9910 Handle<Map> current_map = initial_map;
9728 ElementsKind kind = current_map->elements_kind(); 9911 ElementsKind kind = current_map->elements_kind();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
9847 #endif 10030 #endif
9848 10031
9849 set_map(no_prototype_map); 10032 set_map(no_prototype_map);
9850 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); 10033 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9851 return true; 10034 return true;
9852 } 10035 }
9853 10036
9854 10037
9855 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map, 10038 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9856 Handle<Object> prototype) { 10039 Handle<Object> prototype) {
9857 if (prototype->IsJSObject()) { 10040 if (map->prototype() != *prototype) {
9858 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype); 10041 map->SetPrototype(prototype, FAST_PROTOTYPE);
9859 JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
9860 } 10042 }
9861 map->set_prototype(*prototype);
9862 function->set_prototype_or_initial_map(*map); 10043 function->set_prototype_or_initial_map(*map);
9863 map->set_constructor(*function); 10044 map->set_constructor(*function);
9864 #if TRACE_MAPS 10045 #if TRACE_MAPS
9865 if (FLAG_trace_maps) { 10046 if (FLAG_trace_maps) {
9866 PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n", 10047 PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
9867 reinterpret_cast<void*>(*map), function->shared()->unique_id(), 10048 reinterpret_cast<void*>(*map), function->shared()->unique_id(),
9868 function->shared()->DebugName()->ToCString().get()); 10049 function->shared()->DebugName()->ToCString().get());
9869 } 10050 }
9870 #endif 10051 #endif
9871 } 10052 }
(...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after
12003 return "allocation-site-tenuring-changed"; 12184 return "allocation-site-tenuring-changed";
12004 case kAllocationSiteTransitionChangedGroup: 12185 case kAllocationSiteTransitionChangedGroup:
12005 return "allocation-site-transition-changed"; 12186 return "allocation-site-transition-changed";
12006 } 12187 }
12007 UNREACHABLE(); 12188 UNREACHABLE();
12008 return "?"; 12189 return "?";
12009 } 12190 }
12010 12191
12011 12192
12012 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, 12193 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12013 Handle<Object> prototype) { 12194 Handle<Object> prototype,
12195 PrototypeOptimizationMode mode) {
12014 Handle<Map> new_map = GetPrototypeTransition(map, prototype); 12196 Handle<Map> new_map = GetPrototypeTransition(map, prototype);
12015 if (new_map.is_null()) { 12197 if (new_map.is_null()) {
12016 new_map = Copy(map, "TransitionToPrototype"); 12198 new_map = Copy(map, "TransitionToPrototype");
12017 PutPrototypeTransition(map, prototype, new_map); 12199 PutPrototypeTransition(map, prototype, new_map);
12018 new_map->set_prototype(*prototype); 12200 new_map->SetPrototype(prototype, mode);
12019 } 12201 }
12020 return new_map; 12202 return new_map;
12021 } 12203 }
12022 12204
12023 12205
12024 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 12206 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12025 Handle<Object> value, 12207 Handle<Object> value,
12026 bool from_javascript) { 12208 bool from_javascript) {
12027 #ifdef DEBUG 12209 #ifdef DEBUG
12028 int size = object->Size(); 12210 int size = object->Size();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
12078 iter.Advance(); 12260 iter.Advance();
12079 } 12261 }
12080 } 12262 }
12081 12263
12082 // Set the new prototype of the object. 12264 // Set the new prototype of the object.
12083 Handle<Map> map(real_receiver->map()); 12265 Handle<Map> map(real_receiver->map());
12084 12266
12085 // Nothing to do if prototype is already set. 12267 // Nothing to do if prototype is already set.
12086 if (map->prototype() == *value) return value; 12268 if (map->prototype() == *value) return value;
12087 12269
12088 if (value->IsJSObject()) { 12270 PrototypeOptimizationMode mode =
12089 PrototypeOptimizationMode mode = 12271 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12090 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 12272 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12091 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
12092 }
12093
12094 Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12095 DCHECK(new_map->prototype() == *value); 12273 DCHECK(new_map->prototype() == *value);
12096 JSObject::MigrateToMap(real_receiver, new_map); 12274 JSObject::MigrateToMap(real_receiver, new_map);
12097 12275
12098 if (from_javascript && !dictionary_elements_in_chain && 12276 if (from_javascript && !dictionary_elements_in_chain &&
12099 new_map->DictionaryElementsInPrototypeChainOnly()) { 12277 new_map->DictionaryElementsInPrototypeChainOnly()) {
12100 // If the prototype chain didn't previously have element callbacks, then 12278 // If the prototype chain didn't previously have element callbacks, then
12101 // KeyedStoreICs need to be cleared to ensure any that involve this 12279 // KeyedStoreICs need to be cleared to ensure any that involve this
12102 // map go generic. 12280 // map go generic.
12103 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); 12281 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12104 } 12282 }
(...skipping 4807 matching lines...) Expand 10 before | Expand all | Expand 10 after
16912 Handle<DependentCode> codes = 17090 Handle<DependentCode> codes =
16913 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), 17091 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
16914 DependentCode::kPropertyCellChangedGroup, 17092 DependentCode::kPropertyCellChangedGroup,
16915 info->object_wrapper()); 17093 info->object_wrapper());
16916 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17094 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
16917 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17095 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
16918 cell, info->zone()); 17096 cell, info->zone());
16919 } 17097 }
16920 17098
16921 } } // namespace v8::internal 17099 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698