| 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 |