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

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: addressed comments 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
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 3046 matching lines...) Expand 10 before | Expand all | Expand 10 after
3057 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot 3057 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3058 // have own properties. 3058 // have own properties.
3059 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 3059 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3060 3060
3061 // Store on the holder which may be hidden behind the receiver. 3061 // Store on the holder which may be hidden behind the receiver.
3062 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); 3062 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3063 3063
3064 // Old value for the observation change record. 3064 // Old value for the observation change record.
3065 // Fetch before transforming the object since the encoding may become 3065 // Fetch before transforming the object since the encoding may become
3066 // incompatible with what's cached in |it|. 3066 // incompatible with what's cached in |it|.
3067 bool is_observed = 3067 bool is_observed = receiver->map()->is_observed() &&
3068 receiver->map()->is_observed() && 3068 !it->isolate()->IsInternallyUsedPropertyName(it->name());
3069 !it->name().is_identical_to(it->factory()->hidden_string());
3070 MaybeHandle<Object> maybe_old; 3069 MaybeHandle<Object> maybe_old;
3071 if (is_observed) maybe_old = it->GetDataValue(); 3070 if (is_observed) maybe_old = it->GetDataValue();
3072 3071
3073 // Possibly migrate to the most up-to-date map that will be able to store 3072 // Possibly migrate to the most up-to-date map that will be able to store
3074 // |value| under it->name(). 3073 // |value| under it->name().
3075 it->PrepareForDataProperty(value); 3074 it->PrepareForDataProperty(value);
3076 3075
3077 // Write the property value. 3076 // Write the property value.
3078 it->WriteDataValue(value); 3077 it->WriteDataValue(value);
3079 3078
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3129 // TODO(verwaest): Probably should ensure this is done beforehand. 3128 // TODO(verwaest): Probably should ensure this is done beforehand.
3130 it->InternalizeName(); 3129 it->InternalizeName();
3131 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); 3130 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3132 } else { 3131 } else {
3133 // Write the property value. 3132 // Write the property value.
3134 it->WriteDataValue(value); 3133 it->WriteDataValue(value);
3135 } 3134 }
3136 3135
3137 // Send the change record if there are observers. 3136 // Send the change record if there are observers.
3138 if (receiver->map()->is_observed() && 3137 if (receiver->map()->is_observed() &&
3139 !it->name().is_identical_to(it->factory()->hidden_string())) { 3138 !it->isolate()->IsInternallyUsedPropertyName(it->name())) {
3140 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( 3139 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3141 receiver, "add", it->name(), 3140 receiver, "add", it->name(),
3142 it->factory()->the_hole_value()), 3141 it->factory()->the_hole_value()),
3143 Object); 3142 Object);
3144 } 3143 }
3145 3144
3146 return value; 3145 return value;
3147 } 3146 }
3148 3147
3149 3148
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
3918 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 3917 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3919 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); 3918 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
3920 #ifdef DEBUG 3919 #ifdef DEBUG
3921 uint32_t index; 3920 uint32_t index;
3922 DCHECK(!object->IsJSProxy()); 3921 DCHECK(!object->IsJSProxy());
3923 DCHECK(!name->AsArrayIndex(&index)); 3922 DCHECK(!name->AsArrayIndex(&index));
3924 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 3923 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
3925 DCHECK(maybe.has_value); 3924 DCHECK(maybe.has_value);
3926 DCHECK(!it.IsFound()); 3925 DCHECK(!it.IsFound());
3927 DCHECK(object->map()->is_extensible() || 3926 DCHECK(object->map()->is_extensible() ||
3928 name.is_identical_to(it.isolate()->factory()->hidden_string())); 3927 it.isolate()->IsInternallyUsedPropertyName(name));
3929 #endif 3928 #endif
3930 AddDataProperty(&it, value, attributes, STRICT, 3929 AddDataProperty(&it, value, attributes, STRICT,
3931 CERTAINLY_NOT_STORE_FROM_KEYED).Check(); 3930 CERTAINLY_NOT_STORE_FROM_KEYED).Check();
3932 } 3931 }
3933 3932
3934 3933
3935 // Reconfigures a property to a data property with attributes, even if it is not 3934 // Reconfigures a property to a data property with attributes, even if it is not
3936 // reconfigurable. 3935 // reconfigurable.
3937 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 3936 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
3938 Handle<JSObject> object, 3937 Handle<JSObject> object,
3939 Handle<Name> name, 3938 Handle<Name> name,
3940 Handle<Object> value, 3939 Handle<Object> value,
3941 PropertyAttributes attributes, 3940 PropertyAttributes attributes,
3942 ExecutableAccessorInfoHandling handling) { 3941 ExecutableAccessorInfoHandling handling) {
3943 DCHECK(!value->IsTheHole()); 3942 DCHECK(!value->IsTheHole());
3944 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 3943 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3945 bool is_observed = object->map()->is_observed() && 3944 bool is_observed = object->map()->is_observed() &&
3946 *name != it.isolate()->heap()->hidden_string(); 3945 !it.isolate()->IsInternallyUsedPropertyName(name);
3947 for (; it.IsFound(); it.Next()) { 3946 for (; it.IsFound(); it.Next()) {
3948 switch (it.state()) { 3947 switch (it.state()) {
3949 case LookupIterator::INTERCEPTOR: 3948 case LookupIterator::INTERCEPTOR:
3950 case LookupIterator::JSPROXY: 3949 case LookupIterator::JSPROXY:
3951 case LookupIterator::NOT_FOUND: 3950 case LookupIterator::NOT_FOUND:
3952 case LookupIterator::TRANSITION: 3951 case LookupIterator::TRANSITION:
3953 UNREACHABLE(); 3952 UNREACHABLE();
3954 3953
3955 case LookupIterator::ACCESS_CHECK: 3954 case LookupIterator::ACCESS_CHECK:
3956 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { 3955 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after
5094 } 5093 }
5095 5094
5096 // Skip interceptors on FORCE_DELETION. 5095 // Skip interceptors on FORCE_DELETION.
5097 LookupIterator::Configuration config = 5096 LookupIterator::Configuration config =
5098 delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR 5097 delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR
5099 : LookupIterator::HIDDEN; 5098 : LookupIterator::HIDDEN;
5100 5099
5101 LookupIterator it(object, name, config); 5100 LookupIterator it(object, name, config);
5102 5101
5103 bool is_observed = object->map()->is_observed() && 5102 bool is_observed = object->map()->is_observed() &&
5104 *name != it.isolate()->heap()->hidden_string(); 5103 !it.isolate()->IsInternallyUsedPropertyName(name);
5105 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); 5104 Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
5106 5105
5107 for (; it.IsFound(); it.Next()) { 5106 for (; it.IsFound(); it.Next()) {
5108 switch (it.state()) { 5107 switch (it.state()) {
5109 case LookupIterator::JSPROXY: 5108 case LookupIterator::JSPROXY:
5110 case LookupIterator::NOT_FOUND: 5109 case LookupIterator::NOT_FOUND:
5111 case LookupIterator::TRANSITION: 5110 case LookupIterator::TRANSITION:
5112 UNREACHABLE(); 5111 UNREACHABLE();
5113 case LookupIterator::ACCESS_CHECK: 5112 case LookupIterator::ACCESS_CHECK:
5114 if (it.HasAccess(v8::ACCESS_DELETE)) break; 5113 if (it.HasAccess(v8::ACCESS_DELETE)) break;
(...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after
6320 AssertNoContextChange ncc(isolate); 6319 AssertNoContextChange ncc(isolate);
6321 6320
6322 // Try to flatten before operating on the string. 6321 // Try to flatten before operating on the string.
6323 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); 6322 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6324 6323
6325 uint32_t index = 0; 6324 uint32_t index = 0;
6326 bool is_element = name->AsArrayIndex(&index); 6325 bool is_element = name->AsArrayIndex(&index);
6327 6326
6328 Handle<Object> old_value = isolate->factory()->the_hole_value(); 6327 Handle<Object> old_value = isolate->factory()->the_hole_value();
6329 bool is_observed = object->map()->is_observed() && 6328 bool is_observed = object->map()->is_observed() &&
6330 *name != isolate->heap()->hidden_string(); 6329 !isolate->IsInternallyUsedPropertyName(name);
6331 bool preexists = false; 6330 bool preexists = false;
6332 if (is_observed) { 6331 if (is_observed) {
6333 if (is_element) { 6332 if (is_element) {
6334 Maybe<bool> maybe = HasOwnElement(object, index); 6333 Maybe<bool> maybe = HasOwnElement(object, index);
6335 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used 6334 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6336 // uninitialized in this function". 6335 // uninitialized in this function".
6337 if (!maybe.has_value) { 6336 if (!maybe.has_value) {
6338 DCHECK(false); 6337 DCHECK(false);
6339 return isolate->factory()->undefined_value(); 6338 return isolate->factory()->undefined_value();
6340 } 6339 }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
6579 return GetHeap()->undefined_value(); 6578 return GetHeap()->undefined_value();
6580 } else { 6579 } else {
6581 return property_dictionary()->SlowReverseLookup(value); 6580 return property_dictionary()->SlowReverseLookup(value);
6582 } 6581 }
6583 } 6582 }
6584 6583
6585 6584
6586 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) { 6585 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6587 Handle<Map> result = map->GetIsolate()->factory()->NewMap( 6586 Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6588 map->instance_type(), instance_size); 6587 map->instance_type(), instance_size);
6589 result->set_prototype(map->prototype()); 6588 result->SetPrototype(handle(map->prototype(), map->GetIsolate()));
6590 result->set_constructor(map->constructor()); 6589 result->set_constructor(map->constructor());
6591 result->set_bit_field(map->bit_field()); 6590 result->set_bit_field(map->bit_field());
6592 result->set_bit_field2(map->bit_field2()); 6591 result->set_bit_field2(map->bit_field2());
6593 int new_bit_field3 = map->bit_field3(); 6592 int new_bit_field3 = map->bit_field3();
6594 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 6593 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6595 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); 6594 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6596 new_bit_field3 = EnumLengthBits::update(new_bit_field3, 6595 new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6597 kInvalidEnumCacheSentinel); 6596 kInvalidEnumCacheSentinel);
6598 new_bit_field3 = Deprecated::update(new_bit_field3, false); 6597 new_bit_field3 = Deprecated::update(new_bit_field3, false);
6599 if (!map->is_dictionary_map()) { 6598 if (!map->is_dictionary_map()) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
6776 Map::TraceTransition("NoTransition", *parent, *child, *name); 6775 Map::TraceTransition("NoTransition", *parent, *child, *name);
6777 #endif 6776 #endif
6778 } else { 6777 } else {
6779 Handle<TransitionArray> transitions = 6778 Handle<TransitionArray> transitions =
6780 TransitionArray::Insert(parent, name, child, flag); 6779 TransitionArray::Insert(parent, name, child, flag);
6781 if (!parent->HasTransitionArray() || 6780 if (!parent->HasTransitionArray() ||
6782 *transitions != parent->transitions()) { 6781 *transitions != parent->transitions()) {
6783 parent->set_transitions(*transitions); 6782 parent->set_transitions(*transitions);
6784 } 6783 }
6785 child->SetBackPointer(*parent); 6784 child->SetBackPointer(*parent);
6785 if (child->prototype()->IsJSObject()) {
6786 Handle<JSObject> proto(JSObject::cast(child->prototype()));
6787 if (!child->ShouldRegisterAsPrototypeUser(proto)) {
6788 JSObject::UnregisterPrototypeUser(proto, child);
6789 }
6790 }
6786 #if TRACE_MAPS 6791 #if TRACE_MAPS
6787 Map::TraceTransition("Transition", *parent, *child, *name); 6792 Map::TraceTransition("Transition", *parent, *child, *name);
6788 #endif 6793 #endif
6789 } 6794 }
6790 } 6795 }
6791 6796
6792 6797
6793 Handle<Map> Map::CopyReplaceDescriptors( 6798 Handle<Map> Map::CopyReplaceDescriptors(
6794 Handle<Map> map, Handle<DescriptorArray> descriptors, 6799 Handle<Map> map, Handle<DescriptorArray> descriptors,
6795 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, 6800 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
(...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after
8092 bool FixedArray::IsEqualTo(FixedArray* other) { 8097 bool FixedArray::IsEqualTo(FixedArray* other) {
8093 if (length() != other->length()) return false; 8098 if (length() != other->length()) return false;
8094 for (int i = 0 ; i < length(); ++i) { 8099 for (int i = 0 ; i < length(); ++i) {
8095 if (get(i) != other->get(i)) return false; 8100 if (get(i) != other->get(i)) return false;
8096 } 8101 }
8097 return true; 8102 return true;
8098 } 8103 }
8099 #endif 8104 #endif
8100 8105
8101 8106
8107 // static
8108 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
8109 Handle<HeapObject> value) {
8110 DCHECK(array->IsEmptySlot(index)); // Don't overwrite anything.
8111 Handle<WeakCell> cell = array->GetIsolate()->factory()->NewWeakCell(value);
8112 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
8113 if (FLAG_trace_weak_arrays) {
8114 PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8115 }
8116 array->set_last_used_index(index);
8117 }
8118
8119
8120 // static
8121 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array,
8122 Handle<HeapObject> value,
8123 bool may_be_duplicate) {
8124 Handle<WeakFixedArray> array =
8125 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8126 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8127 : Handle<WeakFixedArray>::cast(maybe_array);
8128
8129 if (may_be_duplicate) {
8130 for (int i = 0; i < array->length(); ++i) {
8131 if (array->get(i) == *value) return array;
8132 }
8133 } else {
8134 #ifdef DEBUG
8135 for (int i = 0; i < array->length(); ++i) {
8136 DCHECK_NE(*value, array->get(i));
8137 }
8138 #endif
8139 }
8140
8141 // Try to store the new entry if there's room. Optimize for consecutive
8142 // accesses.
8143 int first_index = array->last_used_index();
8144 for (int i = first_index;;) {
8145 if (array->IsEmptySlot((i))) {
8146 WeakFixedArray::Set(array, i, value);
8147 return array;
8148 }
8149 if (FLAG_trace_weak_arrays) {
8150 PrintF("[WeakFixedArray: searching for free slot]\n");
8151 }
8152 i = (i + 1) % array->length();
8153 if (i == first_index) break;
8154 }
8155
8156 // No usable slot found, grow the array.
8157 int new_length = array->length() + (array->length() >> 1) + 4;
8158 Handle<WeakFixedArray> new_array =
8159 Allocate(array->GetIsolate(), new_length, array);
8160 if (FLAG_trace_weak_arrays) {
8161 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8162 }
8163 WeakFixedArray::Set(new_array, array->length(), value);
8164 return new_array;
8165 }
8166
8167
8168 void WeakFixedArray::Remove(Handle<HeapObject> value) {
8169 // Optimize for the most recently added element to be removed again.
8170 int first_index = last_used_index();
8171 for (int i = first_index;;) {
8172 if (get(i) == *value) {
8173 clear(i);
8174 return; // StoreAnywhere() makes sure there are no duplicates.
ulan 2014/12/15 15:40:36 What is StoreAnywhere()?
Jakob Kummerow 2014/12/15 16:18:49 An outdated comment. Fixed.
8175 }
8176 i = (i + 1) % length();
8177 if (i == first_index) break;
8178 }
8179 }
8180
8181
8182 // static
8183 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8184 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8185 DCHECK(0 <= size);
8186 Handle<FixedArray> result =
8187 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8188 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
8189 if (initialize_from.is_null()) {
8190 for (int i = 0; i < result->length(); ++i) {
8191 result->set(i, Smi::FromInt(0));
8192 }
8193 } else {
8194 DCHECK(initialize_from->length() <= size);
8195 Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
8196 int target_index = kFirstIndex;
8197 for (int source_index = kFirstIndex; source_index < raw_source->length();
8198 ++source_index) {
8199 // The act of allocating might have caused entries in the source array
8200 // to be cleared. Copy only what's needed.
8201 if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
8202 result->set(target_index++, raw_source->get(source_index));
8203 }
8204 casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
8205 for (; target_index < result->length(); ++target_index) {
8206 result->set(target_index, Smi::FromInt(0));
8207 }
8208 }
8209 return casted_result;
8210 }
8211
8212
8102 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, 8213 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8103 int number_of_descriptors, 8214 int number_of_descriptors,
8104 int slack) { 8215 int slack) {
8105 DCHECK(0 <= number_of_descriptors); 8216 DCHECK(0 <= number_of_descriptors);
8106 Factory* factory = isolate->factory(); 8217 Factory* factory = isolate->factory();
8107 // Do not use DescriptorArray::cast on incomplete object. 8218 // Do not use DescriptorArray::cast on incomplete object.
8108 int size = number_of_descriptors + slack; 8219 int size = number_of_descriptors + slack;
8109 if (size == 0) return factory->empty_descriptor_array(); 8220 if (size == 0) return factory->empty_descriptor_array();
8110 // Allocate the array of keys. 8221 // Allocate the array of keys.
8111 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); 8222 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
(...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after
9662 } 9773 }
9663 } 9774 }
9664 9775
9665 9776
9666 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 9777 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9667 if (!object->map()->is_prototype_map()) return; 9778 if (!object->map()->is_prototype_map()) return;
9668 OptimizeAsPrototype(object, FAST_PROTOTYPE); 9779 OptimizeAsPrototype(object, FAST_PROTOTYPE);
9669 } 9780 }
9670 9781
9671 9782
9783 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
9784 Handle<HeapObject> user) {
9785 DCHECK(FLAG_track_prototype_users);
9786 Isolate* isolate = prototype->GetIsolate();
9787 Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
9788
9789 // Get prototype users array, create it if it doesn't exist yet.
9790 Handle<Object> maybe_array =
9791 JSObject::GetProperty(prototype, symbol).ToHandleChecked();
9792
9793 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user);
9794 if (!maybe_array.is_identical_to(new_array)) {
9795 JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array,
9796 DONT_ENUM).Assert();
9797 }
9798 }
9799
9800
9801 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9802 Handle<HeapObject> user) {
9803 Isolate* isolate = prototype->GetIsolate();
9804 Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
9805
9806 Handle<Object> maybe_array =
9807 JSObject::GetProperty(prototype, symbol).ToHandleChecked();
9808 if (!maybe_array->IsWeakFixedArray()) return;
9809 Handle<WeakFixedArray>::cast(maybe_array)->Remove(user);
9810 }
9811
9812
9813 void Map::SetPrototype(Handle<Object> prototype,
9814 PrototypeOptimizationMode proto_mode) {
9815 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
9816 Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
9817 JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
9818 }
9819 if (prototype->IsJSObject()) {
9820 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9821 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
9822 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
9823 }
9824 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9825 }
9826 WriteBarrierMode wb_mode =
9827 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9828 set_prototype(*prototype, wb_mode);
9829 }
9830
9831
9832 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
9833 if (!FLAG_track_prototype_users) return false;
9834 if (this->is_prototype_map()) return true;
9835 if (this->is_dictionary_map()) return false;
9836 Object* back = GetBackPointer();
9837 if (!back->IsMap()) return true;
9838 if (Map::cast(back)->prototype() != *prototype) return true;
9839 return false;
9840 }
9841
9842
9843 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
9844 if (!FLAG_track_prototype_users) return false;
9845 if (this->is_prototype_map()) return true;
9846 if (GetBackPointer()->IsMap()) return true;
9847 return false;
9848 }
9849
9850
9672 Handle<Object> CacheInitialJSArrayMaps( 9851 Handle<Object> CacheInitialJSArrayMaps(
9673 Handle<Context> native_context, Handle<Map> initial_map) { 9852 Handle<Context> native_context, Handle<Map> initial_map) {
9674 // Replace all of the cached initial array maps in the native context with 9853 // Replace all of the cached initial array maps in the native context with
9675 // the appropriate transitioned elements kind maps. 9854 // the appropriate transitioned elements kind maps.
9676 Factory* factory = native_context->GetIsolate()->factory(); 9855 Factory* factory = native_context->GetIsolate()->factory();
9677 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 9856 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9678 kElementsKindCount, TENURED); 9857 kElementsKindCount, TENURED);
9679 9858
9680 Handle<Map> current_map = initial_map; 9859 Handle<Map> current_map = initial_map;
9681 ElementsKind kind = current_map->elements_kind(); 9860 ElementsKind kind = current_map->elements_kind();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
9800 #endif 9979 #endif
9801 9980
9802 set_map(no_prototype_map); 9981 set_map(no_prototype_map);
9803 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); 9982 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9804 return true; 9983 return true;
9805 } 9984 }
9806 9985
9807 9986
9808 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map, 9987 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9809 Handle<Object> prototype) { 9988 Handle<Object> prototype) {
9810 if (prototype->IsJSObject()) { 9989 if (map->prototype() != *prototype) {
9811 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype); 9990 map->SetPrototype(prototype, FAST_PROTOTYPE);
9812 JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
9813 } 9991 }
9814 map->set_prototype(*prototype);
9815 function->set_prototype_or_initial_map(*map); 9992 function->set_prototype_or_initial_map(*map);
9816 map->set_constructor(*function); 9993 map->set_constructor(*function);
9817 #if TRACE_MAPS 9994 #if TRACE_MAPS
9818 if (FLAG_trace_maps) { 9995 if (FLAG_trace_maps) {
9819 PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n", 9996 PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
9820 reinterpret_cast<void*>(*map), function->shared()->unique_id(), 9997 reinterpret_cast<void*>(*map), function->shared()->unique_id(),
9821 function->shared()->DebugName()->ToCString().get()); 9998 function->shared()->DebugName()->ToCString().get());
9822 } 9999 }
9823 #endif 10000 #endif
9824 } 10001 }
(...skipping 2111 matching lines...) Expand 10 before | Expand all | Expand 10 after
11936 return "allocation-site-tenuring-changed"; 12113 return "allocation-site-tenuring-changed";
11937 case kAllocationSiteTransitionChangedGroup: 12114 case kAllocationSiteTransitionChangedGroup:
11938 return "allocation-site-transition-changed"; 12115 return "allocation-site-transition-changed";
11939 } 12116 }
11940 UNREACHABLE(); 12117 UNREACHABLE();
11941 return "?"; 12118 return "?";
11942 } 12119 }
11943 12120
11944 12121
11945 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, 12122 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
11946 Handle<Object> prototype) { 12123 Handle<Object> prototype,
12124 PrototypeOptimizationMode mode) {
11947 Handle<Map> new_map = GetPrototypeTransition(map, prototype); 12125 Handle<Map> new_map = GetPrototypeTransition(map, prototype);
11948 if (new_map.is_null()) { 12126 if (new_map.is_null()) {
11949 new_map = Copy(map, "TransitionToPrototype"); 12127 new_map = Copy(map, "TransitionToPrototype");
11950 PutPrototypeTransition(map, prototype, new_map); 12128 PutPrototypeTransition(map, prototype, new_map);
11951 new_map->set_prototype(*prototype); 12129 new_map->SetPrototype(prototype, mode);
11952 } 12130 }
11953 return new_map; 12131 return new_map;
11954 } 12132 }
11955 12133
11956 12134
11957 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 12135 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
11958 Handle<Object> value, 12136 Handle<Object> value,
11959 bool from_javascript) { 12137 bool from_javascript) {
11960 #ifdef DEBUG 12138 #ifdef DEBUG
11961 int size = object->Size(); 12139 int size = object->Size();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
12011 iter.Advance(); 12189 iter.Advance();
12012 } 12190 }
12013 } 12191 }
12014 12192
12015 // Set the new prototype of the object. 12193 // Set the new prototype of the object.
12016 Handle<Map> map(real_receiver->map()); 12194 Handle<Map> map(real_receiver->map());
12017 12195
12018 // Nothing to do if prototype is already set. 12196 // Nothing to do if prototype is already set.
12019 if (map->prototype() == *value) return value; 12197 if (map->prototype() == *value) return value;
12020 12198
12021 if (value->IsJSObject()) { 12199 PrototypeOptimizationMode mode =
12022 PrototypeOptimizationMode mode = 12200 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12023 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 12201 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12024 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
12025 }
12026
12027 Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12028 DCHECK(new_map->prototype() == *value); 12202 DCHECK(new_map->prototype() == *value);
12029 JSObject::MigrateToMap(real_receiver, new_map); 12203 JSObject::MigrateToMap(real_receiver, new_map);
12030 12204
12031 if (from_javascript && !dictionary_elements_in_chain && 12205 if (from_javascript && !dictionary_elements_in_chain &&
12032 new_map->DictionaryElementsInPrototypeChainOnly()) { 12206 new_map->DictionaryElementsInPrototypeChainOnly()) {
12033 // If the prototype chain didn't previously have element callbacks, then 12207 // If the prototype chain didn't previously have element callbacks, then
12034 // KeyedStoreICs need to be cleared to ensure any that involve this 12208 // KeyedStoreICs need to be cleared to ensure any that involve this
12035 // map go generic. 12209 // map go generic.
12036 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); 12210 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12037 } 12211 }
(...skipping 4799 matching lines...) Expand 10 before | Expand all | Expand 10 after
16837 Handle<DependentCode> codes = 17011 Handle<DependentCode> codes =
16838 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), 17012 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
16839 DependentCode::kPropertyCellChangedGroup, 17013 DependentCode::kPropertyCellChangedGroup,
16840 info->object_wrapper()); 17014 info->object_wrapper());
16841 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17015 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
16842 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17016 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
16843 cell, info->zone()); 17017 cell, info->zone());
16844 } 17018 }
16845 17019
16846 } } // namespace v8::internal 17020 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698