Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(©)) return maybe_copy; | 6109 if (!maybe_copy->To(©)) 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |