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 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 if (object->IsGlobalObject()) { | 754 if (object->IsGlobalObject()) { |
755 PropertyDetails details = dictionary->DetailsAt(entry); | 755 PropertyDetails details = dictionary->DetailsAt(entry); |
756 if (details.IsDontDelete()) { | 756 if (details.IsDontDelete()) { |
757 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); | 757 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
758 // When forced to delete global properties, we have to make a | 758 // When forced to delete global properties, we have to make a |
759 // map change to invalidate any ICs that think they can load | 759 // map change to invalidate any ICs that think they can load |
760 // from the DontDelete cell without checking if it contains | 760 // from the DontDelete cell without checking if it contains |
761 // the hole value. | 761 // the hole value. |
762 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 762 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
763 ASSERT(new_map->is_dictionary_map()); | 763 ASSERT(new_map->is_dictionary_map()); |
764 object->set_map(*new_map); | 764 JSObject::MigrateToMap(object, new_map); |
765 } | 765 } |
766 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 766 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
767 Handle<Object> value = isolate->factory()->the_hole_value(); | 767 Handle<Object> value = isolate->factory()->the_hole_value(); |
768 PropertyCell::SetValueInferType(cell, value); | 768 PropertyCell::SetValueInferType(cell, value); |
769 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 769 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
770 } else { | 770 } else { |
771 Handle<Object> deleted( | 771 Handle<Object> deleted( |
772 NameDictionary::DeleteProperty(dictionary, entry, mode)); | 772 NameDictionary::DeleteProperty(dictionary, entry, mode)); |
773 if (*deleted == isolate->heap()->true_value()) { | 773 if (*deleted == isolate->heap()->true_value()) { |
774 Handle<NameDictionary> new_properties = | 774 Handle<NameDictionary> new_properties = |
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2138 Isolate* isolate = object->GetIsolate(); | 2138 Isolate* isolate = object->GetIsolate(); |
2139 Handle<Map> old_map(object->map()); | 2139 Handle<Map> old_map(object->map()); |
2140 int number_of_fields = new_map->NumberOfFields(); | 2140 int number_of_fields = new_map->NumberOfFields(); |
2141 int inobject = new_map->inobject_properties(); | 2141 int inobject = new_map->inobject_properties(); |
2142 int unused = new_map->unused_property_fields(); | 2142 int unused = new_map->unused_property_fields(); |
2143 | 2143 |
2144 // Nothing to do if no functions were converted to fields and no smis were | 2144 // Nothing to do if no functions were converted to fields and no smis were |
2145 // converted to doubles. | 2145 // converted to doubles. |
2146 if (!old_map->InstancesNeedRewriting( | 2146 if (!old_map->InstancesNeedRewriting( |
2147 *new_map, number_of_fields, inobject, unused)) { | 2147 *new_map, number_of_fields, inobject, unused)) { |
2148 // Writing the new map here does not require synchronization since it does | |
2149 // not change the actual object size. | |
2150 object->synchronized_set_map(*new_map); | 2148 object->synchronized_set_map(*new_map); |
2151 return; | 2149 return; |
2152 } | 2150 } |
2153 | 2151 |
2154 int total_size = number_of_fields + unused; | 2152 int total_size = number_of_fields + unused; |
2155 int external = total_size - inobject; | 2153 int external = total_size - inobject; |
2156 | 2154 |
2157 if ((old_map->unused_property_fields() == 0) && | 2155 if ((old_map->unused_property_fields() == 0) && |
2158 (new_map->GetBackPointer() == *old_map)) { | 2156 (new_map->GetBackPointer() == *old_map)) { |
2159 // This migration is a transition from a map that has run out out property | 2157 // This migration is a transition from a map that has run out out property |
(...skipping 13 matching lines...) Expand all Loading... |
2173 ASSERT(details.type() == FIELD); | 2171 ASSERT(details.type() == FIELD); |
2174 int target_index = details.field_index() - inobject; | 2172 int target_index = details.field_index() - inobject; |
2175 ASSERT(target_index >= 0); // Must be a backing store index. | 2173 ASSERT(target_index >= 0); // Must be a backing store index. |
2176 new_storage->set(target_index, *value); | 2174 new_storage->set(target_index, *value); |
2177 | 2175 |
2178 // From here on we cannot fail and we shouldn't GC anymore. | 2176 // From here on we cannot fail and we shouldn't GC anymore. |
2179 DisallowHeapAllocation no_allocation; | 2177 DisallowHeapAllocation no_allocation; |
2180 | 2178 |
2181 // Set the new property value and do the map transition. | 2179 // Set the new property value and do the map transition. |
2182 object->set_properties(*new_storage); | 2180 object->set_properties(*new_storage); |
2183 // Writing the new map here does not require synchronization since it does | 2181 object->synchronized_set_map(*new_map); |
2184 // not change the actual object size. | |
2185 object->set_map(*new_map); | |
2186 return; | 2182 return; |
2187 } | 2183 } |
2188 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); | 2184 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
2189 | 2185 |
2190 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2186 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
2191 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); | 2187 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); |
2192 int old_nof = old_map->NumberOfOwnDescriptors(); | 2188 int old_nof = old_map->NumberOfOwnDescriptors(); |
2193 int new_nof = new_map->NumberOfOwnDescriptors(); | 2189 int new_nof = new_map->NumberOfOwnDescriptors(); |
2194 | 2190 |
2195 // This method only supports generalizing instances to at least the same | 2191 // This method only supports generalizing instances to at least the same |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2247 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); | 2243 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); |
2248 object->FastPropertyAtPut(index, array->get(external + i)); | 2244 object->FastPropertyAtPut(index, array->get(external + i)); |
2249 } | 2245 } |
2250 | 2246 |
2251 // Create filler object past the new instance size. | 2247 // Create filler object past the new instance size. |
2252 int new_instance_size = new_map->instance_size(); | 2248 int new_instance_size = new_map->instance_size(); |
2253 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2249 int instance_size_delta = old_map->instance_size() - new_instance_size; |
2254 ASSERT(instance_size_delta >= 0); | 2250 ASSERT(instance_size_delta >= 0); |
2255 Address address = object->address() + new_instance_size; | 2251 Address address = object->address() + new_instance_size; |
2256 | 2252 |
2257 // The trimming is performed on a newly allocated object, which is on a | 2253 Heap* heap = isolate->heap(); |
2258 // freshly allocated page or on an already swept page. Hence, the sweeper | |
2259 // thread can not get confused with the filler creation. No synchronization | |
2260 // needed. | |
2261 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); | |
2262 | 2254 |
2263 // If there are properties in the new backing store, trim it to the correct | 2255 // If there are properties in the new backing store, trim it to the correct |
2264 // size and install the backing store into the object. | 2256 // size and install the backing store into the object. |
2265 if (external > 0) { | 2257 if (external > 0) { |
2266 RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject); | 2258 RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject); |
2267 object->set_properties(*array); | 2259 object->set_properties(*array); |
2268 } | 2260 } |
2269 | 2261 |
2270 // The trimming is performed on a newly allocated object, which is on a | 2262 heap->CreateFillerObjectAt(address, instance_size_delta); |
2271 // freshly allocated page or on an already swept page. Hence, the sweeper | 2263 heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR); |
2272 // thread can not get confused with the filler creation. No synchronization | 2264 |
2273 // needed. | 2265 // We are storing the new map using release store after creating a filler for |
2274 object->set_map(*new_map); | 2266 // the left-over space to avoid races with the sweeper thread. |
| 2267 object->synchronized_set_map(*new_map); |
2275 } | 2268 } |
2276 | 2269 |
2277 | 2270 |
2278 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2271 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2279 int modify_index, | 2272 int modify_index, |
2280 Representation new_representation, | 2273 Representation new_representation, |
2281 Handle<HeapType> new_field_type, | 2274 Handle<HeapType> new_field_type, |
2282 StoreMode store_mode) { | 2275 StoreMode store_mode) { |
2283 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2276 Handle<Map> new_map = Map::GeneralizeRepresentation( |
2284 handle(object->map()), modify_index, new_representation, | 2277 handle(object->map()), modify_index, new_representation, |
(...skipping 2426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4711 | 4704 |
4712 // Allocate new map. | 4705 // Allocate new map. |
4713 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 4706 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
4714 new_map->set_dictionary_map(false); | 4707 new_map->set_dictionary_map(false); |
4715 | 4708 |
4716 if (instance_descriptor_length == 0) { | 4709 if (instance_descriptor_length == 0) { |
4717 DisallowHeapAllocation no_gc; | 4710 DisallowHeapAllocation no_gc; |
4718 ASSERT_LE(unused_property_fields, inobject_props); | 4711 ASSERT_LE(unused_property_fields, inobject_props); |
4719 // Transform the object. | 4712 // Transform the object. |
4720 new_map->set_unused_property_fields(inobject_props); | 4713 new_map->set_unused_property_fields(inobject_props); |
4721 object->set_map(*new_map); | 4714 object->synchronized_set_map(*new_map); |
4722 object->set_properties(isolate->heap()->empty_fixed_array()); | 4715 object->set_properties(isolate->heap()->empty_fixed_array()); |
4723 // Check that it really works. | 4716 // Check that it really works. |
4724 ASSERT(object->HasFastProperties()); | 4717 ASSERT(object->HasFastProperties()); |
4725 return; | 4718 return; |
4726 } | 4719 } |
4727 | 4720 |
4728 // Allocate the instance descriptor. | 4721 // Allocate the instance descriptor. |
4729 Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( | 4722 Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( |
4730 isolate, instance_descriptor_length); | 4723 isolate, instance_descriptor_length); |
4731 | 4724 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4792 } | 4785 } |
4793 ASSERT(current_offset == number_of_fields); | 4786 ASSERT(current_offset == number_of_fields); |
4794 | 4787 |
4795 descriptors->Sort(); | 4788 descriptors->Sort(); |
4796 | 4789 |
4797 DisallowHeapAllocation no_gc; | 4790 DisallowHeapAllocation no_gc; |
4798 new_map->InitializeDescriptors(*descriptors); | 4791 new_map->InitializeDescriptors(*descriptors); |
4799 new_map->set_unused_property_fields(unused_property_fields); | 4792 new_map->set_unused_property_fields(unused_property_fields); |
4800 | 4793 |
4801 // Transform the object. | 4794 // Transform the object. |
4802 object->set_map(*new_map); | 4795 object->synchronized_set_map(*new_map); |
4803 | 4796 |
4804 object->set_properties(*fields); | 4797 object->set_properties(*fields); |
4805 ASSERT(object->IsJSObject()); | 4798 ASSERT(object->IsJSObject()); |
4806 | 4799 |
4807 // Check that it really works. | 4800 // Check that it really works. |
4808 ASSERT(object->HasFastProperties()); | 4801 ASSERT(object->HasFastProperties()); |
4809 } | 4802 } |
4810 | 4803 |
4811 | 4804 |
4812 void JSObject::ResetElements(Handle<JSObject> object) { | 4805 void JSObject::ResetElements(Handle<JSObject> object) { |
(...skipping 1821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6634 Handle<Object> structure, | 6627 Handle<Object> structure, |
6635 PropertyAttributes attributes) { | 6628 PropertyAttributes attributes) { |
6636 // Normalize object to make this operation simple. | 6629 // Normalize object to make this operation simple. |
6637 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 6630 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
6638 | 6631 |
6639 // For the global object allocate a new map to invalidate the global inline | 6632 // For the global object allocate a new map to invalidate the global inline |
6640 // caches which have a global property cell reference directly in the code. | 6633 // caches which have a global property cell reference directly in the code. |
6641 if (object->IsGlobalObject()) { | 6634 if (object->IsGlobalObject()) { |
6642 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 6635 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
6643 ASSERT(new_map->is_dictionary_map()); | 6636 ASSERT(new_map->is_dictionary_map()); |
6644 object->set_map(*new_map); | 6637 JSObject::MigrateToMap(object, new_map); |
6645 | 6638 |
6646 // When running crankshaft, changing the map is not enough. We | 6639 // When running crankshaft, changing the map is not enough. We |
6647 // need to deoptimize all functions that rely on this global | 6640 // need to deoptimize all functions that rely on this global |
6648 // object. | 6641 // object. |
6649 Deoptimizer::DeoptimizeGlobalObject(*object); | 6642 Deoptimizer::DeoptimizeGlobalObject(*object); |
6650 } | 6643 } |
6651 | 6644 |
6652 // Update the dictionary with the new CALLBACKS property. | 6645 // Update the dictionary with the new CALLBACKS property. |
6653 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6646 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
6654 SetNormalizedProperty(object, name, structure, details); | 6647 SetNormalizedProperty(object, name, structure, details); |
(...skipping 10335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16990 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16983 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16991 static const char* error_messages_[] = { | 16984 static const char* error_messages_[] = { |
16992 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16985 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16993 }; | 16986 }; |
16994 #undef ERROR_MESSAGES_TEXTS | 16987 #undef ERROR_MESSAGES_TEXTS |
16995 return error_messages_[reason]; | 16988 return error_messages_[reason]; |
16996 } | 16989 } |
16997 | 16990 |
16998 | 16991 |
16999 } } // namespace v8::internal | 16992 } } // namespace v8::internal |
OLD | NEW |