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 3046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |