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