OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |