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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 case kInteger32: return "i"; | 1984 case kInteger32: return "i"; |
1985 case kHeapObject: return "h"; | 1985 case kHeapObject: return "h"; |
1986 case kExternal: return "x"; | 1986 case kExternal: return "x"; |
1987 default: | 1987 default: |
1988 UNREACHABLE(); | 1988 UNREACHABLE(); |
1989 return NULL; | 1989 return NULL; |
1990 } | 1990 } |
1991 } | 1991 } |
1992 | 1992 |
1993 | 1993 |
1994 static void ZapEndOfFixedArray(Address new_end, int to_trim) { | |
1995 // If we are doing a big trim in old space then we zap the space. | |
1996 Object** zap = reinterpret_cast<Object**>(new_end); | |
1997 zap++; // Header of filler must be at least one word so skip that. | |
1998 for (int i = 1; i < to_trim; i++) { | |
1999 *zap++ = Smi::FromInt(0); | |
2000 } | |
2001 } | |
2002 | |
2003 | |
2004 template<Heap::InvocationMode mode> | |
2005 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { | |
2006 DCHECK(elms->map() != heap->fixed_cow_array_map()); | |
2007 // For now this trick is only applied to fixed arrays in new and paged space. | |
2008 DCHECK(!heap->lo_space()->Contains(elms)); | |
2009 | |
2010 const int len = elms->length(); | |
2011 | |
2012 DCHECK(to_trim < len); | |
2013 | |
2014 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim); | |
2015 | |
2016 if (mode != Heap::FROM_GC || Heap::ShouldZapGarbage()) { | |
2017 ZapEndOfFixedArray(new_end, to_trim); | |
2018 } | |
2019 | |
2020 int size_delta = to_trim * kPointerSize; | |
2021 | |
2022 // Technically in new space this write might be omitted (except for | |
2023 // debug mode which iterates through the heap), but to play safer | |
2024 // we still do it. | |
2025 heap->CreateFillerObjectAt(new_end, size_delta); | |
2026 | |
2027 // We are storing the new length using release store after creating a filler | |
2028 // for the left-over space to avoid races with the sweeper thread. | |
2029 elms->synchronized_set_length(len - to_trim); | |
2030 | |
2031 heap->AdjustLiveBytes(elms->address(), -size_delta, mode); | |
2032 | |
2033 // The array may not be moved during GC, | |
2034 // and size has to be adjusted nevertheless. | |
2035 HeapProfiler* profiler = heap->isolate()->heap_profiler(); | |
2036 if (profiler->is_tracking_allocations()) { | |
2037 profiler->UpdateObjectSizeEvent(elms->address(), elms->Size()); | |
2038 } | |
2039 } | |
2040 | |
2041 | |
2042 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, | 1994 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, |
2043 int target_inobject, int target_unused, | 1995 int target_inobject, int target_unused, |
2044 int* old_number_of_fields) { | 1996 int* old_number_of_fields) { |
2045 // If fields were added (or removed), rewrite the instance. | 1997 // If fields were added (or removed), rewrite the instance. |
2046 *old_number_of_fields = NumberOfFields(); | 1998 *old_number_of_fields = NumberOfFields(); |
2047 DCHECK(target_number_of_fields >= *old_number_of_fields); | 1999 DCHECK(target_number_of_fields >= *old_number_of_fields); |
2048 if (target_number_of_fields != *old_number_of_fields) return true; | 2000 if (target_number_of_fields != *old_number_of_fields) return true; |
2049 | 2001 |
2050 // If smi descriptors were replaced by double descriptors, rewrite. | 2002 // If smi descriptors were replaced by double descriptors, rewrite. |
2051 DescriptorArray* old_desc = instance_descriptors(); | 2003 DescriptorArray* old_desc = instance_descriptors(); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2239 for (int i = 0; i < limit; i++) { | 2191 for (int i = 0; i < limit; i++) { |
2240 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); | 2192 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); |
2241 object->FastPropertyAtPut(index, array->get(external + i)); | 2193 object->FastPropertyAtPut(index, array->get(external + i)); |
2242 } | 2194 } |
2243 | 2195 |
2244 Heap* heap = isolate->heap(); | 2196 Heap* heap = isolate->heap(); |
2245 | 2197 |
2246 // If there are properties in the new backing store, trim it to the correct | 2198 // If there are properties in the new backing store, trim it to the correct |
2247 // size and install the backing store into the object. | 2199 // size and install the backing store into the object. |
2248 if (external > 0) { | 2200 if (external > 0) { |
2249 RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject); | 2201 heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject); |
2250 object->set_properties(*array); | 2202 object->set_properties(*array); |
2251 } | 2203 } |
2252 | 2204 |
2253 // Create filler object past the new instance size. | 2205 // Create filler object past the new instance size. |
2254 int new_instance_size = new_map->instance_size(); | 2206 int new_instance_size = new_map->instance_size(); |
2255 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2207 int instance_size_delta = old_map->instance_size() - new_instance_size; |
2256 DCHECK(instance_size_delta >= 0); | 2208 DCHECK(instance_size_delta >= 0); |
2257 | 2209 |
2258 if (instance_size_delta > 0) { | 2210 if (instance_size_delta > 0) { |
2259 Address address = object->address(); | 2211 Address address = object->address(); |
(...skipping 5958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8218 cache->set(EntryToIndex(entry), *obj); | 8170 cache->set(EntryToIndex(entry), *obj); |
8219 cache->set(EntryToIndex(entry) + 1, *code); | 8171 cache->set(EntryToIndex(entry) + 1, *code); |
8220 cache->ElementAdded(); | 8172 cache->ElementAdded(); |
8221 return cache; | 8173 return cache; |
8222 } | 8174 } |
8223 | 8175 |
8224 | 8176 |
8225 void FixedArray::Shrink(int new_length) { | 8177 void FixedArray::Shrink(int new_length) { |
8226 DCHECK(0 <= new_length && new_length <= length()); | 8178 DCHECK(0 <= new_length && new_length <= length()); |
8227 if (new_length < length()) { | 8179 if (new_length < length()) { |
8228 RightTrimFixedArray<Heap::FROM_MUTATOR>( | 8180 GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>( |
8229 GetHeap(), this, length() - new_length); | 8181 this, length() - new_length); |
8230 } | 8182 } |
8231 } | 8183 } |
8232 | 8184 |
8233 | 8185 |
8234 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | 8186 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( |
8235 Handle<FixedArray> content, | 8187 Handle<FixedArray> content, |
8236 Handle<JSObject> array) { | 8188 Handle<JSObject> array) { |
8237 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); | 8189 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); |
8238 ElementsAccessor* accessor = array->GetElementsAccessor(); | 8190 ElementsAccessor* accessor = array->GetElementsAccessor(); |
8239 Handle<FixedArray> result; | 8191 Handle<FixedArray> result; |
(...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9585 int live_enum = map->EnumLength(); | 9537 int live_enum = map->EnumLength(); |
9586 if (live_enum == kInvalidEnumCacheSentinel) { | 9538 if (live_enum == kInvalidEnumCacheSentinel) { |
9587 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); | 9539 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); |
9588 } | 9540 } |
9589 if (live_enum == 0) return descriptors->ClearEnumCache(); | 9541 if (live_enum == 0) return descriptors->ClearEnumCache(); |
9590 | 9542 |
9591 FixedArray* enum_cache = descriptors->GetEnumCache(); | 9543 FixedArray* enum_cache = descriptors->GetEnumCache(); |
9592 | 9544 |
9593 int to_trim = enum_cache->length() - live_enum; | 9545 int to_trim = enum_cache->length() - live_enum; |
9594 if (to_trim <= 0) return; | 9546 if (to_trim <= 0) return; |
9595 RightTrimFixedArray<Heap::FROM_GC>( | 9547 heap->RightTrimFixedArray<Heap::FROM_GC>( |
9596 heap, descriptors->GetEnumCache(), to_trim); | 9548 descriptors->GetEnumCache(), to_trim); |
9597 | 9549 |
9598 if (!descriptors->HasEnumIndicesCache()) return; | 9550 if (!descriptors->HasEnumIndicesCache()) return; |
9599 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); | 9551 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); |
9600 RightTrimFixedArray<Heap::FROM_GC>(heap, enum_indices_cache, to_trim); | 9552 heap->RightTrimFixedArray<Heap::FROM_GC>(enum_indices_cache, to_trim); |
9601 } | 9553 } |
9602 | 9554 |
9603 | 9555 |
9604 static void TrimDescriptorArray(Heap* heap, | 9556 static void TrimDescriptorArray(Heap* heap, |
9605 Map* map, | 9557 Map* map, |
9606 DescriptorArray* descriptors, | 9558 DescriptorArray* descriptors, |
9607 int number_of_own_descriptors) { | 9559 int number_of_own_descriptors) { |
9608 int number_of_descriptors = descriptors->number_of_descriptors_storage(); | 9560 int number_of_descriptors = descriptors->number_of_descriptors_storage(); |
9609 int to_trim = number_of_descriptors - number_of_own_descriptors; | 9561 int to_trim = number_of_descriptors - number_of_own_descriptors; |
9610 if (to_trim == 0) return; | 9562 if (to_trim == 0) return; |
9611 | 9563 |
9612 RightTrimFixedArray<Heap::FROM_GC>( | 9564 heap->RightTrimFixedArray<Heap::FROM_GC>( |
9613 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize); | 9565 descriptors, to_trim * DescriptorArray::kDescriptorSize); |
9614 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | 9566 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); |
9615 | 9567 |
9616 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); | 9568 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); |
9617 descriptors->Sort(); | 9569 descriptors->Sort(); |
9618 } | 9570 } |
9619 | 9571 |
9620 | 9572 |
9621 // Clear a possible back pointer in case the transition leads to a dead map. | 9573 // Clear a possible back pointer in case the transition leads to a dead map. |
9622 // Return true in case a back pointer has been cleared and false otherwise. | 9574 // Return true in case a back pointer has been cleared and false otherwise. |
9623 static bool ClearBackPointer(Heap* heap, Map* target) { | 9575 static bool ClearBackPointer(Heap* heap, Map* target) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9680 DCHECK(descriptors == GetHeap()->empty_descriptor_array()); | 9632 DCHECK(descriptors == GetHeap()->empty_descriptor_array()); |
9681 } | 9633 } |
9682 } | 9634 } |
9683 | 9635 |
9684 // Note that we never eliminate a transition array, though we might right-trim | 9636 // Note that we never eliminate a transition array, though we might right-trim |
9685 // such that number_of_transitions() == 0. If this assumption changes, | 9637 // such that number_of_transitions() == 0. If this assumption changes, |
9686 // TransitionArray::CopyInsert() will need to deal with the case that a | 9638 // TransitionArray::CopyInsert() will need to deal with the case that a |
9687 // transition array disappeared during GC. | 9639 // transition array disappeared during GC. |
9688 int trim = t->number_of_transitions() - transition_index; | 9640 int trim = t->number_of_transitions() - transition_index; |
9689 if (trim > 0) { | 9641 if (trim > 0) { |
9690 RightTrimFixedArray<Heap::FROM_GC>(heap, t, t->IsSimpleTransition() | 9642 heap->RightTrimFixedArray<Heap::FROM_GC>(t, t->IsSimpleTransition() |
9691 ? trim : trim * TransitionArray::kTransitionSize); | 9643 ? trim : trim * TransitionArray::kTransitionSize); |
9692 } | 9644 } |
9693 DCHECK(HasTransitionArray()); | 9645 DCHECK(HasTransitionArray()); |
9694 } | 9646 } |
9695 | 9647 |
9696 | 9648 |
9697 int Map::Hash() { | 9649 int Map::Hash() { |
9698 // For performance reasons we only hash the 3 most variable fields of a map: | 9650 // For performance reasons we only hash the 3 most variable fields of a map: |
9699 // constructor, prototype and bit_field2. | 9651 // constructor, prototype and bit_field2. |
9700 | 9652 |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9956 code_map->set(dst + kLiteralsOffset, | 9908 code_map->set(dst + kLiteralsOffset, |
9957 code_map->get(src + kLiteralsOffset)); | 9909 code_map->get(src + kLiteralsOffset)); |
9958 code_map->set(dst + kOsrAstIdOffset, | 9910 code_map->set(dst + kOsrAstIdOffset, |
9959 code_map->get(src + kOsrAstIdOffset)); | 9911 code_map->get(src + kOsrAstIdOffset)); |
9960 } | 9912 } |
9961 dst += kEntryLength; | 9913 dst += kEntryLength; |
9962 } | 9914 } |
9963 } | 9915 } |
9964 if (dst != length) { | 9916 if (dst != length) { |
9965 // Always trim even when array is cleared because of heap verifier. | 9917 // Always trim even when array is cleared because of heap verifier. |
9966 RightTrimFixedArray<Heap::FROM_MUTATOR>(GetHeap(), code_map, length - dst); | 9918 GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(code_map, length - dst); |
9967 if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap(); | 9919 if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap(); |
9968 } | 9920 } |
9969 } | 9921 } |
9970 | 9922 |
9971 | 9923 |
9972 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 9924 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { |
9973 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9925 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
9974 DCHECK(shrink_by % kEntryLength == 0); | 9926 DCHECK(shrink_by % kEntryLength == 0); |
9975 DCHECK(shrink_by <= code_map->length() - kEntriesStart); | 9927 DCHECK(shrink_by <= code_map->length() - kEntriesStart); |
9976 // Always trim even when array is cleared because of heap verifier. | 9928 // Always trim even when array is cleared because of heap verifier. |
9977 RightTrimFixedArray<Heap::FROM_GC>(GetHeap(), code_map, shrink_by); | 9929 GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by); |
9978 if (code_map->length() == kEntriesStart) { | 9930 if (code_map->length() == kEntriesStart) { |
9979 ClearOptimizedCodeMap(); | 9931 ClearOptimizedCodeMap(); |
9980 } | 9932 } |
9981 } | 9933 } |
9982 | 9934 |
9983 | 9935 |
9984 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { | 9936 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { |
9985 if (object->IsGlobalObject()) return; | 9937 if (object->IsGlobalObject()) return; |
9986 | 9938 |
9987 // Make sure prototypes are fast objects and their maps have the bit set | 9939 // Make sure prototypes are fast objects and their maps have the bit set |
(...skipping 7063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17051 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17003 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17052 static const char* error_messages_[] = { | 17004 static const char* error_messages_[] = { |
17053 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17005 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17054 }; | 17006 }; |
17055 #undef ERROR_MESSAGES_TEXTS | 17007 #undef ERROR_MESSAGES_TEXTS |
17056 return error_messages_[reason]; | 17008 return error_messages_[reason]; |
17057 } | 17009 } |
17058 | 17010 |
17059 | 17011 |
17060 } } // namespace v8::internal | 17012 } } // namespace v8::internal |
OLD | NEW |