| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "accessors.h" | 7 #include "accessors.h" |
| 8 #include "allocation-site-scopes.h" | 8 #include "allocation-site-scopes.h" |
| 9 #include "api.h" | 9 #include "api.h" |
| 10 #include "arguments.h" | 10 #include "arguments.h" |
| (...skipping 4640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4651 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 4651 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
| 4652 return JSProxy::GetElementAttributeWithHandler( | 4652 return JSProxy::GetElementAttributeWithHandler( |
| 4653 Handle<JSProxy>::cast(proto), receiver, index); | 4653 Handle<JSProxy>::cast(proto), receiver, index); |
| 4654 } | 4654 } |
| 4655 if (proto->IsNull()) return ABSENT; | 4655 if (proto->IsNull()) return ABSENT; |
| 4656 return GetElementAttributeWithReceiver( | 4656 return GetElementAttributeWithReceiver( |
| 4657 Handle<JSObject>::cast(proto), receiver, index, true); | 4657 Handle<JSObject>::cast(proto), receiver, index, true); |
| 4658 } | 4658 } |
| 4659 | 4659 |
| 4660 | 4660 |
| 4661 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, | 4661 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { |
| 4662 Handle<Map> fast_map, | 4662 Handle<FixedArray> array( |
| 4663 PropertyNormalizationMode mode) { | 4663 isolate->factory()->NewFixedArray(kEntries, TENURED)); |
| 4664 int index = fast_map->Hash() % kEntries; | 4664 return Handle<NormalizedMapCache>::cast(array); |
| 4665 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); | |
| 4666 if (result->IsMap() && | |
| 4667 Handle<Map>::cast(result)->EquivalentToForNormalization( | |
| 4668 *fast_map, mode)) { | |
| 4669 #ifdef VERIFY_HEAP | |
| 4670 if (FLAG_verify_heap) { | |
| 4671 Handle<Map>::cast(result)->SharedMapVerify(); | |
| 4672 } | |
| 4673 #endif | |
| 4674 #ifdef ENABLE_SLOW_ASSERTS | |
| 4675 if (FLAG_enable_slow_asserts) { | |
| 4676 // The cached map should match newly created normalized map bit-by-bit, | |
| 4677 // except for the code cache, which can contain some ics which can be | |
| 4678 // applied to the shared map. | |
| 4679 Handle<Map> fresh = Map::CopyNormalized( | |
| 4680 fast_map, mode, SHARED_NORMALIZED_MAP); | |
| 4681 | |
| 4682 ASSERT(memcmp(fresh->address(), | |
| 4683 Handle<Map>::cast(result)->address(), | |
| 4684 Map::kCodeCacheOffset) == 0); | |
| 4685 STATIC_ASSERT(Map::kDependentCodeOffset == | |
| 4686 Map::kCodeCacheOffset + kPointerSize); | |
| 4687 int offset = Map::kDependentCodeOffset + kPointerSize; | |
| 4688 ASSERT(memcmp(fresh->address() + offset, | |
| 4689 Handle<Map>::cast(result)->address() + offset, | |
| 4690 Map::kSize - offset) == 0); | |
| 4691 } | |
| 4692 #endif | |
| 4693 return Handle<Map>::cast(result); | |
| 4694 } | |
| 4695 | |
| 4696 Isolate* isolate = cache->GetIsolate(); | |
| 4697 Handle<Map> map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP); | |
| 4698 ASSERT(map->is_dictionary_map()); | |
| 4699 cache->set(index, *map); | |
| 4700 isolate->counters()->normalized_maps()->Increment(); | |
| 4701 | |
| 4702 return map; | |
| 4703 } | 4665 } |
| 4704 | 4666 |
| 4705 | 4667 |
| 4668 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map, |
| 4669 PropertyNormalizationMode mode) { |
| 4670 DisallowHeapAllocation no_gc; |
| 4671 Object* value = FixedArray::get(GetIndex(fast_map)); |
| 4672 if (!value->IsMap() || |
| 4673 !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) { |
| 4674 return MaybeHandle<Map>(); |
| 4675 } |
| 4676 return handle(Map::cast(value)); |
| 4677 } |
| 4678 |
| 4679 |
| 4680 void NormalizedMapCache::Set(Handle<Map> fast_map, |
| 4681 Handle<Map> normalized_map) { |
| 4682 DisallowHeapAllocation no_gc; |
| 4683 ASSERT(normalized_map->is_dictionary_map()); |
| 4684 FixedArray::set(GetIndex(fast_map), *normalized_map); |
| 4685 } |
| 4686 |
| 4687 |
| 4706 void NormalizedMapCache::Clear() { | 4688 void NormalizedMapCache::Clear() { |
| 4707 int entries = length(); | 4689 int entries = length(); |
| 4708 for (int i = 0; i != entries; i++) { | 4690 for (int i = 0; i != entries; i++) { |
| 4709 set_undefined(i); | 4691 set_undefined(i); |
| 4710 } | 4692 } |
| 4711 } | 4693 } |
| 4712 | 4694 |
| 4713 | 4695 |
| 4714 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object, | 4696 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object, |
| 4715 Handle<Name> name, | 4697 Handle<Name> name, |
| 4716 Handle<Code> code) { | 4698 Handle<Code> code) { |
| 4717 Handle<Map> map(object->map()); | 4699 Handle<Map> map(object->map()); |
| 4718 Map::UpdateCodeCache(map, name, code); | 4700 Map::UpdateCodeCache(map, name, code); |
| 4719 } | 4701 } |
| 4720 | 4702 |
| 4721 | 4703 |
| 4722 void JSObject::NormalizeProperties(Handle<JSObject> object, | 4704 void JSObject::NormalizeProperties(Handle<JSObject> object, |
| 4723 PropertyNormalizationMode mode, | 4705 PropertyNormalizationMode mode, |
| 4724 int expected_additional_properties) { | 4706 int expected_additional_properties) { |
| 4725 if (!object->HasFastProperties()) return; | 4707 if (!object->HasFastProperties()) return; |
| 4726 | 4708 |
| 4727 // The global object is always normalized. | 4709 // The global object is always normalized. |
| 4728 ASSERT(!object->IsGlobalObject()); | 4710 ASSERT(!object->IsGlobalObject()); |
| 4729 // JSGlobalProxy must never be normalized | 4711 // JSGlobalProxy must never be normalized |
| 4730 ASSERT(!object->IsJSGlobalProxy()); | 4712 ASSERT(!object->IsJSGlobalProxy()); |
| 4731 | 4713 |
| 4732 Isolate* isolate = object->GetIsolate(); | 4714 Isolate* isolate = object->GetIsolate(); |
| 4733 HandleScope scope(isolate); | 4715 HandleScope scope(isolate); |
| 4734 Handle<Map> map(object->map()); | 4716 Handle<Map> map(object->map()); |
| 4717 Handle<Map> new_map = Map::Normalize(map, mode); |
| 4735 | 4718 |
| 4736 // Allocate new content. | 4719 // Allocate new content. |
| 4737 int real_size = map->NumberOfOwnDescriptors(); | 4720 int real_size = map->NumberOfOwnDescriptors(); |
| 4738 int property_count = real_size; | 4721 int property_count = real_size; |
| 4739 if (expected_additional_properties > 0) { | 4722 if (expected_additional_properties > 0) { |
| 4740 property_count += expected_additional_properties; | 4723 property_count += expected_additional_properties; |
| 4741 } else { | 4724 } else { |
| 4742 property_count += 2; // Make space for two more properties. | 4725 property_count += 2; // Make space for two more properties. |
| 4743 } | 4726 } |
| 4744 Handle<NameDictionary> dictionary = | 4727 Handle<NameDictionary> dictionary = |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4779 case NORMAL: | 4762 case NORMAL: |
| 4780 case NONEXISTENT: | 4763 case NONEXISTENT: |
| 4781 UNREACHABLE(); | 4764 UNREACHABLE(); |
| 4782 break; | 4765 break; |
| 4783 } | 4766 } |
| 4784 } | 4767 } |
| 4785 | 4768 |
| 4786 // Copy the next enumeration index from instance descriptor. | 4769 // Copy the next enumeration index from instance descriptor. |
| 4787 dictionary->SetNextEnumerationIndex(real_size + 1); | 4770 dictionary->SetNextEnumerationIndex(real_size + 1); |
| 4788 | 4771 |
| 4789 Handle<NormalizedMapCache> cache( | |
| 4790 isolate->context()->native_context()->normalized_map_cache()); | |
| 4791 Handle<Map> new_map = NormalizedMapCache::Get( | |
| 4792 cache, handle(object->map()), mode); | |
| 4793 ASSERT(new_map->is_dictionary_map()); | |
| 4794 | |
| 4795 // From here on we cannot fail and we shouldn't GC anymore. | 4772 // From here on we cannot fail and we shouldn't GC anymore. |
| 4796 DisallowHeapAllocation no_allocation; | 4773 DisallowHeapAllocation no_allocation; |
| 4797 | 4774 |
| 4798 // Resize the object in the heap if necessary. | 4775 // Resize the object in the heap if necessary. |
| 4799 int new_instance_size = new_map->instance_size(); | 4776 int new_instance_size = new_map->instance_size(); |
| 4800 int instance_size_delta = map->instance_size() - new_instance_size; | 4777 int instance_size_delta = map->instance_size() - new_instance_size; |
| 4801 ASSERT(instance_size_delta >= 0); | 4778 ASSERT(instance_size_delta >= 0); |
| 4802 Heap* heap = isolate->heap(); | 4779 Heap* heap = isolate->heap(); |
| 4803 heap->CreateFillerObjectAt(object->address() + new_instance_size, | 4780 heap->CreateFillerObjectAt(object->address() + new_instance_size, |
| 4804 instance_size_delta); | 4781 instance_size_delta); |
| 4805 heap->AdjustLiveBytes(object->address(), | 4782 heap->AdjustLiveBytes(object->address(), |
| 4806 -instance_size_delta, | 4783 -instance_size_delta, |
| 4807 Heap::FROM_MUTATOR); | 4784 Heap::FROM_MUTATOR); |
| 4808 | 4785 |
| 4809 // We are storing the new map using release store after creating a filler for | 4786 // We are storing the new map using release store after creating a filler for |
| 4810 // the left-over space to avoid races with the sweeper thread. | 4787 // the left-over space to avoid races with the sweeper thread. |
| 4811 object->synchronized_set_map(*new_map); | 4788 object->synchronized_set_map(*new_map); |
| 4812 | 4789 |
| 4813 map->NotifyLeafMapLayoutChange(); | |
| 4814 | |
| 4815 object->set_properties(*dictionary); | 4790 object->set_properties(*dictionary); |
| 4816 | 4791 |
| 4817 isolate->counters()->props_to_dictionary()->Increment(); | 4792 isolate->counters()->props_to_dictionary()->Increment(); |
| 4818 | 4793 |
| 4819 #ifdef DEBUG | 4794 #ifdef DEBUG |
| 4820 if (FLAG_trace_normalization) { | 4795 if (FLAG_trace_normalization) { |
| 4821 PrintF("Object properties have been normalized:\n"); | 4796 PrintF("Object properties have been normalized:\n"); |
| 4822 object->Print(); | 4797 object->Print(); |
| 4823 } | 4798 } |
| 4824 #endif | 4799 #endif |
| (...skipping 2406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7231 kInvalidEnumCacheSentinel); | 7206 kInvalidEnumCacheSentinel); |
| 7232 new_bit_field3 = Deprecated::update(new_bit_field3, false); | 7207 new_bit_field3 = Deprecated::update(new_bit_field3, false); |
| 7233 if (!map->is_dictionary_map()) { | 7208 if (!map->is_dictionary_map()) { |
| 7234 new_bit_field3 = IsUnstable::update(new_bit_field3, false); | 7209 new_bit_field3 = IsUnstable::update(new_bit_field3, false); |
| 7235 } | 7210 } |
| 7236 result->set_bit_field3(new_bit_field3); | 7211 result->set_bit_field3(new_bit_field3); |
| 7237 return result; | 7212 return result; |
| 7238 } | 7213 } |
| 7239 | 7214 |
| 7240 | 7215 |
| 7216 Handle<Map> Map::Normalize(Handle<Map> fast_map, |
| 7217 PropertyNormalizationMode mode) { |
| 7218 ASSERT(!fast_map->is_dictionary_map()); |
| 7219 |
| 7220 Isolate* isolate = fast_map->GetIsolate(); |
| 7221 Handle<NormalizedMapCache> cache( |
| 7222 isolate->context()->native_context()->normalized_map_cache()); |
| 7223 |
| 7224 Handle<Map> new_map; |
| 7225 if (cache->Get(fast_map, mode).ToHandle(&new_map)) { |
| 7226 #ifdef VERIFY_HEAP |
| 7227 if (FLAG_verify_heap) { |
| 7228 new_map->SharedMapVerify(); |
| 7229 } |
| 7230 #endif |
| 7231 #ifdef ENABLE_SLOW_ASSERTS |
| 7232 if (FLAG_enable_slow_asserts) { |
| 7233 // The cached map should match newly created normalized map bit-by-bit, |
| 7234 // except for the code cache, which can contain some ics which can be |
| 7235 // applied to the shared map. |
| 7236 Handle<Map> fresh = Map::CopyNormalized( |
| 7237 fast_map, mode, SHARED_NORMALIZED_MAP); |
| 7238 |
| 7239 ASSERT(memcmp(fresh->address(), |
| 7240 new_map->address(), |
| 7241 Map::kCodeCacheOffset) == 0); |
| 7242 STATIC_ASSERT(Map::kDependentCodeOffset == |
| 7243 Map::kCodeCacheOffset + kPointerSize); |
| 7244 int offset = Map::kDependentCodeOffset + kPointerSize; |
| 7245 ASSERT(memcmp(fresh->address() + offset, |
| 7246 new_map->address() + offset, |
| 7247 Map::kSize - offset) == 0); |
| 7248 } |
| 7249 #endif |
| 7250 } else { |
| 7251 new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP); |
| 7252 cache->Set(fast_map, new_map); |
| 7253 isolate->counters()->normalized_maps()->Increment(); |
| 7254 } |
| 7255 fast_map->NotifyLeafMapLayoutChange(); |
| 7256 return new_map; |
| 7257 } |
| 7258 |
| 7259 |
| 7241 Handle<Map> Map::CopyNormalized(Handle<Map> map, | 7260 Handle<Map> Map::CopyNormalized(Handle<Map> map, |
| 7242 PropertyNormalizationMode mode, | 7261 PropertyNormalizationMode mode, |
| 7243 NormalizedMapSharingMode sharing) { | 7262 NormalizedMapSharingMode sharing) { |
| 7244 int new_instance_size = map->instance_size(); | 7263 int new_instance_size = map->instance_size(); |
| 7245 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 7264 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 7246 new_instance_size -= map->inobject_properties() * kPointerSize; | 7265 new_instance_size -= map->inobject_properties() * kPointerSize; |
| 7247 } | 7266 } |
| 7248 | 7267 |
| 7249 Handle<Map> result = RawCopy(map, new_instance_size); | 7268 Handle<Map> result = RawCopy(map, new_instance_size); |
| 7250 | 7269 |
| (...skipping 9959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17210 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17229 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17211 static const char* error_messages_[] = { | 17230 static const char* error_messages_[] = { |
| 17212 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17231 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17213 }; | 17232 }; |
| 17214 #undef ERROR_MESSAGES_TEXTS | 17233 #undef ERROR_MESSAGES_TEXTS |
| 17215 return error_messages_[reason]; | 17234 return error_messages_[reason]; |
| 17216 } | 17235 } |
| 17217 | 17236 |
| 17218 | 17237 |
| 17219 } } // namespace v8::internal | 17238 } } // namespace v8::internal |
| OLD | NEW |