Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/objects.cc

Issue 194783002: Use MigrateToMap instead of set_map to update the map of a JSObject. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comment Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1957 matching lines...) Expand 10 before | Expand all | Expand 10 after
1968 static Handle<Object> NewStorageFor(Isolate* isolate, 1968 static Handle<Object> NewStorageFor(Isolate* isolate,
1969 Handle<Object> object, 1969 Handle<Object> object,
1970 Representation representation) { 1970 Representation representation) {
1971 Heap* heap = isolate->heap(); 1971 Heap* heap = isolate->heap();
1972 CALL_HEAP_FUNCTION(isolate, 1972 CALL_HEAP_FUNCTION(isolate,
1973 object->AllocateNewStorageFor(heap, representation), 1973 object->AllocateNewStorageFor(heap, representation),
1974 Object); 1974 Object);
1975 } 1975 }
1976 1976
1977 1977
1978 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
1979 Handle<Map> new_map,
1980 Handle<Name> name,
1981 Handle<Object> value,
1982 int field_index,
1983 Representation representation) {
1984 Isolate* isolate = object->GetIsolate();
1985
1986 // This method is used to transition to a field. If we are transitioning to a
1987 // double field, allocate new storage.
1988 Handle<Object> storage = NewStorageFor(isolate, value, representation);
1989
1990 if (object->map()->unused_property_fields() == 0) {
1991 int new_unused = new_map->unused_property_fields();
1992 Handle<FixedArray> properties(object->properties());
1993 Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray(
1994 properties, properties->length() + new_unused + 1);
1995 object->set_properties(*values);
1996 }
1997
1998 object->set_map(*new_map);
1999 object->FastPropertyAtPut(field_index, *storage);
2000 }
2001
2002
2003 static MaybeObject* CopyAddFieldDescriptor(Map* map, 1978 static MaybeObject* CopyAddFieldDescriptor(Map* map,
2004 Name* name, 1979 Name* name,
2005 int index, 1980 int index,
2006 PropertyAttributes attributes, 1981 PropertyAttributes attributes,
2007 Representation representation, 1982 Representation representation,
2008 TransitionFlag flag) { 1983 TransitionFlag flag) {
2009 Map* new_map; 1984 Map* new_map;
2010 FieldDescriptor new_field_desc(name, index, attributes, representation); 1985 FieldDescriptor new_field_desc(name, index, attributes, representation);
2011 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); 1986 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag);
2012 if (!maybe_map->To(&new_map)) return maybe_map; 1987 if (!maybe_map->To(&new_map)) return maybe_map;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 2032
2058 // Compute the new index for new field. 2033 // Compute the new index for new field.
2059 int index = object->map()->NextFreePropertyIndex(); 2034 int index = object->map()->NextFreePropertyIndex();
2060 2035
2061 // Allocate new instance descriptors with (name, index) added 2036 // Allocate new instance descriptors with (name, index) added
2062 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; 2037 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
2063 Representation representation = value->OptimalRepresentation(value_type); 2038 Representation representation = value->OptimalRepresentation(value_type);
2064 Handle<Map> new_map = CopyAddFieldDescriptor( 2039 Handle<Map> new_map = CopyAddFieldDescriptor(
2065 handle(object->map()), name, index, attributes, representation, flag); 2040 handle(object->map()), name, index, attributes, representation, flag);
2066 2041
2067 AddFastPropertyUsingMap(object, new_map, name, value, index, representation); 2042 JSObject::MigrateToMap(object, new_map);
2043
2044 if (representation.IsDouble()) {
2045 // Nothing more to be done.
2046 if (value->IsUninitialized()) return;
2047 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
2048 box->set_value(value->Number());
2049 } else {
2050 object->FastPropertyAtPut(index, *value);
2051 }
2068 } 2052 }
2069 2053
2070 2054
2071 static MaybeObject* CopyAddConstantDescriptor(Map* map, 2055 static MaybeObject* CopyAddConstantDescriptor(Map* map,
2072 Name* name, 2056 Name* name,
2073 Object* value, 2057 Object* value,
2074 PropertyAttributes attributes, 2058 PropertyAttributes attributes,
2075 TransitionFlag flag) { 2059 TransitionFlag flag) {
2076 ConstantDescriptor new_constant_desc(name, value, attributes); 2060 ConstantDescriptor new_constant_desc(name, value, attributes);
2077 return map->CopyAddDescriptor(&new_constant_desc, flag); 2061 return map->CopyAddDescriptor(&new_constant_desc, flag);
(...skipping 23 matching lines...) Expand all
2101 // Don't add transitions to special properties with non-trivial 2085 // Don't add transitions to special properties with non-trivial
2102 // attributes. 2086 // attributes.
2103 attributes != NONE) 2087 attributes != NONE)
2104 ? OMIT_TRANSITION 2088 ? OMIT_TRANSITION
2105 : initial_flag; 2089 : initial_flag;
2106 2090
2107 // Allocate new instance descriptors with (name, constant) added. 2091 // Allocate new instance descriptors with (name, constant) added.
2108 Handle<Map> new_map = CopyAddConstantDescriptor( 2092 Handle<Map> new_map = CopyAddConstantDescriptor(
2109 handle(object->map()), name, constant, attributes, flag); 2093 handle(object->map()), name, constant, attributes, flag);
2110 2094
2111 object->set_map(*new_map); 2095 JSObject::MigrateToMap(object, new_map);
2112 } 2096 }
2113 2097
2114 2098
2115 void JSObject::AddSlowProperty(Handle<JSObject> object, 2099 void JSObject::AddSlowProperty(Handle<JSObject> object,
2116 Handle<Name> name, 2100 Handle<Name> name,
2117 Handle<Object> value, 2101 Handle<Object> value,
2118 PropertyAttributes attributes) { 2102 PropertyAttributes attributes) {
2119 ASSERT(!object->HasFastProperties()); 2103 ASSERT(!object->HasFastProperties());
2120 Isolate* isolate = object->GetIsolate(); 2104 Isolate* isolate = object->GetIsolate();
2121 Handle<NameDictionary> dict(object->property_dictionary()); 2105 Handle<NameDictionary> dict(object->property_dictionary());
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 object->set_map(*new_map); 2395 object->set_map(*new_map);
2412 return; 2396 return;
2413 } 2397 }
2414 2398
2415 int total_size = number_of_fields + unused; 2399 int total_size = number_of_fields + unused;
2416 int external = total_size - inobject; 2400 int external = total_size - inobject;
2417 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); 2401 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2418 2402
2419 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); 2403 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2420 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); 2404 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2421 int descriptors = new_map->NumberOfOwnDescriptors(); 2405 int old_nof = old_map->NumberOfOwnDescriptors();
2406 int new_nof = new_map->NumberOfOwnDescriptors();
2422 2407
2423 for (int i = 0; i < descriptors; i++) { 2408 // This method only supports generalizing instances to at least the same
2409 // number of properties.
2410 ASSERT(old_nof <= new_nof);
2411
2412 for (int i = 0; i < old_nof; i++) {
2424 PropertyDetails details = new_descriptors->GetDetails(i); 2413 PropertyDetails details = new_descriptors->GetDetails(i);
2425 if (details.type() != FIELD) continue; 2414 if (details.type() != FIELD) continue;
2426 PropertyDetails old_details = old_descriptors->GetDetails(i); 2415 PropertyDetails old_details = old_descriptors->GetDetails(i);
2427 if (old_details.type() == CALLBACKS) { 2416 if (old_details.type() == CALLBACKS) {
2428 ASSERT(details.representation().IsTagged()); 2417 ASSERT(details.representation().IsTagged());
2429 continue; 2418 continue;
2430 } 2419 }
2431 ASSERT(old_details.type() == CONSTANT || 2420 ASSERT(old_details.type() == CONSTANT ||
2432 old_details.type() == FIELD); 2421 old_details.type() == FIELD);
2433 Object* raw_value = old_details.type() == CONSTANT 2422 Object* raw_value = old_details.type() == CONSTANT
2434 ? old_descriptors->GetValue(i) 2423 ? old_descriptors->GetValue(i)
2435 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); 2424 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
2436 Handle<Object> value(raw_value, isolate); 2425 Handle<Object> value(raw_value, isolate);
2437 if (!old_details.representation().IsDouble() && 2426 if (!old_details.representation().IsDouble() &&
2438 details.representation().IsDouble()) { 2427 details.representation().IsDouble()) {
2439 if (old_details.representation().IsNone()) { 2428 if (old_details.representation().IsNone()) {
2440 value = handle(Smi::FromInt(0), isolate); 2429 value = handle(Smi::FromInt(0), isolate);
2441 } 2430 }
2442 value = NewStorageFor(isolate, value, details.representation()); 2431 value = NewStorageFor(isolate, value, details.representation());
2443 } 2432 }
2444 ASSERT(!(details.representation().IsDouble() && value->IsSmi())); 2433 ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
2445 int target_index = new_descriptors->GetFieldIndex(i) - inobject; 2434 int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2446 if (target_index < 0) target_index += total_size; 2435 if (target_index < 0) target_index += total_size;
2447 array->set(target_index, *value); 2436 array->set(target_index, *value);
2448 } 2437 }
2449 2438
2439 for (int i = old_nof; i < new_nof; i++) {
2440 PropertyDetails details = new_descriptors->GetDetails(i);
2441 if (details.type() != FIELD) continue;
2442 if (details.representation().IsDouble()) {
2443 int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2444 if (target_index < 0) target_index += total_size;
2445 Handle<Object> box = isolate->factory()->NewHeapNumber(0);
2446 array->set(target_index, *box);
2447 }
2448 }
2449
2450 // From here on we cannot fail and we shouldn't GC anymore. 2450 // From here on we cannot fail and we shouldn't GC anymore.
2451 DisallowHeapAllocation no_allocation; 2451 DisallowHeapAllocation no_allocation;
2452 2452
2453 // Copy (real) inobject properties. If necessary, stop at number_of_fields to 2453 // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2454 // avoid overwriting |one_pointer_filler_map|. 2454 // avoid overwriting |one_pointer_filler_map|.
2455 int limit = Min(inobject, number_of_fields); 2455 int limit = Min(inobject, number_of_fields);
2456 for (int i = 0; i < limit; i++) { 2456 for (int i = 0; i < limit; i++) {
2457 object->FastPropertyAtPut(i, array->get(external + i)); 2457 object->FastPropertyAtPut(i, array->get(external + i));
2458 } 2458 }
2459 2459
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after
3852 IsDictionaryElementsKind(obj_kind)) { 3852 IsDictionaryElementsKind(obj_kind)) {
3853 to_kind = obj_kind; 3853 to_kind = obj_kind;
3854 } 3854 }
3855 if (IsDictionaryElementsKind(to_kind)) { 3855 if (IsDictionaryElementsKind(to_kind)) {
3856 NormalizeElements(object); 3856 NormalizeElements(object);
3857 } else { 3857 } else {
3858 TransitionElementsKind(object, to_kind); 3858 TransitionElementsKind(object, to_kind);
3859 } 3859 }
3860 map = MapAsElementsKind(map, to_kind); 3860 map = MapAsElementsKind(map, to_kind);
3861 } 3861 }
3862 int total_size = 3862 JSObject::MigrateToMap(object, map);
3863 map->NumberOfOwnDescriptors() + map->unused_property_fields();
3864 int out_of_object = total_size - map->inobject_properties();
3865 if (out_of_object != object->properties()->length()) {
3866 Isolate* isolate = object->GetIsolate();
3867 Handle<FixedArray> new_properties = isolate->factory()->CopySizeFixedArray(
3868 handle(object->properties()), out_of_object);
3869 object->set_properties(*new_properties);
3870 }
3871 object->set_map(*map);
3872 } 3863 }
3873 3864
3874 3865
3875 void JSObject::MigrateInstance(Handle<JSObject> object) { 3866 void JSObject::MigrateInstance(Handle<JSObject> object) {
3876 // Converting any field to the most specific type will cause the 3867 // Converting any field to the most specific type will cause the
3877 // GeneralizeFieldRepresentation algorithm to create the most general existing 3868 // GeneralizeFieldRepresentation algorithm to create the most general existing
3878 // transition that matches the object. This achieves what is needed. 3869 // transition that matches the object. This achieves what is needed.
3879 Handle<Map> original_map(object->map()); 3870 Handle<Map> original_map(object->map());
3880 GeneralizeFieldRepresentation( 3871 GeneralizeFieldRepresentation(
3881 object, 0, Representation::None(), ALLOW_AS_CONSTANT); 3872 object, 0, Representation::None(), ALLOW_AS_CONSTANT);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3917 return JSObject::AddProperty( 3908 return JSObject::AddProperty(
3918 object, name, value, attributes, kNonStrictMode, 3909 object, name, value, attributes, kNonStrictMode,
3919 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, 3910 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
3920 JSReceiver::OMIT_EXTENSIBILITY_CHECK, 3911 JSReceiver::OMIT_EXTENSIBILITY_CHECK,
3921 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); 3912 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
3922 } 3913 }
3923 3914
3924 // Keep the target CONSTANT if the same value is stored. 3915 // Keep the target CONSTANT if the same value is stored.
3925 // TODO(verwaest): Also support keeping the placeholder 3916 // TODO(verwaest): Also support keeping the placeholder
3926 // (value->IsUninitialized) as constant. 3917 // (value->IsUninitialized) as constant.
3927 if (details.type() == CONSTANT && 3918 if (!value->FitsRepresentation(details.representation()) ||
3928 descriptors->GetValue(descriptor) == *value) { 3919 (details.type() == CONSTANT &&
3929 object->set_map(*transition_map); 3920 descriptors->GetValue(descriptor) != *value)) {
3930 return value; 3921 transition_map = Map::GeneralizeRepresentation(transition_map,
3922 descriptor, value->OptimalRepresentation(), FORCE_FIELD);
3931 } 3923 }
3932 3924
3933 Representation representation = details.representation(); 3925 JSObject::MigrateToMap(object, transition_map);
3934 3926
3935 if (!value->FitsRepresentation(representation) || 3927 // Reload.
3936 details.type() == CONSTANT) { 3928 descriptors = transition_map->instance_descriptors();
3937 transition_map = Map::GeneralizeRepresentation(transition_map, 3929 details = descriptors->GetDetails(descriptor);
3938 descriptor, value->OptimalRepresentation(), FORCE_FIELD); 3930
3939 Object* back = transition_map->GetBackPointer(); 3931 if (details.type() != FIELD) return value;
3940 if (back->IsMap()) { 3932
3941 MigrateToMap(object, handle(Map::cast(back))); 3933 int field_index = descriptors->GetFieldIndex(descriptor);
3942 } 3934 if (details.representation().IsDouble()) {
3943 descriptors = transition_map->instance_descriptors(); 3935 // Nothing more to be done.
3944 representation = descriptors->GetDetails(descriptor).representation(); 3936 if (value->IsUninitialized()) return value;
3937 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index));
3938 box->set_value(value->Number());
3939 } else {
3940 object->FastPropertyAtPut(field_index, *value);
3945 } 3941 }
3946 3942
3947 int field_index = descriptors->GetFieldIndex(descriptor);
3948 AddFastPropertyUsingMap(
3949 object, transition_map, name, value, field_index, representation);
3950 return value; 3943 return value;
3951 } 3944 }
3952 3945
3953 3946
3954 static void SetPropertyToField(LookupResult* lookup, 3947 static void SetPropertyToField(LookupResult* lookup,
3955 Handle<Name> name, 3948 Handle<Name> name,
3956 Handle<Object> value) { 3949 Handle<Object> value) {
3957 Representation representation = lookup->representation(); 3950 Representation representation = lookup->representation();
3958 if (!value->FitsRepresentation(representation) || 3951 if (!value->FitsRepresentation(representation) ||
3959 lookup->type() == CONSTANT) { 3952 lookup->type() == CONSTANT) {
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
4761 // Switch to using the dictionary as the backing storage for elements. 4754 // Switch to using the dictionary as the backing storage for elements.
4762 if (is_arguments) { 4755 if (is_arguments) {
4763 FixedArray::cast(elements())->set(1, dictionary); 4756 FixedArray::cast(elements())->set(1, dictionary);
4764 } else { 4757 } else {
4765 // Set the new map first to satify the elements type assert in 4758 // Set the new map first to satify the elements type assert in
4766 // set_elements(). 4759 // set_elements().
4767 Map* new_map; 4760 Map* new_map;
4768 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), 4761 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
4769 DICTIONARY_ELEMENTS); 4762 DICTIONARY_ELEMENTS);
4770 if (!maybe->To(&new_map)) return maybe; 4763 if (!maybe->To(&new_map)) return maybe;
4764 // TODO(verwaest): Replace by MigrateToMap.
4771 set_map(new_map); 4765 set_map(new_map);
4772 set_elements(dictionary); 4766 set_elements(dictionary);
4773 } 4767 }
4774 4768
4775 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> 4769 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
4776 Increment(); 4770 Increment();
4777 4771
4778 #ifdef DEBUG 4772 #ifdef DEBUG
4779 if (FLAG_trace_normalization) { 4773 if (FLAG_trace_normalization) {
4780 PrintF("Object elements have been normalized:\n"); 4774 PrintF("Object elements have been normalized:\n");
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after
5489 5483
5490 // Make sure that we never go back to fast case. 5484 // Make sure that we never go back to fast case.
5491 dictionary->set_requires_slow_elements(); 5485 dictionary->set_requires_slow_elements();
5492 5486
5493 // Do a map transition, other objects with this map may still 5487 // Do a map transition, other objects with this map may still
5494 // be extensible. 5488 // be extensible.
5495 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5489 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5496 Handle<Map> new_map = Map::Copy(handle(object->map())); 5490 Handle<Map> new_map = Map::Copy(handle(object->map()));
5497 5491
5498 new_map->set_is_extensible(false); 5492 new_map->set_is_extensible(false);
5499 object->set_map(*new_map); 5493 JSObject::MigrateToMap(object, new_map);
5500 ASSERT(!object->map()->is_extensible()); 5494 ASSERT(!object->map()->is_extensible());
5501 5495
5502 if (object->map()->is_observed()) { 5496 if (object->map()->is_observed()) {
5503 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), 5497 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5504 isolate->factory()->the_hole_value()); 5498 isolate->factory()->the_hole_value());
5505 } 5499 }
5506 return object; 5500 return object;
5507 } 5501 }
5508 5502
5509 5503
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
5582 // No existing elements, use a pre-allocated empty backing store 5576 // No existing elements, use a pre-allocated empty backing store
5583 new_element_dictionary = 5577 new_element_dictionary =
5584 isolate->factory()->empty_slow_element_dictionary(); 5578 isolate->factory()->empty_slow_element_dictionary();
5585 } 5579 }
5586 } 5580 }
5587 5581
5588 LookupResult result(isolate); 5582 LookupResult result(isolate);
5589 Handle<Map> old_map(object->map()); 5583 Handle<Map> old_map(object->map());
5590 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); 5584 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
5591 if (result.IsTransition()) { 5585 if (result.IsTransition()) {
5592 Map* transition_map = result.GetTransitionTarget(); 5586 Handle<Map> transition_map(result.GetTransitionTarget());
5593 ASSERT(transition_map->has_dictionary_elements()); 5587 ASSERT(transition_map->has_dictionary_elements());
5594 ASSERT(transition_map->is_frozen()); 5588 ASSERT(transition_map->is_frozen());
5595 ASSERT(!transition_map->is_extensible()); 5589 ASSERT(!transition_map->is_extensible());
5596 object->set_map(transition_map); 5590 JSObject::MigrateToMap(object, transition_map);
5597 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { 5591 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5598 // Create a new descriptor array with fully-frozen properties 5592 // Create a new descriptor array with fully-frozen properties
5599 int num_descriptors = old_map->NumberOfOwnDescriptors(); 5593 int num_descriptors = old_map->NumberOfOwnDescriptors();
5600 Handle<DescriptorArray> new_descriptors = 5594 Handle<DescriptorArray> new_descriptors =
5601 DescriptorArray::CopyUpToAddAttributes( 5595 DescriptorArray::CopyUpToAddAttributes(
5602 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); 5596 handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
5603 Handle<Map> new_map = Map::CopyReplaceDescriptors( 5597 Handle<Map> new_map = Map::CopyReplaceDescriptors(
5604 old_map, new_descriptors, INSERT_TRANSITION, 5598 old_map, new_descriptors, INSERT_TRANSITION,
5605 isolate->factory()->frozen_symbol()); 5599 isolate->factory()->frozen_symbol());
5606 new_map->freeze(); 5600 new_map->freeze();
5607 new_map->set_is_extensible(false); 5601 new_map->set_is_extensible(false);
5608 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 5602 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5609 object->set_map(*new_map); 5603 JSObject::MigrateToMap(object, new_map);
5610 } else { 5604 } else {
5611 // Slow path: need to normalize properties for safety 5605 // Slow path: need to normalize properties for safety
5612 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 5606 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5613 5607
5614 // Create a new map, since other objects with this map may be extensible. 5608 // Create a new map, since other objects with this map may be extensible.
5615 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5609 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5616 Handle<Map> new_map = Map::Copy(handle(object->map())); 5610 Handle<Map> new_map = Map::Copy(handle(object->map()));
5617 new_map->freeze(); 5611 new_map->freeze();
5618 new_map->set_is_extensible(false); 5612 new_map->set_is_extensible(false);
5619 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 5613 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5620 object->set_map(*new_map); 5614 JSObject::MigrateToMap(object, new_map);
5621 5615
5622 // Freeze dictionary-mode properties 5616 // Freeze dictionary-mode properties
5623 FreezeDictionary(object->property_dictionary()); 5617 FreezeDictionary(object->property_dictionary());
5624 } 5618 }
5625 5619
5626 ASSERT(object->map()->has_dictionary_elements()); 5620 ASSERT(object->map()->has_dictionary_elements());
5627 if (!new_element_dictionary.is_null()) { 5621 if (!new_element_dictionary.is_null()) {
5628 object->set_elements(*new_element_dictionary); 5622 object->set_elements(*new_element_dictionary);
5629 } 5623 }
5630 5624
(...skipping 23 matching lines...) Expand all
5654 Handle<Map> new_map; 5648 Handle<Map> new_map;
5655 if (result.IsTransition()) { 5649 if (result.IsTransition()) {
5656 new_map = handle(result.GetTransitionTarget()); 5650 new_map = handle(result.GetTransitionTarget());
5657 ASSERT(new_map->is_observed()); 5651 ASSERT(new_map->is_observed());
5658 } else if (object->map()->CanHaveMoreTransitions()) { 5652 } else if (object->map()->CanHaveMoreTransitions()) {
5659 new_map = Map::CopyForObserved(handle(object->map())); 5653 new_map = Map::CopyForObserved(handle(object->map()));
5660 } else { 5654 } else {
5661 new_map = Map::Copy(handle(object->map())); 5655 new_map = Map::Copy(handle(object->map()));
5662 new_map->set_is_observed(); 5656 new_map->set_is_observed();
5663 } 5657 }
5664 object->set_map(*new_map); 5658 JSObject::MigrateToMap(object, new_map);
5665 } 5659 }
5666 5660
5667 5661
5668 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { 5662 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
5669 Isolate* isolate = object->GetIsolate(); 5663 Isolate* isolate = object->GetIsolate();
5670 CALL_HEAP_FUNCTION(isolate, 5664 CALL_HEAP_FUNCTION(isolate,
5671 isolate->heap()->CopyJSObject(*object), JSObject); 5665 isolate->heap()->CopyJSObject(*object), JSObject);
5672 } 5666 }
5673 5667
5674 5668
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
6384 object, name, getter, setter, attributes, access_control); 6378 object, name, getter, setter, attributes, access_control);
6385 } 6379 }
6386 6380
6387 if (is_observed) { 6381 if (is_observed) {
6388 const char* type = preexists ? "reconfigure" : "add"; 6382 const char* type = preexists ? "reconfigure" : "add";
6389 EnqueueChangeRecord(object, type, name, old_value); 6383 EnqueueChangeRecord(object, type, name, old_value);
6390 } 6384 }
6391 } 6385 }
6392 6386
6393 6387
6394 static bool TryAccessorTransition(JSObject* self, 6388 static bool TryAccessorTransition(Handle<JSObject> self,
6395 Map* transitioned_map, 6389 Handle<Map> transitioned_map,
6396 int target_descriptor, 6390 int target_descriptor,
6397 AccessorComponent component, 6391 AccessorComponent component,
6398 Object* accessor, 6392 Handle<Object> accessor,
6399 PropertyAttributes attributes) { 6393 PropertyAttributes attributes) {
6400 DescriptorArray* descs = transitioned_map->instance_descriptors(); 6394 DescriptorArray* descs = transitioned_map->instance_descriptors();
6401 PropertyDetails details = descs->GetDetails(target_descriptor); 6395 PropertyDetails details = descs->GetDetails(target_descriptor);
6402 6396
6403 // If the transition target was not callbacks, fall back to the slow case. 6397 // If the transition target was not callbacks, fall back to the slow case.
6404 if (details.type() != CALLBACKS) return false; 6398 if (details.type() != CALLBACKS) return false;
6405 Object* descriptor = descs->GetCallbacksObject(target_descriptor); 6399 Object* descriptor = descs->GetCallbacksObject(target_descriptor);
6406 if (!descriptor->IsAccessorPair()) return false; 6400 if (!descriptor->IsAccessorPair()) return false;
6407 6401
6408 Object* target_accessor = AccessorPair::cast(descriptor)->get(component); 6402 Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
6409 PropertyAttributes target_attributes = details.attributes(); 6403 PropertyAttributes target_attributes = details.attributes();
6410 6404
6411 // Reuse transition if adding same accessor with same attributes. 6405 // Reuse transition if adding same accessor with same attributes.
6412 if (target_accessor == accessor && target_attributes == attributes) { 6406 if (target_accessor == *accessor && target_attributes == attributes) {
6413 self->set_map(transitioned_map); 6407 JSObject::MigrateToMap(self, transitioned_map);
6414 return true; 6408 return true;
6415 } 6409 }
6416 6410
6417 // If either not the same accessor, or not the same attributes, fall back to 6411 // If either not the same accessor, or not the same attributes, fall back to
6418 // the slow case. 6412 // the slow case.
6419 return false; 6413 return false;
6420 } 6414 }
6421 6415
6422 6416
6423 static MaybeObject* CopyInsertDescriptor(Map* map, 6417 static MaybeObject* CopyInsertDescriptor(Map* map,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
6465 } 6459 }
6466 } else { 6460 } else {
6467 return false; 6461 return false;
6468 } 6462 }
6469 6463
6470 int descriptor_number = result.GetDescriptorIndex(); 6464 int descriptor_number = result.GetDescriptorIndex();
6471 6465
6472 object->map()->LookupTransition(*object, *name, &result); 6466 object->map()->LookupTransition(*object, *name, &result);
6473 6467
6474 if (result.IsFound()) { 6468 if (result.IsFound()) {
6475 Map* target = result.GetTransitionTarget(); 6469 Handle<Map> target(result.GetTransitionTarget());
6476 ASSERT(target->NumberOfOwnDescriptors() == 6470 ASSERT(target->NumberOfOwnDescriptors() ==
6477 object->map()->NumberOfOwnDescriptors()); 6471 object->map()->NumberOfOwnDescriptors());
6478 // This works since descriptors are sorted in order of addition. 6472 // This works since descriptors are sorted in order of addition.
6479 ASSERT(object->map()->instance_descriptors()-> 6473 ASSERT(object->map()->instance_descriptors()->
6480 GetKey(descriptor_number) == *name); 6474 GetKey(descriptor_number) == *name);
6481 return TryAccessorTransition(*object, target, descriptor_number, 6475 return TryAccessorTransition(object, target, descriptor_number,
6482 component, *accessor, attributes); 6476 component, accessor, attributes);
6483 } 6477 }
6484 } else { 6478 } else {
6485 // If not, lookup a transition. 6479 // If not, lookup a transition.
6486 object->map()->LookupTransition(*object, *name, &result); 6480 object->map()->LookupTransition(*object, *name, &result);
6487 6481
6488 // If there is a transition, try to follow it. 6482 // If there is a transition, try to follow it.
6489 if (result.IsFound()) { 6483 if (result.IsFound()) {
6490 Map* target = result.GetTransitionTarget(); 6484 Handle<Map> target(result.GetTransitionTarget());
6491 int descriptor_number = target->LastAdded(); 6485 int descriptor_number = target->LastAdded();
6492 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) 6486 ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
6493 ->Equals(*name)); 6487 ->Equals(*name));
6494 return TryAccessorTransition(*object, target, descriptor_number, 6488 return TryAccessorTransition(object, target, descriptor_number,
6495 component, *accessor, attributes); 6489 component, accessor, attributes);
6496 } 6490 }
6497 } 6491 }
6498 6492
6499 // If there is no transition yet, add a transition to the a new accessor pair 6493 // If there is no transition yet, add a transition to the a new accessor pair
6500 // containing the accessor. Allocate a new pair if there were no source 6494 // containing the accessor. Allocate a new pair if there were no source
6501 // accessors. Otherwise, copy the pair and modify the accessor. 6495 // accessors. Otherwise, copy the pair and modify the accessor.
6502 Handle<AccessorPair> accessors = source_accessors != NULL 6496 Handle<AccessorPair> accessors = source_accessors != NULL
6503 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) 6497 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6504 : isolate->factory()->NewAccessorPair(); 6498 : isolate->factory()->NewAccessorPair();
6505 accessors->set(component, *accessor); 6499 accessors->set(component, *accessor);
6506 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), 6500 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()),
6507 name, accessors, attributes); 6501 name, accessors, attributes);
6508 object->set_map(*new_map); 6502 JSObject::MigrateToMap(object, new_map);
6509 return true; 6503 return true;
6510 } 6504 }
6511 6505
6512 6506
6513 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, 6507 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6514 Handle<AccessorInfo> info) { 6508 Handle<AccessorInfo> info) {
6515 Isolate* isolate = object->GetIsolate(); 6509 Isolate* isolate = object->GetIsolate();
6516 Factory* factory = isolate->factory(); 6510 Factory* factory = isolate->factory();
6517 Handle<Name> name(Name::cast(info->name())); 6511 Handle<Name> name(Name::cast(info->name()));
6518 6512
(...skipping 3263 matching lines...) Expand 10 before | Expand all | Expand 10 after
9782 // If the value is not a JSReceiver, store the value in the map's 9776 // If the value is not a JSReceiver, store the value in the map's
9783 // constructor field so it can be accessed. Also, set the prototype 9777 // constructor field so it can be accessed. Also, set the prototype
9784 // used for constructing objects to the original object prototype. 9778 // used for constructing objects to the original object prototype.
9785 // See ECMA-262 13.2.2. 9779 // See ECMA-262 13.2.2.
9786 if (!value->IsJSReceiver()) { 9780 if (!value->IsJSReceiver()) {
9787 // Copy the map so this does not affect unrelated functions. 9781 // Copy the map so this does not affect unrelated functions.
9788 // Remove map transitions because they point to maps with a 9782 // Remove map transitions because they point to maps with a
9789 // different prototype. 9783 // different prototype.
9790 Handle<Map> new_map = Map::Copy(handle(function->map())); 9784 Handle<Map> new_map = Map::Copy(handle(function->map()));
9791 9785
9792 function->set_map(*new_map); 9786 JSObject::MigrateToMap(function, new_map);
9793 new_map->set_constructor(*value); 9787 new_map->set_constructor(*value);
9794 new_map->set_non_instance_prototype(true); 9788 new_map->set_non_instance_prototype(true);
9795 Isolate* isolate = new_map->GetIsolate(); 9789 Isolate* isolate = new_map->GetIsolate();
9796 construct_prototype = handle( 9790 construct_prototype = handle(
9797 isolate->context()->native_context()->initial_object_prototype(), 9791 isolate->context()->native_context()->initial_object_prototype(),
9798 isolate); 9792 isolate);
9799 } else { 9793 } else {
9800 function->map()->set_non_instance_prototype(false); 9794 function->map()->set_non_instance_prototype(false);
9801 } 9795 }
9802 9796
(...skipping 2053 matching lines...) Expand 10 before | Expand all | Expand 10 after
11856 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); 11850 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
11857 } 11851 }
11858 11852
11859 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); 11853 Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
11860 if (new_map.is_null()) { 11854 if (new_map.is_null()) {
11861 new_map = Map::Copy(map); 11855 new_map = Map::Copy(map);
11862 Map::PutPrototypeTransition(map, value, new_map); 11856 Map::PutPrototypeTransition(map, value, new_map);
11863 new_map->set_prototype(*value); 11857 new_map->set_prototype(*value);
11864 } 11858 }
11865 ASSERT(new_map->prototype() == *value); 11859 ASSERT(new_map->prototype() == *value);
11866 real_receiver->set_map(*new_map); 11860 JSObject::MigrateToMap(real_receiver, new_map);
11867 11861
11868 if (!dictionary_elements_in_chain && 11862 if (!dictionary_elements_in_chain &&
11869 new_map->DictionaryElementsInPrototypeChainOnly()) { 11863 new_map->DictionaryElementsInPrototypeChainOnly()) {
11870 // If the prototype chain didn't previously have element callbacks, then 11864 // If the prototype chain didn't previously have element callbacks, then
11871 // KeyedStoreICs need to be cleared to ensure any that involve this 11865 // KeyedStoreICs need to be cleared to ensure any that involve this
11872 // map go generic. 11866 // map go generic.
11873 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); 11867 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11874 } 11868 }
11875 11869
11876 heap->ClearInstanceofCache(); 11870 heap->ClearInstanceofCache();
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
12197 return value; 12191 return value;
12198 } 12192 }
12199 // Change elements kind from Smi-only to generic FAST if necessary. 12193 // Change elements kind from Smi-only to generic FAST if necessary.
12200 if (object->HasFastSmiElements() && !value->IsSmi()) { 12194 if (object->HasFastSmiElements() && !value->IsSmi()) {
12201 ElementsKind kind = object->HasFastHoleyElements() 12195 ElementsKind kind = object->HasFastHoleyElements()
12202 ? FAST_HOLEY_ELEMENTS 12196 ? FAST_HOLEY_ELEMENTS
12203 : FAST_ELEMENTS; 12197 : FAST_ELEMENTS;
12204 12198
12205 UpdateAllocationSite(object, kind); 12199 UpdateAllocationSite(object, kind);
12206 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12200 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12207 object->set_map(*new_map); 12201 JSObject::MigrateToMap(object, new_map);
12208 ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); 12202 ASSERT(IsFastObjectElementsKind(object->GetElementsKind()));
12209 } 12203 }
12210 // Increase backing store capacity if that's been decided previously. 12204 // Increase backing store capacity if that's been decided previously.
12211 if (new_capacity != capacity) { 12205 if (new_capacity != capacity) {
12212 SetFastElementsCapacitySmiMode smi_mode = 12206 SetFastElementsCapacitySmiMode smi_mode =
12213 value->IsSmi() && object->HasFastSmiElements() 12207 value->IsSmi() && object->HasFastSmiElements()
12214 ? kAllowSmiElements 12208 ? kAllowSmiElements
12215 : kDontAllowSmiElements; 12209 : kDontAllowSmiElements;
12216 Handle<FixedArray> new_elements = 12210 Handle<FixedArray> new_elements =
12217 SetFastElementsCapacityAndLength(object, new_capacity, array_length, 12211 SetFastElementsCapacityAndLength(object, new_capacity, array_length,
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
12886 (IsFastSmiOrObjectElementsKind(from_kind) && 12880 (IsFastSmiOrObjectElementsKind(from_kind) &&
12887 IsFastSmiOrObjectElementsKind(to_kind)) || 12881 IsFastSmiOrObjectElementsKind(to_kind)) ||
12888 (from_kind == FAST_DOUBLE_ELEMENTS && 12882 (from_kind == FAST_DOUBLE_ELEMENTS &&
12889 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12883 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12890 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12884 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12891 // No change is needed to the elements() buffer, the transition 12885 // No change is needed to the elements() buffer, the transition
12892 // only requires a map change. 12886 // only requires a map change.
12893 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); 12887 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
12894 Map* new_map; 12888 Map* new_map;
12895 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 12889 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
12890 // TODO(verwaest): Replace by MigrateToMap.
12896 set_map(new_map); 12891 set_map(new_map);
12897 if (FLAG_trace_elements_transitions) { 12892 if (FLAG_trace_elements_transitions) {
12898 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 12893 FixedArrayBase* elms = FixedArrayBase::cast(elements());
12899 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); 12894 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
12900 } 12895 }
12901 return this; 12896 return this;
12902 } 12897 }
12903 12898
12904 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 12899 FixedArrayBase* elms = FixedArrayBase::cast(elements());
12905 uint32_t capacity = static_cast<uint32_t>(elms->length()); 12900 uint32_t capacity = static_cast<uint32_t>(elms->length());
(...skipping 3592 matching lines...) Expand 10 before | Expand all | Expand 10 after
16498 #define ERROR_MESSAGES_TEXTS(C, T) T, 16493 #define ERROR_MESSAGES_TEXTS(C, T) T,
16499 static const char* error_messages_[] = { 16494 static const char* error_messages_[] = {
16500 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16495 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16501 }; 16496 };
16502 #undef ERROR_MESSAGES_TEXTS 16497 #undef ERROR_MESSAGES_TEXTS
16503 return error_messages_[reason]; 16498 return error_messages_[reason];
16504 } 16499 }
16505 16500
16506 16501
16507 } } // namespace v8::internal 16502 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698