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

Side by Side Diff: src/objects.cc

Issue 10909007: Sharing of descriptor arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: u Created 8 years, 3 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 } 1536 }
1537 return true; 1537 return true;
1538 } 1538 }
1539 1539
1540 1540
1541 MaybeObject* JSObject::AddFastProperty(String* name, 1541 MaybeObject* JSObject::AddFastProperty(String* name,
1542 Object* value, 1542 Object* value,
1543 PropertyAttributes attributes, 1543 PropertyAttributes attributes,
1544 StoreFromKeyed store_mode) { 1544 StoreFromKeyed store_mode) {
1545 ASSERT(!IsJSGlobalProxy()); 1545 ASSERT(!IsJSGlobalProxy());
1546 ASSERT(map()->instance_descriptors()->Search(name) == 1546 ASSERT(DescriptorArray::kNotFound ==
1547 DescriptorArray::kNotFound); 1547 map()->instance_descriptors()->Search(
1548 name, map()->NumberOfOwnDescriptors()));
1548 1549
1549 // Normalize the object if the name is an actual string (not the 1550 // Normalize the object if the name is an actual string (not the
1550 // hidden symbols) and is not a real identifier. 1551 // hidden symbols) and is not a real identifier.
1551 // Normalize the object if it will have too many fast properties. 1552 // Normalize the object if it will have too many fast properties.
1552 Isolate* isolate = GetHeap()->isolate(); 1553 Isolate* isolate = GetHeap()->isolate();
1553 StringInputBuffer buffer(name); 1554 StringInputBuffer buffer(name);
1554 if ((!IsIdentifier(isolate->unicode_cache(), &buffer) 1555 if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
1555 && name != isolate->heap()->hidden_symbol()) || 1556 && name != isolate->heap()->hidden_symbol()) ||
1556 (map()->unused_property_fields() == 0 && 1557 (map()->unused_property_fields() == 0 &&
1557 TooManyFastProperties(properties()->length(), store_mode))) { 1558 TooManyFastProperties(properties()->length(), store_mode))) {
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 } 2150 }
2150 2151
2151 2152
2152 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, 2153 void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
2153 Handle<Object> descriptors) { 2154 Handle<Object> descriptors) {
2154 Isolate* isolate = map->GetIsolate(); 2155 Isolate* isolate = map->GetIsolate();
2155 Handle<DescriptorArray> array(map->instance_descriptors()); 2156 Handle<DescriptorArray> array(map->instance_descriptors());
2156 v8::NeanderArray callbacks(descriptors); 2157 v8::NeanderArray callbacks(descriptors);
2157 int nof_callbacks = callbacks.length(); 2158 int nof_callbacks = callbacks.length();
2158 int descriptor_count = array->number_of_descriptors(); 2159 int descriptor_count = array->number_of_descriptors();
2160 ASSERT(descriptor_count == map->NumberOfOwnDescriptors());
2159 2161
2160 // Ensure the keys are symbols before writing them into the instance 2162 // Ensure the keys are symbols before writing them into the instance
2161 // descriptor. Since it may cause a GC, it has to be done before we 2163 // descriptor. Since it may cause a GC, it has to be done before we
2162 // temporarily put the heap in an invalid state while appending descriptors. 2164 // temporarily put the heap in an invalid state while appending descriptors.
2163 for (int i = 0; i < nof_callbacks; ++i) { 2165 for (int i = 0; i < nof_callbacks; ++i) {
2164 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); 2166 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
2165 Handle<String> key = 2167 Handle<String> key =
2166 isolate->factory()->SymbolFromString( 2168 isolate->factory()->SymbolFromString(
2167 Handle<String>(String::cast(entry->name()))); 2169 Handle<String>(String::cast(entry->name())));
2168 entry->set_name(*key); 2170 entry->set_name(*key);
2169 } 2171 }
2170 2172
2171 Handle<DescriptorArray> result = 2173 Handle<DescriptorArray> result =
2172 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks); 2174 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
2173 2175
2174 // Ensure that marking will not progress and change color of objects. 2176 // Ensure that marking will not progress and change color of objects.
2175 DescriptorArray::WhitenessWitness witness(*result); 2177 DescriptorArray::WhitenessWitness witness(*result);
2176 2178
2177 // Copy the descriptors from the array. 2179 // Copy the descriptors from the array.
2178 if (0 < descriptor_count) { 2180 for (int i = 0; i < descriptor_count; i++) {
2179 for (int i = 0; i < descriptor_count; i++) { 2181 result->CopyFrom(i, *array, i, witness);
2180 result->CopyFrom(i, *array, i, witness);
2181 }
2182 } 2182 }
2183 2183
2184 // After this point the GC is not allowed to run anymore until the map is in a 2184 // After this point the GC is not allowed to run anymore until the map is in a
2185 // consistent state again, i.e., all the descriptors are appended and the 2185 // consistent state again, i.e., all the descriptors are appended and the
2186 // descriptor array is trimmed to the right size. 2186 // descriptor array is trimmed to the right size.
2187 Map::SetDescriptors(map, result); 2187 Map::SetDescriptors(map, result);
2188 2188
2189 // Fill in new callback descriptors. Process the callbacks from 2189 // Fill in new callback descriptors. Process the callbacks from
2190 // back to front so that the last callback with a given name takes 2190 // back to front so that the last callback with a given name takes
2191 // precedence over previously added callbacks with that name. 2191 // precedence over previously added callbacks with that name.
2192 int nof = descriptor_count;
2192 for (int i = nof_callbacks - 1; i >= 0; i--) { 2193 for (int i = nof_callbacks - 1; i >= 0; i--) {
2193 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); 2194 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2194 String* key = String::cast(entry->name()); 2195 String* key = String::cast(entry->name());
2195 // Check if a descriptor with this name already exists before writing. 2196 // Check if a descriptor with this name already exists before writing.
2196 if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) == 2197 if (result->Search(key, nof) == DescriptorArray::kNotFound) {
2197 DescriptorArray::kNotFound) {
2198 CallbacksDescriptor desc(key, entry, entry->property_attributes()); 2198 CallbacksDescriptor desc(key, entry, entry->property_attributes());
2199 map->AppendDescriptor(&desc, witness); 2199 map->AppendDescriptor(&desc, witness);
2200 nof += 1;
2200 } 2201 }
2201 } 2202 }
2202 2203
2203 int new_number_of_descriptors = map->NumberOfOwnDescriptors(); 2204 ASSERT(nof == map->NumberOfOwnDescriptors());
2205
2204 // Reinstall the original descriptor array if no new elements were added. 2206 // Reinstall the original descriptor array if no new elements were added.
2205 if (new_number_of_descriptors == descriptor_count) { 2207 if (nof == descriptor_count) {
2206 Map::SetDescriptors(map, array); 2208 Map::SetDescriptors(map, array);
2207 return; 2209 return;
2208 } 2210 }
2209 2211
2210 // If duplicates were detected, trim the descriptor array to the right size. 2212 // If duplicates were detected, trim the descriptor array to the right size.
2211 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors); 2213 int new_array_size = DescriptorArray::LengthFor(nof);
2212 if (new_array_size < result->length()) { 2214 if (new_array_size < result->length()) {
2213 RightTrimFixedArray<FROM_MUTATOR>( 2215 RightTrimFixedArray<FROM_MUTATOR>(
2214 isolate->heap(), *result, result->length() - new_array_size); 2216 isolate->heap(), *result, result->length() - new_array_size);
2215 } 2217 }
2216 } 2218 }
2217 2219
2218 2220
2219 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { 2221 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2220 ASSERT(!map.is_null()); 2222 ASSERT(!map.is_null());
2221 for (int i = 0; i < maps->length(); ++i) { 2223 for (int i = 0; i < maps->length(); ++i) {
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after
3268 if (!HasFastProperties()) return this; 3270 if (!HasFastProperties()) return this;
3269 3271
3270 // The global object is always normalized. 3272 // The global object is always normalized.
3271 ASSERT(!IsGlobalObject()); 3273 ASSERT(!IsGlobalObject());
3272 // JSGlobalProxy must never be normalized 3274 // JSGlobalProxy must never be normalized
3273 ASSERT(!IsJSGlobalProxy()); 3275 ASSERT(!IsJSGlobalProxy());
3274 3276
3275 Map* map_of_this = map(); 3277 Map* map_of_this = map();
3276 3278
3277 // Allocate new content. 3279 // Allocate new content.
3278 int property_count = map_of_this->NumberOfDescribedProperties(); 3280 int real_size = map_of_this->NumberOfOwnDescriptors();
3281 int property_count =
3282 map_of_this->NumberOfDescribedProperties(OWN_DESCRIPTORS);
3279 if (expected_additional_properties > 0) { 3283 if (expected_additional_properties > 0) {
3280 property_count += expected_additional_properties; 3284 property_count += expected_additional_properties;
3281 } else { 3285 } else {
3282 property_count += 2; // Make space for two more properties. 3286 property_count += 2; // Make space for two more properties.
3283 } 3287 }
3284 StringDictionary* dictionary; 3288 StringDictionary* dictionary;
3285 { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); 3289 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3286 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3290 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3287 }
3288 3291
3289 DescriptorArray* descs = map_of_this->instance_descriptors(); 3292 DescriptorArray* descs = map_of_this->instance_descriptors();
3290 for (int i = 0; i < descs->number_of_descriptors(); i++) { 3293 for (int i = 0; i < real_size; i++) {
3291 PropertyDetails details = descs->GetDetails(i); 3294 PropertyDetails details = descs->GetDetails(i);
3292 switch (details.type()) { 3295 switch (details.type()) {
3293 case CONSTANT_FUNCTION: { 3296 case CONSTANT_FUNCTION: {
3294 PropertyDetails d = PropertyDetails(details.attributes(), 3297 PropertyDetails d = PropertyDetails(details.attributes(),
3295 NORMAL, 3298 NORMAL,
3296 details.descriptor_index()); 3299 details.descriptor_index());
3297 Object* value = descs->GetConstantFunction(i); 3300 Object* value = descs->GetConstantFunction(i);
3298 MaybeObject* maybe_dictionary = 3301 MaybeObject* maybe_dictionary =
3299 dictionary->Add(descs->GetKey(i), value, d); 3302 dictionary->Add(descs->GetKey(i), value, d);
3300 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3303 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
(...skipping 24 matching lines...) Expand all
3325 case TRANSITION: 3328 case TRANSITION:
3326 case NONEXISTENT: 3329 case NONEXISTENT:
3327 UNREACHABLE(); 3330 UNREACHABLE();
3328 break; 3331 break;
3329 } 3332 }
3330 } 3333 }
3331 3334
3332 Heap* current_heap = GetHeap(); 3335 Heap* current_heap = GetHeap();
3333 3336
3334 // Copy the next enumeration index from instance descriptor. 3337 // Copy the next enumeration index from instance descriptor.
3335 int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); 3338 dictionary->SetNextEnumerationIndex(real_size + 1);
3336 dictionary->SetNextEnumerationIndex(index);
3337 3339
3338 Map* new_map; 3340 Map* new_map;
3339 MaybeObject* maybe_map = 3341 MaybeObject* maybe_map =
3340 current_heap->isolate()->context()->native_context()-> 3342 current_heap->isolate()->context()->native_context()->
3341 normalized_map_cache()->Get(this, mode); 3343 normalized_map_cache()->Get(this, mode);
3342 if (!maybe_map->To(&new_map)) return maybe_map; 3344 if (!maybe_map->To(&new_map)) return maybe_map;
3343 ASSERT(new_map->is_dictionary_map()); 3345 ASSERT(new_map->is_dictionary_map());
3344 3346
3345 // We have now successfully allocated all the necessary objects. 3347 // We have now successfully allocated all the necessary objects.
3346 // Changes can now be made with the guarantee that all of them take effect. 3348 // Changes can now be made with the guarantee that all of them take effect.
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
3672 ASSERT(!IsJSGlobalProxy()); 3674 ASSERT(!IsJSGlobalProxy());
3673 Object* inline_value; 3675 Object* inline_value;
3674 if (HasFastProperties()) { 3676 if (HasFastProperties()) {
3675 // If the object has fast properties, check whether the first slot 3677 // If the object has fast properties, check whether the first slot
3676 // in the descriptor array matches the hidden symbol. Since the 3678 // in the descriptor array matches the hidden symbol. Since the
3677 // hidden symbols hash code is zero (and no other string has hash 3679 // hidden symbols hash code is zero (and no other string has hash
3678 // code zero) it will always occupy the first entry if present. 3680 // code zero) it will always occupy the first entry if present.
3679 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3681 DescriptorArray* descriptors = this->map()->instance_descriptors();
3680 if (descriptors->number_of_descriptors() > 0) { 3682 if (descriptors->number_of_descriptors() > 0) {
3681 int sorted_index = descriptors->GetSortedKeyIndex(0); 3683 int sorted_index = descriptors->GetSortedKeyIndex(0);
3682 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) { 3684 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
3685 sorted_index < map()->NumberOfOwnDescriptors()) {
3683 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3686 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3684 inline_value = this->FastPropertyAt( 3687 inline_value =
3685 descriptors->GetFieldIndex(sorted_index)); 3688 this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index));
3686 } else { 3689 } else {
3687 inline_value = GetHeap()->undefined_value(); 3690 inline_value = GetHeap()->undefined_value();
3688 } 3691 }
3689 } else { 3692 } else {
3690 inline_value = GetHeap()->undefined_value(); 3693 inline_value = GetHeap()->undefined_value();
3691 } 3694 }
3692 } else { 3695 } else {
3693 PropertyAttributes attributes; 3696 PropertyAttributes attributes;
3694 // You can't install a getter on a property indexed by the hidden symbol, 3697 // You can't install a getter on a property indexed by the hidden symbol,
3695 // so we can be sure that GetLocalPropertyPostInterceptor returns a real 3698 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3740 // for hidden properties yet. 3743 // for hidden properties yet.
3741 ASSERT(HasHiddenProperties() != value->IsSmi()); 3744 ASSERT(HasHiddenProperties() != value->IsSmi());
3742 if (HasFastProperties()) { 3745 if (HasFastProperties()) {
3743 // If the object has fast properties, check whether the first slot 3746 // If the object has fast properties, check whether the first slot
3744 // in the descriptor array matches the hidden symbol. Since the 3747 // in the descriptor array matches the hidden symbol. Since the
3745 // hidden symbols hash code is zero (and no other string has hash 3748 // hidden symbols hash code is zero (and no other string has hash
3746 // code zero) it will always occupy the first entry if present. 3749 // code zero) it will always occupy the first entry if present.
3747 DescriptorArray* descriptors = this->map()->instance_descriptors(); 3750 DescriptorArray* descriptors = this->map()->instance_descriptors();
3748 if (descriptors->number_of_descriptors() > 0) { 3751 if (descriptors->number_of_descriptors() > 0) {
3749 int sorted_index = descriptors->GetSortedKeyIndex(0); 3752 int sorted_index = descriptors->GetSortedKeyIndex(0);
3750 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) { 3753 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
3754 sorted_index < map()->NumberOfOwnDescriptors()) {
3751 ASSERT(descriptors->GetType(sorted_index) == FIELD); 3755 ASSERT(descriptors->GetType(sorted_index) == FIELD);
3752 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), 3756 this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
3753 value); 3757 value);
3754 return this; 3758 return this;
3755 } 3759 }
3756 } 3760 }
3757 } 3761 }
3758 MaybeObject* store_result = 3762 MaybeObject* store_result =
3759 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), 3763 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3760 value, 3764 value,
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
4178 } 4182 }
4179 4183
4180 4184
4181 void Map::SetDescriptors(Handle<Map> map, 4185 void Map::SetDescriptors(Handle<Map> map,
4182 Handle<DescriptorArray> descriptors) { 4186 Handle<DescriptorArray> descriptors) {
4183 Isolate* isolate = map->GetIsolate(); 4187 Isolate* isolate = map->GetIsolate();
4184 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); 4188 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors));
4185 } 4189 }
4186 4190
4187 4191
4188 int Map::NumberOfDescribedProperties(PropertyAttributes filter) { 4192 int Map::NumberOfDescribedProperties(DescriptorFlag which,
4193 PropertyAttributes filter) {
4189 int result = 0; 4194 int result = 0;
4190 DescriptorArray* descs = instance_descriptors(); 4195 DescriptorArray* descs = instance_descriptors();
4191 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4196 int limit = which == ALL_DESCRIPTORS
4192 PropertyDetails details = descs->GetDetails(i); 4197 ? descs->number_of_descriptors()
4193 if ((details.attributes() & filter) == 0) { 4198 : NumberOfOwnDescriptors();
4194 result++; 4199 for (int i = 0; i < limit; i++) {
4195 } 4200 if ((descs->GetDetails(i).attributes() & filter) == 0) result++;
4196 } 4201 }
4197 return result; 4202 return result;
4198 } 4203 }
4199 4204
4200 4205
4201 int Map::PropertyIndexFor(String* name) { 4206 int Map::PropertyIndexFor(String* name) {
4202 DescriptorArray* descs = instance_descriptors(); 4207 DescriptorArray* descs = instance_descriptors();
4203 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4208 int limit = NumberOfOwnDescriptors();
4209 for (int i = 0; i < limit; i++) {
4204 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i); 4210 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4205 } 4211 }
4206 return -1; 4212 return -1;
4207 } 4213 }
4208 4214
4209 4215
4210 int Map::NextFreePropertyIndex() { 4216 int Map::NextFreePropertyIndex() {
4211 int max_index = -1; 4217 int max_index = -1;
4218 int number_of_own_descriptors = NumberOfOwnDescriptors();
4212 DescriptorArray* descs = instance_descriptors(); 4219 DescriptorArray* descs = instance_descriptors();
4213 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4220 for (int i = 0; i < number_of_own_descriptors; i++) {
4214 if (descs->GetType(i) == FIELD) { 4221 if (descs->GetType(i) == FIELD) {
4215 int current_index = descs->GetFieldIndex(i); 4222 int current_index = descs->GetFieldIndex(i);
4216 if (current_index > max_index) max_index = current_index; 4223 if (current_index > max_index) max_index = current_index;
4217 } 4224 }
4218 } 4225 }
4219 return max_index + 1; 4226 return max_index + 1;
4220 } 4227 }
4221 4228
4222 4229
4223 AccessorDescriptor* Map::FindAccessor(String* name) { 4230 AccessorDescriptor* Map::FindAccessor(String* name) {
4224 DescriptorArray* descs = instance_descriptors(); 4231 DescriptorArray* descs = instance_descriptors();
4225 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4232 int number_of_own_descriptors = NumberOfOwnDescriptors();
4226 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) { 4233 for (int i = 0; i < number_of_own_descriptors; i++) {
4234 if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
4227 return descs->GetCallbacks(i); 4235 return descs->GetCallbacks(i);
4228 } 4236 }
4229 } 4237 }
4230 return NULL; 4238 return NULL;
4231 } 4239 }
4232 4240
4233 4241
4234 void JSReceiver::LocalLookup(String* name, LookupResult* result) { 4242 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
4235 ASSERT(name->IsString()); 4243 ASSERT(name->IsString());
4236 4244
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
4640 } else { 4648 } else {
4641 return GetHeap()->null_value(); 4649 return GetHeap()->null_value();
4642 } 4650 }
4643 4651
4644 int descriptor_number = result.GetDescriptorIndex(); 4652 int descriptor_number = result.GetDescriptorIndex();
4645 4653
4646 map()->LookupTransition(this, name, &result); 4654 map()->LookupTransition(this, name, &result);
4647 4655
4648 if (result.IsFound()) { 4656 if (result.IsFound()) {
4649 Map* target = result.GetTransitionTarget(); 4657 Map* target = result.GetTransitionTarget();
4650 ASSERT(target->instance_descriptors()->number_of_descriptors() == 4658 ASSERT(target->NumberOfOwnDescriptors() ==
4651 map()->instance_descriptors()->number_of_descriptors()); 4659 map()->NumberOfOwnDescriptors());
4652 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name); 4660 // This works since descriptors are sorted in order of addition.
4661 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name);
4653 return TryAccessorTransition( 4662 return TryAccessorTransition(
4654 this, target, descriptor_number, component, accessor, attributes); 4663 this, target, descriptor_number, component, accessor, attributes);
4655 } 4664 }
4656 } else { 4665 } else {
4657 // If not, lookup a transition. 4666 // If not, lookup a transition.
4658 map()->LookupTransition(this, name, &result); 4667 map()->LookupTransition(this, name, &result);
4659 4668
4660 // If there is a transition, try to follow it. 4669 // If there is a transition, try to follow it.
4661 if (result.IsFound()) { 4670 if (result.IsFound()) {
4662 Map* target = result.GetTransitionTarget(); 4671 Map* target = result.GetTransitionTarget();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
4825 } 4834 }
4826 } 4835 }
4827 } 4836 }
4828 } 4837 }
4829 return heap->undefined_value(); 4838 return heap->undefined_value();
4830 } 4839 }
4831 4840
4832 4841
4833 Object* JSObject::SlowReverseLookup(Object* value) { 4842 Object* JSObject::SlowReverseLookup(Object* value) {
4834 if (HasFastProperties()) { 4843 if (HasFastProperties()) {
4844 int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
4835 DescriptorArray* descs = map()->instance_descriptors(); 4845 DescriptorArray* descs = map()->instance_descriptors();
4836 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4846 for (int i = 0; i < number_of_own_descriptors; i++) {
4837 if (descs->GetType(i) == FIELD) { 4847 if (descs->GetType(i) == FIELD) {
4838 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { 4848 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4839 return descs->GetKey(i); 4849 return descs->GetKey(i);
4840 } 4850 }
4841 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { 4851 } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4842 if (descs->GetConstantFunction(i) == value) { 4852 if (descs->GetConstantFunction(i) == value) {
4843 return descs->GetKey(i); 4853 return descs->GetKey(i);
4844 } 4854 }
4845 } 4855 }
4846 } 4856 }
4847 return GetHeap()->undefined_value(); 4857 return GetHeap()->undefined_value();
4848 } else { 4858 } else {
4849 return property_dictionary()->SlowReverseLookup(value); 4859 return property_dictionary()->SlowReverseLookup(value);
4850 } 4860 }
4851 } 4861 }
4852 4862
4853 4863
4854 MaybeObject* Map::RawCopy(int instance_size) { 4864 MaybeObject* Map::RawCopy(int instance_size) {
4855 Map* result; 4865 Map* result;
4856 MaybeObject* maybe_result = 4866 MaybeObject* maybe_result =
4857 GetHeap()->AllocateMap(instance_type(), instance_size); 4867 GetHeap()->AllocateMap(instance_type(), instance_size);
4858 if (!maybe_result->To(&result)) return maybe_result; 4868 if (!maybe_result->To(&result)) return maybe_result;
4859 4869
4860 result->set_prototype(prototype()); 4870 result->set_prototype(prototype());
4861 result->set_constructor(constructor()); 4871 result->set_constructor(constructor());
4862 result->set_bit_field(bit_field()); 4872 result->set_bit_field(bit_field());
4863 result->set_bit_field2(bit_field2()); 4873 result->set_bit_field2(bit_field2());
4864 result->set_bit_field3(bit_field3()); 4874 result->set_bit_field3(bit_field3());
4865 result->SetNumberOfOwnDescriptors(0); 4875 int new_bit_field3 = bit_field3();
4866 result->SetEnumLength(kInvalidEnumCache); 4876 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
4877 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
4878 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
4879 result->set_bit_field3(new_bit_field3);
4867 return result; 4880 return result;
4868 } 4881 }
4869 4882
4870 4883
4871 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, 4884 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4872 NormalizedMapSharingMode sharing) { 4885 NormalizedMapSharingMode sharing) {
4873 int new_instance_size = instance_size(); 4886 int new_instance_size = instance_size();
4874 if (mode == CLEAR_INOBJECT_PROPERTIES) { 4887 if (mode == CLEAR_INOBJECT_PROPERTIES) {
4875 new_instance_size -= inobject_properties() * kPointerSize; 4888 new_instance_size -= inobject_properties() * kPointerSize;
4876 } 4889 }
(...skipping 29 matching lines...) Expand all
4906 result->set_inobject_properties(inobject_properties()); 4919 result->set_inobject_properties(inobject_properties());
4907 result->set_unused_property_fields(unused_property_fields()); 4920 result->set_unused_property_fields(unused_property_fields());
4908 4921
4909 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); 4922 result->set_pre_allocated_property_fields(pre_allocated_property_fields());
4910 result->set_is_shared(false); 4923 result->set_is_shared(false);
4911 result->ClearCodeCache(GetHeap()); 4924 result->ClearCodeCache(GetHeap());
4912 return result; 4925 return result;
4913 } 4926 }
4914 4927
4915 4928
4929 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
4930 Map* result;
4931 MaybeObject* maybe_result = CopyDropDescriptors();
4932 if (!maybe_result->To(&result)) return maybe_result;
4933
4934 String* name = descriptor->GetKey();
4935
4936 TransitionArray* transitions;
4937 MaybeObject* maybe_transitions = AddTransition(name, result);
4938 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4939
4940 DescriptorArray* descriptors = instance_descriptors();
4941 int old_size = descriptors->number_of_descriptors();
4942
4943 DescriptorArray* new_descriptors;
4944 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1);
4945 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
4946 FixedArray::WhitenessWitness witness(new_descriptors);
4947
4948 for (int i = 0; i < old_size; ++i) {
4949 new_descriptors->CopyFrom(i, descriptors, i, witness);
4950 }
4951 new_descriptors->Append(descriptor, witness, old_size);
4952
4953 // If the source descriptors had an enum cache we copy it. This ensures that
4954 // the maps to which we push the new descriptor array back can rely on a
4955 // cache always being available once it is set. If the map has more
4956 // enumerated descriptors than available in the original cache, the cache
4957 // will be lazily replaced by the extended cache when needed.
4958 if (descriptors->HasEnumCache()) {
4959 new_descriptors->CopyEnumCacheFrom(descriptors);
4960 }
4961
4962 transitions->set_descriptors(new_descriptors);
4963 set_transitions(transitions);
4964 result->SetBackPointer(this);
4965 SetOwnsDescriptors(false);
4966
4967 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors());
4968
4969 return result;
4970 }
4971
4972
4916 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, 4973 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
4917 String* name, 4974 String* name,
4918 TransitionFlag flag) { 4975 TransitionFlag flag) {
4976 ASSERT(descriptors->IsSortedNoDuplicates());
4977
4919 Map* result; 4978 Map* result;
4920 MaybeObject* maybe_result = CopyDropDescriptors(); 4979 MaybeObject* maybe_result = CopyDropDescriptors();
4921 if (!maybe_result->To(&result)) return maybe_result; 4980 if (!maybe_result->To(&result)) return maybe_result;
4922 4981
4923 if (descriptors->number_of_descriptors() != 0) { 4982 // Unless we are creating a map with no descriptors and no back pointer, we
4983 // insert the descriptor array locally.
4984 if (!descriptors->IsEmpty()) {
4924 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); 4985 MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
4925 if (maybe_failure->IsFailure()) return maybe_failure; 4986 if (maybe_failure->IsFailure()) return maybe_failure;
4926 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); 4987 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
4927 } 4988 }
4928 4989
4929 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 4990 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
4930 TransitionArray* transitions; 4991 TransitionArray* transitions;
4931 MaybeObject* maybe_transitions = AddTransition(name, result); 4992 MaybeObject* maybe_transitions = AddTransition(name, result);
4932 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 4993 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4933 4994
4995 if (descriptors->IsEmpty()) {
4996 if (OwnsDescriptors()) {
4997 // If the copied map has no added fields, and the parent map owns its
4998 // descriptors, those descriptors have to be empty. In that case,
4999 // transfer ownership of the descriptors to the new child.
5000 ASSERT(instance_descriptors()->IsEmpty());
5001 SetOwnsDescriptors(false);
5002 } else {
5003 // If the parent did not own its own descriptors, it may share a larger
5004 // descriptors array already. In that case, force a split by setting
5005 // the descriptor array of the new map to the empty descriptor array.
5006 MaybeObject* maybe_failure =
5007 result->SetDescriptors(GetHeap()->empty_descriptor_array());
5008 if (maybe_failure->IsFailure()) return maybe_failure;
5009 }
5010 }
5011
4934 set_transitions(transitions); 5012 set_transitions(transitions);
4935 result->SetBackPointer(this); 5013 result->SetBackPointer(this);
4936 } 5014 }
4937 5015
4938 return result; 5016 return result;
4939 } 5017 }
4940 5018
4941 5019
4942 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 5020 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
4943 // Create a new free-floating map only if we are not allowed to store it.
4944 Map* new_map = NULL;
4945 MaybeObject* maybe_new_map = Copy();
4946 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4947 new_map->set_elements_kind(kind);
4948
4949 if (flag == INSERT_TRANSITION) { 5021 if (flag == INSERT_TRANSITION) {
4950 ASSERT(!HasElementsTransition() || 5022 ASSERT(!HasElementsTransition() ||
4951 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 5023 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
4952 IsExternalArrayElementsKind( 5024 IsExternalArrayElementsKind(
4953 elements_transition_map()->elements_kind())) && 5025 elements_transition_map()->elements_kind())) &&
4954 (kind == DICTIONARY_ELEMENTS || 5026 (kind == DICTIONARY_ELEMENTS ||
4955 IsExternalArrayElementsKind(kind)))); 5027 IsExternalArrayElementsKind(kind))));
4956 ASSERT(!IsFastElementsKind(kind) || 5028 ASSERT(!IsFastElementsKind(kind) ||
4957 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 5029 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
4958 ASSERT(kind != elements_kind()); 5030 ASSERT(kind != elements_kind());
5031 }
5032
5033 if (flag == INSERT_TRANSITION && OwnsDescriptors()) {
5034 // In case the map owned its own descriptors, share the descriptors and
5035 // transfer ownership to the new map.
5036 Map* new_map;
5037 MaybeObject* maybe_new_map = CopyDropDescriptors();
5038 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4959 5039
4960 MaybeObject* added_elements = set_elements_transition_map(new_map); 5040 MaybeObject* added_elements = set_elements_transition_map(new_map);
4961 if (added_elements->IsFailure()) return added_elements; 5041 if (added_elements->IsFailure()) return added_elements;
4962 5042
5043 new_map->set_elements_kind(kind);
5044 new_map->SetBackPointer(this);
5045 new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors());
5046 SetOwnsDescriptors(false);
5047 return new_map;
5048 }
5049
5050 // In case the map did not own its own descriptors, a split is forced by
5051 // copying the map; creating a new descriptor array cell.
5052 // Create a new free-floating map only if we are not allowed to store it.
5053 Map* new_map;
5054 MaybeObject* maybe_new_map = Copy();
5055 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
5056 ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors());
5057 new_map->set_elements_kind(kind);
5058
5059 if (flag == INSERT_TRANSITION) {
5060 // Map::Copy does not store the descriptor array in case it is empty, since
5061 // it does not insert a back pointer; implicitly indicating that its
5062 // descriptor array is empty. Since in this case we do want to insert a back
5063 // pointer, we have to manually set the empty descriptor array to force a
5064 // split.
5065 if (!new_map->StoresOwnDescriptors()) {
5066 ASSERT(new_map->NumberOfOwnDescriptors() == 0);
5067 MaybeObject* maybe_failure =
5068 new_map->SetDescriptors(GetHeap()->empty_descriptor_array());
5069 if (maybe_failure->IsFailure()) return maybe_failure;
5070 }
5071 MaybeObject* added_elements = set_elements_transition_map(new_map);
5072 if (added_elements->IsFailure()) return added_elements;
5073
4963 new_map->SetBackPointer(this); 5074 new_map->SetBackPointer(this);
4964 } 5075 }
4965 5076
4966 return new_map; 5077 return new_map;
4967 } 5078 }
4968 5079
4969 5080
4970 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { 5081 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
4971 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); 5082 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
4972 5083
4973 // If the map has pre-allocated properties always start out with a descriptor 5084 // If the map has pre-allocated properties always start out with a descriptor
4974 // array describing these properties. 5085 // array describing these properties.
4975 ASSERT(constructor()->IsJSFunction()); 5086 ASSERT(constructor()->IsJSFunction());
4976 JSFunction* ctor = JSFunction::cast(constructor()); 5087 JSFunction* ctor = JSFunction::cast(constructor());
4977 Map* map = ctor->initial_map(); 5088 Map* map = ctor->initial_map();
4978 DescriptorArray* descriptors = map->instance_descriptors(); 5089 DescriptorArray* descriptors = map->instance_descriptors();
4979 5090
4980 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); 5091 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
5092 DescriptorArray* new_descriptors;
5093 MaybeObject* maybe_descriptors =
5094 descriptors->CopyUpTo(number_of_own_descriptors);
5095 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5096
5097 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION);
4981 } 5098 }
4982 5099
4983 5100
4984 MaybeObject* Map::Copy() { 5101 MaybeObject* Map::Copy() {
4985 DescriptorArray* descriptors = instance_descriptors(); 5102 DescriptorArray* descriptors = instance_descriptors();
4986 return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION); 5103 DescriptorArray* new_descriptors;
5104 int number_of_own_descriptors = NumberOfOwnDescriptors();
5105 MaybeObject* maybe_descriptors =
5106 descriptors->CopyUpTo(number_of_own_descriptors);
5107 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5108
5109 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION);
4987 } 5110 }
4988 5111
4989 5112
4990 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 5113 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
4991 TransitionFlag flag) { 5114 TransitionFlag flag) {
4992 DescriptorArray* descriptors = instance_descriptors(); 5115 DescriptorArray* descriptors = instance_descriptors();
5116 // name->PrintLn();
Jakob Kummerow 2012/09/11 14:24:25 leftover?
Toon Verwaest 2012/09/11 14:49:23 Done.
4993 5117
4994 // Ensure the key is a symbol. 5118 // Ensure the key is a symbol.
4995 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5119 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
4996 if (maybe_failure->IsFailure()) return maybe_failure; 5120 if (maybe_failure->IsFailure()) return maybe_failure;
4997 5121
4998 String* key = descriptor->GetKey(); 5122 int old_size = NumberOfOwnDescriptors();
4999 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound); 5123 int new_size = old_size + 1;
5124 descriptor->SetEnumerationIndex(new_size);
5000 5125
5001 int old_size = descriptors->number_of_descriptors(); 5126 if (flag == INSERT_TRANSITION &&
5002 int new_size = old_size + 1; 5127 OwnsDescriptors() &&
5128 CanHaveMoreTransitions()) {
5129 return ShareDescriptor(descriptor);
5130 }
5003 5131
5004 DescriptorArray* new_descriptors; 5132 DescriptorArray* new_descriptors;
5005 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size); 5133 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1);
5006 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5134 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5007 5135
5008 FixedArray::WhitenessWitness witness(new_descriptors); 5136 FixedArray::WhitenessWitness witness(new_descriptors);
5009 5137
5010 // Copy the descriptors, inserting a descriptor. 5138 // Copy the descriptors, inserting a descriptor.
5011 for (int i = 0; i < old_size; ++i) { 5139 for (int i = 0; i < old_size; ++i) {
5012 new_descriptors->CopyFrom(i, descriptors, i, witness); 5140 new_descriptors->CopyFrom(i, descriptors, i, witness);
5013 } 5141 }
5014 5142
5015 new_descriptors->Append(descriptor, witness, old_size); 5143 new_descriptors->Set(old_size, descriptor, witness);
5144 new_descriptors->Sort();
5016 5145
5017 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); 5146 return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag);
5018
5019 return CopyReplaceDescriptors(new_descriptors, key, flag);
5020 } 5147 }
5021 5148
5022 5149
5023 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 5150 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
5024 TransitionFlag flag) { 5151 TransitionFlag flag) {
5025 DescriptorArray* old_descriptors = instance_descriptors(); 5152 DescriptorArray* old_descriptors = instance_descriptors();
5026 5153
5027 // Ensure the key is a symbol. 5154 // Ensure the key is a symbol.
5028 MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5155 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5029 if (maybe_result->IsFailure()) return maybe_result; 5156 if (maybe_result->IsFailure()) return maybe_result;
5030 5157
5031 // We replace the key if it is already present. 5158 // We replace the key if it is already present.
5032 int index = old_descriptors->SearchWithCache(descriptor->GetKey()); 5159 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
5033 if (index != DescriptorArray::kNotFound) { 5160 if (index != DescriptorArray::kNotFound) {
5034 return CopyReplaceDescriptor(descriptor, index, flag); 5161 return CopyReplaceDescriptor(descriptor, index, flag);
5035 } 5162 }
5036 return CopyAddDescriptor(descriptor, flag); 5163 return CopyAddDescriptor(descriptor, flag);
5037 } 5164 }
5038 5165
5039 5166
5167 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
5168 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
5169 // if (enumeration_index == number_of_descriptors()) return this;
Jakob Kummerow 2012/09/11 14:24:25 // ?
Toon Verwaest 2012/09/11 14:49:23 This is leftover code. Removed. It would have bee
5170
5171 int size = enumeration_index;
5172
5173 DescriptorArray* descriptors;
5174 MaybeObject* maybe_descriptors = Allocate(size);
5175 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
5176 DescriptorArray::WhitenessWitness witness(descriptors);
5177
5178 for (int i = 0; i < size; ++i) {
5179 descriptors->CopyFrom(i, this, i, witness);
5180 }
5181
5182 if (number_of_descriptors() != enumeration_index) descriptors->Sort();
5183
5184 return descriptors;
5185 }
5186
5187
5040 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, 5188 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
5041 int insertion_index, 5189 int insertion_index,
5042 TransitionFlag flag) { 5190 TransitionFlag flag) {
5043 DescriptorArray* descriptors = instance_descriptors();
5044 int size = descriptors->number_of_descriptors();
5045 ASSERT(0 <= insertion_index && insertion_index < size);
5046
5047 // Ensure the key is a symbol. 5191 // Ensure the key is a symbol.
5048 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5192 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5049 if (maybe_failure->IsFailure()) return maybe_failure; 5193 if (maybe_failure->IsFailure()) return maybe_failure;
5050 5194
5195 DescriptorArray* descriptors = instance_descriptors();
5196
5051 String* key = descriptor->GetKey(); 5197 String* key = descriptor->GetKey();
5052 ASSERT(key == descriptors->GetKey(insertion_index)); 5198 ASSERT(key == descriptors->GetKey(insertion_index));
5053 5199
5200 int new_size = NumberOfOwnDescriptors();
5201 ASSERT(0 <= insertion_index && insertion_index < new_size);
5202
5203 PropertyDetails details = descriptors->GetDetails(insertion_index);
5204 ASSERT_LE(details.descriptor_index(), new_size);
5205 descriptor->SetEnumerationIndex(details.descriptor_index());
5206
5054 DescriptorArray* new_descriptors; 5207 DescriptorArray* new_descriptors;
5055 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size); 5208 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
5056 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5209 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5210 DescriptorArray::WhitenessWitness witness(new_descriptors);
5057 5211
5058 FixedArray::WhitenessWitness witness(new_descriptors); 5212 for (int i = 0; i < new_size; ++i) {
5059 5213 if (i == insertion_index) {
5060 // Copy the descriptors, replacing a descriptor. 5214 new_descriptors->Set(i, descriptor, witness);
5061 for (int index = 0; index < size; ++index) { 5215 } else {
5062 if (index == insertion_index) continue; 5216 new_descriptors->CopyFrom(i, descriptors, i, witness);
5063 new_descriptors->CopyFrom(index, descriptors, index, witness); 5217 }
5064 } 5218 }
5065 5219
5066 PropertyDetails original_details = descriptors->GetDetails(insertion_index); 5220 // Resort if descriptors were removed.
Jakob Kummerow 2012/09/11 14:24:25 nit: s/Resort/Re-sort/
Toon Verwaest 2012/09/11 14:49:23 Done.
5067 descriptor->SetEnumerationIndex(original_details.descriptor_index()); 5221 if (new_size != descriptors->length()) new_descriptors->Sort();
5068 descriptor->SetSortedKey(original_details.pointer());
5069
5070 new_descriptors->Set(insertion_index, descriptor, witness);
5071
5072 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5073 5222
5074 return CopyReplaceDescriptors(new_descriptors, key, flag); 5223 return CopyReplaceDescriptors(new_descriptors, key, flag);
5075 } 5224 }
5076 5225
5077 5226
5078 void Map::UpdateCodeCache(Handle<Map> map, 5227 void Map::UpdateCodeCache(Handle<Map> map,
5079 Handle<String> name, 5228 Handle<String> name,
5080 Handle<Code> code) { 5229 Handle<Code> code) {
5081 Isolate* isolate = map->GetIsolate(); 5230 Isolate* isolate = map->GetIsolate();
5082 CALL_HEAP_FUNCTION_VOID(isolate, 5231 CALL_HEAP_FUNCTION_VOID(isolate,
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after
5860 return result; 6009 return result;
5861 } 6010 }
5862 6011
5863 6012
5864 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 6013 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5865 FixedArray* new_cache, 6014 FixedArray* new_cache,
5866 Object* new_index_cache) { 6015 Object* new_index_cache) {
5867 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 6016 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5868 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 6017 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5869 if (HasEnumCache()) { 6018 if (HasEnumCache()) {
6019 ASSERT(new_cache->length() > FixedArray::cast(GetEnumCache())->length());
5870 FixedArray::cast(get(kEnumCacheIndex))-> 6020 FixedArray::cast(get(kEnumCacheIndex))->
5871 set(kEnumCacheBridgeCacheIndex, new_cache); 6021 set(kEnumCacheBridgeCacheIndex, new_cache);
5872 FixedArray::cast(get(kEnumCacheIndex))-> 6022 FixedArray::cast(get(kEnumCacheIndex))->
5873 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 6023 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5874 } else { 6024 } else {
5875 if (IsEmpty()) return; // Do nothing for empty descriptor array. 6025 ASSERT(!IsEmpty()); // Do nothing for empty descriptor array.
Jakob Kummerow 2012/09/11 14:24:25 outdated comment (just remove it)
Toon Verwaest 2012/09/11 14:49:23 Done.
5876 FixedArray::cast(bridge_storage)-> 6026 FixedArray::cast(bridge_storage)->
5877 set(kEnumCacheBridgeCacheIndex, new_cache); 6027 set(kEnumCacheBridgeCacheIndex, new_cache);
5878 FixedArray::cast(bridge_storage)-> 6028 FixedArray::cast(bridge_storage)->
5879 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 6029 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5880 set(kEnumCacheIndex, bridge_storage); 6030 set(kEnumCacheIndex, bridge_storage);
5881 } 6031 }
5882 } 6032 }
5883 6033
5884 6034
5885 void DescriptorArray::CopyFrom(int dst_index, 6035 void DescriptorArray::CopyFrom(int dst_index,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
5941 if (right_child_hash > child_hash) { 6091 if (right_child_hash > child_hash) {
5942 child_index++; 6092 child_index++;
5943 child_hash = right_child_hash; 6093 child_hash = right_child_hash;
5944 } 6094 }
5945 } 6095 }
5946 if (child_hash <= parent_hash) break; 6096 if (child_hash <= parent_hash) break;
5947 SwapSortedKeys(parent_index, child_index); 6097 SwapSortedKeys(parent_index, child_index);
5948 parent_index = child_index; 6098 parent_index = child_index;
5949 } 6099 }
5950 } 6100 }
6101 ASSERT(IsSortedNoDuplicates());
5951 } 6102 }
5952 6103
5953 6104
5954 MaybeObject* AccessorPair::Copy() { 6105 MaybeObject* AccessorPair::Copy() {
5955 Heap* heap = GetHeap(); 6106 Heap* heap = GetHeap();
5956 AccessorPair* copy; 6107 AccessorPair* copy;
5957 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); 6108 MaybeObject* maybe_copy = heap->AllocateAccessorPair();
5958 if (!maybe_copy->To(&copy)) return maybe_copy; 6109 if (!maybe_copy->To(&copy)) return maybe_copy;
5959 6110
5960 copy->set_getter(getter()); 6111 copy->set_getter(getter());
(...skipping 1227 matching lines...) Expand 10 before | Expand all | Expand 10 after
7188 void String::PrintOn(FILE* file) { 7339 void String::PrintOn(FILE* file) {
7189 int length = this->length(); 7340 int length = this->length();
7190 for (int i = 0; i < length; i++) { 7341 for (int i = 0; i < length; i++) {
7191 fprintf(file, "%c", Get(i)); 7342 fprintf(file, "%c", Get(i));
7192 } 7343 }
7193 } 7344 }
7194 7345
7195 7346
7196 // Clear a possible back pointer in case the transition leads to a dead map. 7347 // Clear a possible back pointer in case the transition leads to a dead map.
7197 // Return true in case a back pointer has been cleared and false otherwise. 7348 // Return true in case a back pointer has been cleared and false otherwise.
7198 static bool ClearBackPointer(Heap* heap, Object* target) { 7349 static bool ClearBackPointer(Heap* heap, Map* target) {
7199 ASSERT(target->IsMap()); 7350 if (Marking::MarkBitFrom(target).Get()) return false;
7200 Map* map = Map::cast(target); 7351 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7201 if (Marking::MarkBitFrom(map).Get()) return false;
7202 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7203 return true; 7352 return true;
7204 } 7353 }
7205 7354
7206 7355
7207 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, 7356 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
7208 // because it cannot be called from outside the GC and we already have methods 7357 // because it cannot be called from outside the GC and we already have methods
7209 // depending on the transitions layout in the GC anyways. 7358 // depending on the transitions layout in the GC anyways.
7210 void Map::ClearNonLiveTransitions(Heap* heap) { 7359 void Map::ClearNonLiveTransitions(Heap* heap) {
7211 // If there are no transitions to be cleared, return. 7360 // If there are no transitions to be cleared, return.
7212 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7361 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7213 // properly cleared. 7362 // properly cleared.
7214 if (!HasTransitionArray()) return; 7363 if (!HasTransitionArray()) return;
7215 7364
7216 TransitionArray* t = transitions(); 7365 TransitionArray* t = transitions();
7217 MarkCompactCollector* collector = heap->mark_compact_collector(); 7366 MarkCompactCollector* collector = heap->mark_compact_collector();
7218 7367
7219 int transition_index = 0; 7368 int transition_index = 0;
7220 7369
7370 DescriptorArray* descriptors = t->descriptors();
7371 bool descriptors_owner_died = false;
7372
7221 // Compact all live descriptors to the left. 7373 // Compact all live descriptors to the left.
7222 for (int i = 0; i < t->number_of_transitions(); ++i) { 7374 for (int i = 0; i < t->number_of_transitions(); ++i) {
7223 if (!ClearBackPointer(heap, t->GetTarget(i))) { 7375 Map* target = t->GetTarget(i);
7376 if (ClearBackPointer(heap, target)) {
7377 if (target->instance_descriptors() == descriptors) {
7378 descriptors_owner_died = true;
7379 }
7380 } else {
7224 if (i != transition_index) { 7381 if (i != transition_index) {
7225 String* key = t->GetKey(i); 7382 String* key = t->GetKey(i);
7226 t->SetKey(transition_index, key); 7383 t->SetKey(transition_index, key);
7227 Object** key_slot = t->GetKeySlot(transition_index); 7384 Object** key_slot = t->GetKeySlot(transition_index);
7228 collector->RecordSlot(key_slot, key_slot, key); 7385 collector->RecordSlot(key_slot, key_slot, key);
7229 // Target slots do not need to be recorded since maps are not compacted. 7386 // Target slots do not need to be recorded since maps are not compacted.
7230 t->SetTarget(transition_index, t->GetTarget(i)); 7387 t->SetTarget(transition_index, t->GetTarget(i));
7231 } 7388 }
7232 transition_index++; 7389 transition_index++;
7233 } 7390 }
7234 } 7391 }
7235 7392
7236 if (t->HasElementsTransition() && 7393 if (t->HasElementsTransition() &&
7237 ClearBackPointer(heap, t->elements_transition())) { 7394 ClearBackPointer(heap, t->elements_transition())) {
7395 if (t->elements_transition()->instance_descriptors() == descriptors) {
7396 descriptors_owner_died = true;
7397 }
7238 t->ClearElementsTransition(); 7398 t->ClearElementsTransition();
7239 } else { 7399 } else {
7240 // If there are no transitions to be cleared, return. 7400 // If there are no transitions to be cleared, return.
7241 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7401 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7242 // properly cleared. 7402 // properly cleared.
7243 if (transition_index == t->number_of_transitions()) return; 7403 if (transition_index == t->number_of_transitions()) return;
7244 } 7404 }
7245 7405
7406 int number_of_own_descriptors = NumberOfOwnDescriptors();
7407
7408 if (descriptors_owner_died) {
7409 if (number_of_own_descriptors > 0) {
7410 int live_enum = NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
7411 int number_of_descriptors = descriptors->number_of_descriptors();
7412 int to_trim = number_of_descriptors - number_of_own_descriptors;
7413 if (to_trim > 0) {
7414 RightTrimFixedArray<FROM_GC>(
7415 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize);
7416 if (descriptors->HasEnumCache()) {
7417 FixedArray* enum_cache =
7418 FixedArray::cast(descriptors->GetEnumCache());
7419 to_trim = enum_cache->length() - live_enum;
7420 if (to_trim > 0) {
7421 RightTrimFixedArray<FROM_GC>(
7422 heap, FixedArray::cast(descriptors->GetEnumCache()), to_trim);
7423 }
7424 }
7425 descriptors->Sort();
7426 }
7427 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
7428 } else {
7429 t->set_descriptors(heap->empty_descriptor_array());
7430 }
7431 SetOwnsDescriptors(true);
7432 }
7433
7246 // If the final transition array does not contain any live transitions, remove 7434 // If the final transition array does not contain any live transitions, remove
7247 // the transition array from the map. 7435 // the transition array from the map.
7248 if (transition_index == 0 && 7436 if (transition_index == 0 &&
7249 !t->HasElementsTransition() && 7437 !t->HasElementsTransition() &&
7250 !t->HasPrototypeTransitions() && 7438 !t->HasPrototypeTransitions() &&
7251 t->descriptors()->IsEmpty()) { 7439 number_of_own_descriptors == 0) {
7252 return ClearTransitions(heap); 7440 return ClearTransitions(heap);
7253 } 7441 }
7254 7442
7255 int trim = t->number_of_transitions() - transition_index; 7443 int trim = t->number_of_transitions() - transition_index;
7256 if (trim > 0) { 7444 if (trim > 0) {
7257 RightTrimFixedArray<FROM_GC>( 7445 RightTrimFixedArray<FROM_GC>(
7258 heap, t, trim * TransitionArray::kTransitionSize); 7446 heap, t, trim * TransitionArray::kTransitionSize);
7259 } 7447 }
7260 } 7448 }
7261 7449
(...skipping 3100 matching lines...) Expand 10 before | Expand all | Expand 10 after
10362 } 10550 }
10363 10551
10364 LookupResult result(isolate); 10552 LookupResult result(isolate);
10365 LocalLookupRealNamedProperty(key, &result); 10553 LocalLookupRealNamedProperty(key, &result);
10366 return result.IsPropertyCallbacks(); 10554 return result.IsPropertyCallbacks();
10367 } 10555 }
10368 10556
10369 10557
10370 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { 10558 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10371 return HasFastProperties() ? 10559 return HasFastProperties() ?
10372 map()->NumberOfDescribedProperties(filter) : 10560 map()->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter) :
10373 property_dictionary()->NumberOfElementsFilterAttributes(filter); 10561 property_dictionary()->NumberOfElementsFilterAttributes(filter);
10374 } 10562 }
10375 10563
10376 10564
10377 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { 10565 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10378 Object* temp = get(i); 10566 Object* temp = get(i);
10379 set(i, get(j)); 10567 set(i, get(j));
10380 set(j, temp); 10568 set(j, temp);
10381 if (this != numbers) { 10569 if (this != numbers) {
10382 temp = numbers->get(i); 10570 temp = numbers->get(i);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
10486 } 10674 }
10487 } 10675 }
10488 10676
10489 10677
10490 // Fill in the names of local properties into the supplied storage. The main 10678 // Fill in the names of local properties into the supplied storage. The main
10491 // purpose of this function is to provide reflection information for the object 10679 // purpose of this function is to provide reflection information for the object
10492 // mirrors. 10680 // mirrors.
10493 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { 10681 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10494 ASSERT(storage->length() >= (NumberOfLocalProperties() - index)); 10682 ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10495 if (HasFastProperties()) { 10683 if (HasFastProperties()) {
10684 int real_size = map()->NumberOfOwnDescriptors();
10496 DescriptorArray* descs = map()->instance_descriptors(); 10685 DescriptorArray* descs = map()->instance_descriptors();
10497 ASSERT(storage->length() >= index + descs->number_of_descriptors()); 10686 ASSERT(storage->length() >= index + real_size);
10498 for (int i = 0; i < descs->number_of_descriptors(); i++) { 10687 for (int i = 0; i < real_size; i++) {
10499 storage->set(index + i, descs->GetKey(i)); 10688 storage->set(index + i, descs->GetKey(i));
10500 } 10689 }
10501 } else { 10690 } else {
10502 property_dictionary()->CopyKeysTo(storage, 10691 property_dictionary()->CopyKeysTo(storage,
10503 index, 10692 index,
10504 StringDictionary::UNSORTED); 10693 StringDictionary::UNSORTED);
10505 } 10694 }
10506 } 10695 }
10507 10696
10508 10697
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after
12191 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); 12380 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12192 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 12381 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12193 } 12382 }
12194 FixedArray* enumeration_order = FixedArray::cast(obj); 12383 FixedArray* enumeration_order = FixedArray::cast(obj);
12195 12384
12196 // Fill the enumeration order array with property details. 12385 // Fill the enumeration order array with property details.
12197 int capacity = HashTable<Shape, Key>::Capacity(); 12386 int capacity = HashTable<Shape, Key>::Capacity();
12198 int pos = 0; 12387 int pos = 0;
12199 for (int i = 0; i < capacity; i++) { 12388 for (int i = 0; i < capacity; i++) {
12200 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { 12389 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12201 enumeration_order->set( 12390 int index = DetailsAt(i).dictionary_index();
12202 pos++, Smi::FromInt(DetailsAt(i).dictionary_index())); 12391 enumeration_order->set(pos++, Smi::FromInt(index));
12203 } 12392 }
12204 } 12393 }
12205 12394
12206 // Sort the arrays wrt. enumeration order. 12395 // Sort the arrays wrt. enumeration order.
12207 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); 12396 iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12208 12397
12209 // Overwrite the enumeration_order with the enumeration indices. 12398 // Overwrite the enumeration_order with the enumeration indices.
12210 for (int i = 0; i < length; i++) { 12399 for (int i = 0; i < length; i++) {
12211 int index = Smi::cast(iteration_order->get(i))->value(); 12400 int index = Smi::cast(iteration_order->get(i))->value();
12212 int enum_index = PropertyDetails::kInitialIndex + i; 12401 int enum_index = PropertyDetails::kInitialIndex + i;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
12321 uint32_t hash) { 12510 uint32_t hash) {
12322 // Compute the key object. 12511 // Compute the key object.
12323 Object* k; 12512 Object* k;
12324 { MaybeObject* maybe_k = Shape::AsObject(key); 12513 { MaybeObject* maybe_k = Shape::AsObject(key);
12325 if (!maybe_k->ToObject(&k)) return maybe_k; 12514 if (!maybe_k->ToObject(&k)) return maybe_k;
12326 } 12515 }
12327 12516
12328 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); 12517 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12329 // Insert element at empty or deleted entry 12518 // Insert element at empty or deleted entry
12330 if (!details.IsDeleted() && 12519 if (!details.IsDeleted() &&
12331 details.dictionary_index() == 0 && Shape::kIsEnumerable) { 12520 details.dictionary_index() == 0 &&
12521 Shape::kIsEnumerable) {
12332 // Assign an enumeration index to the property and update 12522 // Assign an enumeration index to the property and update
12333 // SetNextEnumerationIndex. 12523 // SetNextEnumerationIndex.
12334 int index = NextEnumerationIndex(); 12524 int index = NextEnumerationIndex();
12335 details = PropertyDetails(details.attributes(), details.type(), index); 12525 details = PropertyDetails(details.attributes(), details.type(), index);
12336 SetNextEnumerationIndex(index + 1); 12526 SetNextEnumerationIndex(index + 1);
12337 } 12527 }
12338 SetEntry(entry, k, value, details); 12528 SetEntry(entry, k, value, details);
12339 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() 12529 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12340 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); 12530 || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12341 HashTable<Shape, Key>::ElementAdded(); 12531 HashTable<Shape, Key>::ElementAdded();
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after
13215 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13405 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13216 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13406 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13217 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13407 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13218 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13408 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13219 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13409 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13220 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13410 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13221 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13411 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13222 } 13412 }
13223 13413
13224 } } // namespace v8::internal 13414 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698