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 |