| 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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 value = result->holder()->FastPropertyAt(result->GetFieldIndex()); | 644 value = result->holder()->FastPropertyAt(result->GetFieldIndex()); |
| 645 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 645 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 646 return value->IsTheHole() ? heap->undefined_value() : value; | 646 return value->IsTheHole() ? heap->undefined_value() : value; |
| 647 case CONSTANT_FUNCTION: | 647 case CONSTANT_FUNCTION: |
| 648 return result->GetConstantFunction(); | 648 return result->GetConstantFunction(); |
| 649 case CALLBACKS: | 649 case CALLBACKS: |
| 650 return result->holder()->GetPropertyWithCallback( | 650 return result->holder()->GetPropertyWithCallback( |
| 651 receiver, result->GetCallbackObject(), name); | 651 receiver, result->GetCallbackObject(), name); |
| 652 case HANDLER: | 652 case HANDLER: |
| 653 return result->proxy()->GetPropertyWithHandler(receiver, name); | 653 return result->proxy()->GetPropertyWithHandler(receiver, name); |
| 654 case INTERCEPTOR: | 654 case INTERCEPTOR: { |
| 655 JSObject* recvr = JSObject::cast(receiver); |
| 655 return result->holder()->GetPropertyWithInterceptor( | 656 return result->holder()->GetPropertyWithInterceptor( |
| 656 receiver, name, attributes); | 657 recvr, name, attributes); |
| 658 } |
| 657 case TRANSITION: | 659 case TRANSITION: |
| 658 case NONEXISTENT: | 660 case NONEXISTENT: |
| 659 UNREACHABLE(); | 661 UNREACHABLE(); |
| 660 break; | 662 break; |
| 661 } | 663 } |
| 662 UNREACHABLE(); | 664 UNREACHABLE(); |
| 663 return NULL; | 665 return NULL; |
| 664 } | 666 } |
| 665 | 667 |
| 666 | 668 |
| (...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 return value; | 1685 return value; |
| 1684 } else { | 1686 } else { |
| 1685 Handle<Object> args[1] = {Handle<String>(name)}; | 1687 Handle<Object> args[1] = {Handle<String>(name)}; |
| 1686 return heap->isolate()->Throw( | 1688 return heap->isolate()->Throw( |
| 1687 *FACTORY->NewTypeError("object_not_extensible", | 1689 *FACTORY->NewTypeError("object_not_extensible", |
| 1688 HandleVector(args, 1))); | 1690 HandleVector(args, 1))); |
| 1689 } | 1691 } |
| 1690 } | 1692 } |
| 1691 if (HasFastProperties()) { | 1693 if (HasFastProperties()) { |
| 1692 // Ensure the descriptor array does not get too big. | 1694 // Ensure the descriptor array does not get too big. |
| 1693 if (map_of_this->NumberOfOwnDescriptors() < | 1695 if (map_of_this->instance_descriptors()->number_of_descriptors() < |
| 1694 DescriptorArray::kMaxNumberOfDescriptors) { | 1696 DescriptorArray::kMaxNumberOfDescriptors) { |
| 1695 if (value->IsJSFunction()) { | 1697 if (value->IsJSFunction()) { |
| 1696 return AddConstantFunctionProperty(name, | 1698 return AddConstantFunctionProperty(name, |
| 1697 JSFunction::cast(value), | 1699 JSFunction::cast(value), |
| 1698 attributes); | 1700 attributes); |
| 1699 } else { | 1701 } else { |
| 1700 return AddFastProperty(name, value, attributes, store_mode); | 1702 return AddFastProperty(name, value, attributes, store_mode); |
| 1701 } | 1703 } |
| 1702 } else { | 1704 } else { |
| 1703 // Normalize the object to prevent very large instance descriptors. | 1705 // Normalize the object to prevent very large instance descriptors. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 // descriptor array is returned to the smaller maps by installing a reduced | 1777 // descriptor array is returned to the smaller maps by installing a reduced |
| 1776 // copy of the descriptor array in the old_map. | 1778 // copy of the descriptor array in the old_map. |
| 1777 | 1779 |
| 1778 // This phase is executed before creating the new map since it requires | 1780 // This phase is executed before creating the new map since it requires |
| 1779 // allocation that may fail. | 1781 // allocation that may fail. |
| 1780 if (!old_target->StoresOwnDescriptors()) { | 1782 if (!old_target->StoresOwnDescriptors()) { |
| 1781 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 1783 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 1782 | 1784 |
| 1783 old_target->SetBackPointer(GetHeap()->undefined_value()); | 1785 old_target->SetBackPointer(GetHeap()->undefined_value()); |
| 1784 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); | 1786 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); |
| 1785 // Reset the backpointer before returning failure, otherwise the map ends up | 1787 if (maybe_failure->IsFailure()) return maybe_failure; |
| 1786 // with an undefined backpointer and no descriptors, losing its own | |
| 1787 // descriptors. Setting the backpointer always succeeds. | |
| 1788 old_target->SetBackPointer(old_map); | 1788 old_target->SetBackPointer(old_map); |
| 1789 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 1790 | 1789 |
| 1791 old_map->set_owns_descriptors(true); | 1790 old_map->set_owns_descriptors(true); |
| 1792 } | 1791 } |
| 1793 | 1792 |
| 1794 MaybeObject* maybe_result = | 1793 MaybeObject* maybe_result = |
| 1795 ConvertDescriptorToField(name, new_value, attributes); | 1794 ConvertDescriptorToField(name, new_value, attributes); |
| 1796 if (!maybe_result->To(&result)) return maybe_result; | 1795 if (!maybe_result->To(&result)) return maybe_result; |
| 1797 | 1796 |
| 1798 if (!HasFastProperties()) return result; | 1797 if (!HasFastProperties()) return result; |
| 1799 | 1798 |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2169 return heap->the_hole_value(); | 2168 return heap->the_hole_value(); |
| 2170 } | 2169 } |
| 2171 | 2170 |
| 2172 | 2171 |
| 2173 enum RightTrimMode { FROM_GC, FROM_MUTATOR }; | 2172 enum RightTrimMode { FROM_GC, FROM_MUTATOR }; |
| 2174 | 2173 |
| 2175 | 2174 |
| 2176 static void ZapEndOfFixedArray(Address new_end, int to_trim) { | 2175 static void ZapEndOfFixedArray(Address new_end, int to_trim) { |
| 2177 // If we are doing a big trim in old space then we zap the space. | 2176 // If we are doing a big trim in old space then we zap the space. |
| 2178 Object** zap = reinterpret_cast<Object**>(new_end); | 2177 Object** zap = reinterpret_cast<Object**>(new_end); |
| 2179 zap++; // Header of filler must be at least one word so skip that. | |
| 2180 for (int i = 1; i < to_trim; i++) { | 2178 for (int i = 1; i < to_trim; i++) { |
| 2181 *zap++ = Smi::FromInt(0); | 2179 *zap++ = Smi::FromInt(0); |
| 2182 } | 2180 } |
| 2183 } | 2181 } |
| 2184 | 2182 |
| 2185 | |
| 2186 template<RightTrimMode trim_mode> | 2183 template<RightTrimMode trim_mode> |
| 2187 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { | 2184 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { |
| 2188 ASSERT(elms->map() != HEAP->fixed_cow_array_map()); | 2185 ASSERT(elms->map() != HEAP->fixed_cow_array_map()); |
| 2189 // For now this trick is only applied to fixed arrays in new and paged space. | 2186 // For now this trick is only applied to fixed arrays in new and paged space. |
| 2190 ASSERT(!HEAP->lo_space()->Contains(elms)); | 2187 ASSERT(!HEAP->lo_space()->Contains(elms)); |
| 2191 | 2188 |
| 2192 const int len = elms->length(); | 2189 const int len = elms->length(); |
| 2193 | 2190 |
| 2194 ASSERT(to_trim < len); | 2191 ASSERT(to_trim < len); |
| 2195 | 2192 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2216 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { | 2213 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { |
| 2217 if (trim_mode == FROM_GC) { | 2214 if (trim_mode == FROM_GC) { |
| 2218 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); | 2215 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); |
| 2219 } else { | 2216 } else { |
| 2220 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); | 2217 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); |
| 2221 } | 2218 } |
| 2222 } | 2219 } |
| 2223 } | 2220 } |
| 2224 | 2221 |
| 2225 | 2222 |
| 2226 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 2223 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, |
| 2227 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2224 Handle<Object> descriptors) { |
| 2228 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | |
| 2229 int number_of_descriptors = descriptors->number_of_descriptors(); | |
| 2230 Isolate* isolate = map->GetIsolate(); | |
| 2231 Handle<DescriptorArray> new_descriptors = | |
| 2232 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | |
| 2233 DescriptorArray::WhitenessWitness witness(*new_descriptors); | |
| 2234 | |
| 2235 for (int i = 0; i < number_of_descriptors; ++i) { | |
| 2236 new_descriptors->CopyFrom(i, *descriptors, i, witness); | |
| 2237 } | |
| 2238 | |
| 2239 Map::SetDescriptors(map, new_descriptors); | |
| 2240 } | |
| 2241 | |
| 2242 | |
| 2243 void Map::AppendCallbackDescriptors(Handle<Map> map, | |
| 2244 Handle<Object> descriptors) { | |
| 2245 Isolate* isolate = map->GetIsolate(); | 2225 Isolate* isolate = map->GetIsolate(); |
| 2246 Handle<DescriptorArray> array(map->instance_descriptors()); | 2226 Handle<DescriptorArray> array(map->instance_descriptors()); |
| 2247 NeanderArray callbacks(descriptors); | 2227 v8::NeanderArray callbacks(descriptors); |
| 2248 int nof_callbacks = callbacks.length(); | 2228 int nof_callbacks = callbacks.length(); |
| 2249 | 2229 int descriptor_count = array->number_of_descriptors(); |
| 2250 ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks); | 2230 ASSERT(descriptor_count == map->NumberOfOwnDescriptors()); |
| 2251 | 2231 |
| 2252 // Ensure the keys are symbols before writing them into the instance | 2232 // Ensure the keys are symbols before writing them into the instance |
| 2253 // descriptor. Since it may cause a GC, it has to be done before we | 2233 // descriptor. Since it may cause a GC, it has to be done before we |
| 2254 // temporarily put the heap in an invalid state while appending descriptors. | 2234 // temporarily put the heap in an invalid state while appending descriptors. |
| 2255 for (int i = 0; i < nof_callbacks; ++i) { | 2235 for (int i = 0; i < nof_callbacks; ++i) { |
| 2256 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); | 2236 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); |
| 2257 Handle<String> key = | 2237 Handle<String> key = |
| 2258 isolate->factory()->SymbolFromString( | 2238 isolate->factory()->SymbolFromString( |
| 2259 Handle<String>(String::cast(entry->name()))); | 2239 Handle<String>(String::cast(entry->name()))); |
| 2260 entry->set_name(*key); | 2240 entry->set_name(*key); |
| 2261 } | 2241 } |
| 2262 | 2242 |
| 2263 int nof = map->NumberOfOwnDescriptors(); | 2243 Handle<DescriptorArray> result = |
| 2244 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks); |
| 2245 |
| 2246 // Ensure that marking will not progress and change color of objects. |
| 2247 DescriptorArray::WhitenessWitness witness(*result); |
| 2248 |
| 2249 // Copy the descriptors from the array. |
| 2250 for (int i = 0; i < descriptor_count; i++) { |
| 2251 result->CopyFrom(i, *array, i, witness); |
| 2252 } |
| 2253 |
| 2254 // After this point the GC is not allowed to run anymore until the map is in a |
| 2255 // consistent state again, i.e., all the descriptors are appended and the |
| 2256 // descriptor array is trimmed to the right size. |
| 2257 Map::SetDescriptors(map, result); |
| 2264 | 2258 |
| 2265 // Fill in new callback descriptors. Process the callbacks from | 2259 // Fill in new callback descriptors. Process the callbacks from |
| 2266 // back to front so that the last callback with a given name takes | 2260 // back to front so that the last callback with a given name takes |
| 2267 // precedence over previously added callbacks with that name. | 2261 // precedence over previously added callbacks with that name. |
| 2262 int nof = descriptor_count; |
| 2268 for (int i = nof_callbacks - 1; i >= 0; i--) { | 2263 for (int i = nof_callbacks - 1; i >= 0; i--) { |
| 2269 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); | 2264 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); |
| 2270 String* key = String::cast(entry->name()); | 2265 String* key = String::cast(entry->name()); |
| 2271 // Check if a descriptor with this name already exists before writing. | 2266 // Check if a descriptor with this name already exists before writing. |
| 2272 if (array->Search(key, nof) == DescriptorArray::kNotFound) { | 2267 if (result->Search(key, nof) == DescriptorArray::kNotFound) { |
| 2273 CallbacksDescriptor desc(key, entry, entry->property_attributes()); | 2268 CallbacksDescriptor desc(key, entry, entry->property_attributes()); |
| 2274 array->Append(&desc); | 2269 map->AppendDescriptor(&desc, witness); |
| 2275 nof += 1; | 2270 nof += 1; |
| 2276 } | 2271 } |
| 2277 } | 2272 } |
| 2278 | 2273 |
| 2279 map->SetNumberOfOwnDescriptors(nof); | 2274 ASSERT(nof == map->NumberOfOwnDescriptors()); |
| 2275 |
| 2276 // Reinstall the original descriptor array if no new elements were added. |
| 2277 if (nof == descriptor_count) { |
| 2278 Map::SetDescriptors(map, array); |
| 2279 return; |
| 2280 } |
| 2281 |
| 2282 // If duplicates were detected, trim the descriptor array to the right size. |
| 2283 int new_array_size = DescriptorArray::LengthFor(nof); |
| 2284 if (new_array_size < result->length()) { |
| 2285 RightTrimFixedArray<FROM_MUTATOR>( |
| 2286 isolate->heap(), *result, result->length() - new_array_size); |
| 2287 } |
| 2280 } | 2288 } |
| 2281 | 2289 |
| 2282 | 2290 |
| 2283 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { | 2291 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { |
| 2284 ASSERT(!map.is_null()); | 2292 ASSERT(!map.is_null()); |
| 2285 for (int i = 0; i < maps->length(); ++i) { | 2293 for (int i = 0; i < maps->length(); ++i) { |
| 2286 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; | 2294 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; |
| 2287 } | 2295 } |
| 2288 return false; | 2296 return false; |
| 2289 } | 2297 } |
| (...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3333 | 3341 |
| 3334 // The global object is always normalized. | 3342 // The global object is always normalized. |
| 3335 ASSERT(!IsGlobalObject()); | 3343 ASSERT(!IsGlobalObject()); |
| 3336 // JSGlobalProxy must never be normalized | 3344 // JSGlobalProxy must never be normalized |
| 3337 ASSERT(!IsJSGlobalProxy()); | 3345 ASSERT(!IsJSGlobalProxy()); |
| 3338 | 3346 |
| 3339 Map* map_of_this = map(); | 3347 Map* map_of_this = map(); |
| 3340 | 3348 |
| 3341 // Allocate new content. | 3349 // Allocate new content. |
| 3342 int real_size = map_of_this->NumberOfOwnDescriptors(); | 3350 int real_size = map_of_this->NumberOfOwnDescriptors(); |
| 3343 int property_count = real_size; | 3351 int property_count = |
| 3352 map_of_this->NumberOfDescribedProperties(OWN_DESCRIPTORS); |
| 3344 if (expected_additional_properties > 0) { | 3353 if (expected_additional_properties > 0) { |
| 3345 property_count += expected_additional_properties; | 3354 property_count += expected_additional_properties; |
| 3346 } else { | 3355 } else { |
| 3347 property_count += 2; // Make space for two more properties. | 3356 property_count += 2; // Make space for two more properties. |
| 3348 } | 3357 } |
| 3349 StringDictionary* dictionary; | 3358 StringDictionary* dictionary; |
| 3350 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); | 3359 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); |
| 3351 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 3360 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
| 3352 | 3361 |
| 3353 DescriptorArray* descs = map_of_this->instance_descriptors(); | 3362 DescriptorArray* descs = map_of_this->instance_descriptors(); |
| (...skipping 1643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4997 // descriptors in the descriptor array. | 5006 // descriptors in the descriptor array. |
| 4998 ASSERT(NumberOfOwnDescriptors() == | 5007 ASSERT(NumberOfOwnDescriptors() == |
| 4999 instance_descriptors()->number_of_descriptors()); | 5008 instance_descriptors()->number_of_descriptors()); |
| 5000 Map* result; | 5009 Map* result; |
| 5001 MaybeObject* maybe_result = CopyDropDescriptors(); | 5010 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 5002 if (!maybe_result->To(&result)) return maybe_result; | 5011 if (!maybe_result->To(&result)) return maybe_result; |
| 5003 | 5012 |
| 5004 String* name = descriptor->GetKey(); | 5013 String* name = descriptor->GetKey(); |
| 5005 | 5014 |
| 5006 TransitionArray* transitions; | 5015 TransitionArray* transitions; |
| 5007 MaybeObject* maybe_transitions = | 5016 MaybeObject* maybe_transitions = AddTransition(name, result); |
| 5008 AddTransition(name, result, SIMPLE_TRANSITION); | |
| 5009 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5017 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 5010 | 5018 |
| 5011 DescriptorArray* descriptors = instance_descriptors(); | 5019 DescriptorArray* descriptors = instance_descriptors(); |
| 5012 int old_size = descriptors->number_of_descriptors(); | 5020 int old_size = descriptors->number_of_descriptors(); |
| 5013 | 5021 |
| 5014 DescriptorArray* new_descriptors; | 5022 DescriptorArray* new_descriptors; |
| 5023 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); |
| 5024 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5025 DescriptorArray::WhitenessWitness witness(new_descriptors); |
| 5015 | 5026 |
| 5016 if (descriptors->NumberOfSlackDescriptors() > 0) { | 5027 for (int i = 0; i < old_size; ++i) { |
| 5017 new_descriptors = descriptors; | 5028 new_descriptors->CopyFrom(i, descriptors, i, witness); |
| 5018 new_descriptors->Append(descriptor); | 5029 } |
| 5019 } else { | 5030 new_descriptors->Append(descriptor, witness, old_size); |
| 5020 // Descriptor arrays grow by 50%. | |
| 5021 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( | |
| 5022 old_size, old_size < 4 ? 1 : old_size / 2); | |
| 5023 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 5024 | 5031 |
| 5025 DescriptorArray::WhitenessWitness witness(new_descriptors); | 5032 // If the source descriptors had an enum cache we copy it. This ensures that |
| 5026 | 5033 // the maps to which we push the new descriptor array back can rely on a |
| 5027 // Copy the descriptors, inserting a descriptor. | 5034 // cache always being available once it is set. If the map has more |
| 5028 for (int i = 0; i < old_size; ++i) { | 5035 // enumerated descriptors than available in the original cache, the cache |
| 5029 new_descriptors->CopyFrom(i, descriptors, i, witness); | 5036 // will be lazily replaced by the extended cache when needed. |
| 5030 } | 5037 if (descriptors->HasEnumCache()) { |
| 5031 | 5038 new_descriptors->CopyEnumCacheFrom(descriptors); |
| 5032 new_descriptors->Append(descriptor, witness); | |
| 5033 | |
| 5034 // If the source descriptors had an enum cache we copy it. This ensures that | |
| 5035 // the maps to which we push the new descriptor array back can rely on a | |
| 5036 // cache always being available once it is set. If the map has more | |
| 5037 // enumerated descriptors than available in the original cache, the cache | |
| 5038 // will be lazily replaced by the extended cache when needed. | |
| 5039 if (descriptors->HasEnumCache()) { | |
| 5040 new_descriptors->CopyEnumCacheFrom(descriptors); | |
| 5041 } | |
| 5042 } | 5039 } |
| 5043 | 5040 |
| 5044 transitions->set_descriptors(new_descriptors); | 5041 transitions->set_descriptors(new_descriptors); |
| 5045 | |
| 5046 set_transitions(transitions); | 5042 set_transitions(transitions); |
| 5047 result->SetBackPointer(this); | 5043 result->SetBackPointer(this); |
| 5048 set_owns_descriptors(false); | 5044 set_owns_descriptors(false); |
| 5049 | 5045 |
| 5050 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); | 5046 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); |
| 5051 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 5047 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 5052 | 5048 |
| 5053 return result; | 5049 return result; |
| 5054 } | 5050 } |
| 5055 | 5051 |
| 5056 | 5052 |
| 5057 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 5053 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 5058 String* name, | 5054 String* name, |
| 5059 TransitionFlag flag, | 5055 TransitionFlag flag) { |
| 5060 int descriptor_index) { | |
| 5061 ASSERT(descriptors->IsSortedNoDuplicates()); | 5056 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 5062 | 5057 |
| 5063 Map* result; | 5058 Map* result; |
| 5064 MaybeObject* maybe_result = CopyDropDescriptors(); | 5059 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 5065 if (!maybe_result->To(&result)) return maybe_result; | 5060 if (!maybe_result->To(&result)) return maybe_result; |
| 5066 | 5061 |
| 5067 // Unless we are creating a map with no descriptors and no back pointer, we | 5062 // Unless we are creating a map with no descriptors and no back pointer, we |
| 5068 // insert the descriptor array locally. | 5063 // insert the descriptor array locally. |
| 5069 if (!descriptors->IsEmpty()) { | 5064 if (!descriptors->IsEmpty()) { |
| 5070 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); | 5065 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); |
| 5071 if (maybe_failure->IsFailure()) return maybe_failure; | 5066 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5072 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); | 5067 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); |
| 5073 } | 5068 } |
| 5074 | 5069 |
| 5075 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 5070 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
| 5076 TransitionArray* transitions; | 5071 TransitionArray* transitions; |
| 5077 SimpleTransitionFlag simple_flag = | 5072 MaybeObject* maybe_transitions = AddTransition(name, result); |
| 5078 (descriptor_index == descriptors->number_of_descriptors() - 1) | |
| 5079 ? SIMPLE_TRANSITION | |
| 5080 : FULL_TRANSITION; | |
| 5081 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | |
| 5082 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5073 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 5083 | 5074 |
| 5084 if (descriptors->IsEmpty()) { | 5075 if (descriptors->IsEmpty()) { |
| 5085 if (owns_descriptors()) { | 5076 if (owns_descriptors()) { |
| 5086 // If the copied map has no added fields, and the parent map owns its | 5077 // If the copied map has no added fields, and the parent map owns its |
| 5087 // descriptors, those descriptors have to be empty. In that case, | 5078 // descriptors, those descriptors have to be empty. In that case, |
| 5088 // transfer ownership of the descriptors to the new child. | 5079 // transfer ownership of the descriptors to the new child. |
| 5089 ASSERT(instance_descriptors()->IsEmpty()); | 5080 ASSERT(instance_descriptors()->IsEmpty()); |
| 5090 set_owns_descriptors(false); | 5081 set_owns_descriptors(false); |
| 5091 } else { | 5082 } else { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5176 JSFunction* ctor = JSFunction::cast(constructor()); | 5167 JSFunction* ctor = JSFunction::cast(constructor()); |
| 5177 Map* map = ctor->initial_map(); | 5168 Map* map = ctor->initial_map(); |
| 5178 DescriptorArray* descriptors = map->instance_descriptors(); | 5169 DescriptorArray* descriptors = map->instance_descriptors(); |
| 5179 | 5170 |
| 5180 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 5171 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 5181 DescriptorArray* new_descriptors; | 5172 DescriptorArray* new_descriptors; |
| 5182 MaybeObject* maybe_descriptors = | 5173 MaybeObject* maybe_descriptors = |
| 5183 descriptors->CopyUpTo(number_of_own_descriptors); | 5174 descriptors->CopyUpTo(number_of_own_descriptors); |
| 5184 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5175 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5185 | 5176 |
| 5186 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); | 5177 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); |
| 5187 } | 5178 } |
| 5188 | 5179 |
| 5189 | 5180 |
| 5190 MaybeObject* Map::Copy() { | 5181 MaybeObject* Map::Copy() { |
| 5191 DescriptorArray* descriptors = instance_descriptors(); | 5182 DescriptorArray* descriptors = instance_descriptors(); |
| 5192 DescriptorArray* new_descriptors; | 5183 DescriptorArray* new_descriptors; |
| 5193 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 5184 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 5194 MaybeObject* maybe_descriptors = | 5185 MaybeObject* maybe_descriptors = |
| 5195 descriptors->CopyUpTo(number_of_own_descriptors); | 5186 descriptors->CopyUpTo(number_of_own_descriptors); |
| 5196 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5187 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5197 | 5188 |
| 5198 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); | 5189 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION); |
| 5199 } | 5190 } |
| 5200 | 5191 |
| 5201 | 5192 |
| 5202 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, | 5193 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
| 5203 TransitionFlag flag) { | 5194 TransitionFlag flag) { |
| 5204 DescriptorArray* descriptors = instance_descriptors(); | 5195 DescriptorArray* descriptors = instance_descriptors(); |
| 5205 | 5196 |
| 5206 // Ensure the key is a symbol. | 5197 // Ensure the key is a symbol. |
| 5207 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); | 5198 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
| 5208 if (maybe_failure->IsFailure()) return maybe_failure; | 5199 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5209 | 5200 |
| 5210 int old_size = NumberOfOwnDescriptors(); | 5201 int old_size = NumberOfOwnDescriptors(); |
| 5211 int new_size = old_size + 1; | 5202 int new_size = old_size + 1; |
| 5212 descriptor->SetEnumerationIndex(new_size); | 5203 descriptor->SetEnumerationIndex(new_size); |
| 5213 | 5204 |
| 5214 if (flag == INSERT_TRANSITION && | 5205 if (flag == INSERT_TRANSITION && |
| 5215 owns_descriptors() && | 5206 owns_descriptors() && |
| 5216 CanHaveMoreTransitions()) { | 5207 CanHaveMoreTransitions()) { |
| 5217 return ShareDescriptor(descriptor); | 5208 return ShareDescriptor(descriptor); |
| 5218 } | 5209 } |
| 5219 | 5210 |
| 5220 DescriptorArray* new_descriptors; | 5211 DescriptorArray* new_descriptors; |
| 5221 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1); | 5212 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); |
| 5222 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5213 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5223 | 5214 |
| 5224 DescriptorArray::WhitenessWitness witness(new_descriptors); | 5215 DescriptorArray::WhitenessWitness witness(new_descriptors); |
| 5225 | 5216 |
| 5226 // Copy the descriptors, inserting a descriptor. | 5217 // Copy the descriptors, inserting a descriptor. |
| 5227 for (int i = 0; i < old_size; ++i) { | 5218 for (int i = 0; i < old_size; ++i) { |
| 5228 new_descriptors->CopyFrom(i, descriptors, i, witness); | 5219 new_descriptors->CopyFrom(i, descriptors, i, witness); |
| 5229 } | 5220 } |
| 5230 | 5221 |
| 5231 if (old_size != descriptors->number_of_descriptors()) { | 5222 new_descriptors->Set(old_size, descriptor, witness); |
| 5232 new_descriptors->SetNumberOfDescriptors(new_size); | 5223 new_descriptors->Sort(); |
| 5233 new_descriptors->Set(old_size, descriptor, witness); | |
| 5234 new_descriptors->Sort(); | |
| 5235 } else { | |
| 5236 new_descriptors->Append(descriptor, witness); | |
| 5237 } | |
| 5238 | 5224 |
| 5239 String* key = descriptor->GetKey(); | 5225 return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag); |
| 5240 int insertion_index = new_descriptors->number_of_descriptors() - 1; | |
| 5241 | |
| 5242 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); | |
| 5243 } | 5226 } |
| 5244 | 5227 |
| 5245 | 5228 |
| 5246 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, | 5229 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, |
| 5247 TransitionFlag flag) { | 5230 TransitionFlag flag) { |
| 5248 DescriptorArray* old_descriptors = instance_descriptors(); | 5231 DescriptorArray* old_descriptors = instance_descriptors(); |
| 5249 | 5232 |
| 5250 // Ensure the key is a symbol. | 5233 // Ensure the key is a symbol. |
| 5251 MaybeObject* maybe_result = descriptor->KeyToSymbol(); | 5234 MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
| 5252 if (maybe_result->IsFailure()) return maybe_result; | 5235 if (maybe_result->IsFailure()) return maybe_result; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5308 if (i == insertion_index) { | 5291 if (i == insertion_index) { |
| 5309 new_descriptors->Set(i, descriptor, witness); | 5292 new_descriptors->Set(i, descriptor, witness); |
| 5310 } else { | 5293 } else { |
| 5311 new_descriptors->CopyFrom(i, descriptors, i, witness); | 5294 new_descriptors->CopyFrom(i, descriptors, i, witness); |
| 5312 } | 5295 } |
| 5313 } | 5296 } |
| 5314 | 5297 |
| 5315 // Re-sort if descriptors were removed. | 5298 // Re-sort if descriptors were removed. |
| 5316 if (new_size != descriptors->length()) new_descriptors->Sort(); | 5299 if (new_size != descriptors->length()) new_descriptors->Sort(); |
| 5317 | 5300 |
| 5318 return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index); | 5301 return CopyReplaceDescriptors(new_descriptors, key, flag); |
| 5319 } | 5302 } |
| 5320 | 5303 |
| 5321 | 5304 |
| 5322 void Map::UpdateCodeCache(Handle<Map> map, | 5305 void Map::UpdateCodeCache(Handle<Map> map, |
| 5323 Handle<String> name, | 5306 Handle<String> name, |
| 5324 Handle<Code> code) { | 5307 Handle<Code> code) { |
| 5325 Isolate* isolate = map->GetIsolate(); | 5308 Isolate* isolate = map->GetIsolate(); |
| 5326 CALL_HEAP_FUNCTION_VOID(isolate, | 5309 CALL_HEAP_FUNCTION_VOID(isolate, |
| 5327 map->UpdateCodeCache(*name, *code)); | 5310 map->UpdateCodeCache(*name, *code)); |
| 5328 } | 5311 } |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6083 bool FixedArray::IsEqualTo(FixedArray* other) { | 6066 bool FixedArray::IsEqualTo(FixedArray* other) { |
| 6084 if (length() != other->length()) return false; | 6067 if (length() != other->length()) return false; |
| 6085 for (int i = 0 ; i < length(); ++i) { | 6068 for (int i = 0 ; i < length(); ++i) { |
| 6086 if (get(i) != other->get(i)) return false; | 6069 if (get(i) != other->get(i)) return false; |
| 6087 } | 6070 } |
| 6088 return true; | 6071 return true; |
| 6089 } | 6072 } |
| 6090 #endif | 6073 #endif |
| 6091 | 6074 |
| 6092 | 6075 |
| 6093 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) { | 6076 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { |
| 6094 Heap* heap = Isolate::Current()->heap(); | 6077 Heap* heap = Isolate::Current()->heap(); |
| 6095 // Do not use DescriptorArray::cast on incomplete object. | 6078 // Do not use DescriptorArray::cast on incomplete object. |
| 6096 int size = number_of_descriptors + slack; | |
| 6097 if (size == 0) return heap->empty_descriptor_array(); | |
| 6098 FixedArray* result; | 6079 FixedArray* result; |
| 6080 if (number_of_descriptors == 0) return heap->empty_descriptor_array(); |
| 6099 // Allocate the array of keys. | 6081 // Allocate the array of keys. |
| 6100 MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size)); | 6082 MaybeObject* maybe_array = |
| 6083 heap->AllocateFixedArray(LengthFor(number_of_descriptors)); |
| 6101 if (!maybe_array->To(&result)) return maybe_array; | 6084 if (!maybe_array->To(&result)) return maybe_array; |
| 6102 | 6085 |
| 6103 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); | |
| 6104 result->set(kEnumCacheIndex, Smi::FromInt(0)); | 6086 result->set(kEnumCacheIndex, Smi::FromInt(0)); |
| 6105 return result; | 6087 return result; |
| 6106 } | 6088 } |
| 6107 | 6089 |
| 6108 | 6090 |
| 6109 void DescriptorArray::ClearEnumCache() { | 6091 void DescriptorArray::ClearEnumCache() { |
| 6110 set(kEnumCacheIndex, Smi::FromInt(0)); | 6092 set(kEnumCacheIndex, Smi::FromInt(0)); |
| 6111 } | 6093 } |
| 6112 | 6094 |
| 6113 | 6095 |
| 6114 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 6096 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| 6115 FixedArray* new_cache, | 6097 FixedArray* new_cache, |
| 6116 Object* new_index_cache) { | 6098 Object* new_index_cache) { |
| 6117 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 6099 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
| 6118 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); | 6100 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
| 6119 if (HasEnumCache()) { | 6101 if (HasEnumCache()) { |
| 6120 ASSERT(new_cache->length() > GetEnumCache()->length()); | 6102 ASSERT(new_cache->length() > FixedArray::cast(GetEnumCache())->length()); |
| 6121 FixedArray::cast(get(kEnumCacheIndex))-> | 6103 FixedArray::cast(get(kEnumCacheIndex))-> |
| 6122 set(kEnumCacheBridgeCacheIndex, new_cache); | 6104 set(kEnumCacheBridgeCacheIndex, new_cache); |
| 6123 FixedArray::cast(get(kEnumCacheIndex))-> | 6105 FixedArray::cast(get(kEnumCacheIndex))-> |
| 6124 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 6106 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
| 6125 } else { | 6107 } else { |
| 6126 ASSERT(!IsEmpty()); | 6108 ASSERT(!IsEmpty()); |
| 6127 FixedArray::cast(bridge_storage)-> | 6109 FixedArray::cast(bridge_storage)-> |
| 6128 set(kEnumCacheBridgeCacheIndex, new_cache); | 6110 set(kEnumCacheBridgeCacheIndex, new_cache); |
| 6129 FixedArray::cast(bridge_storage)-> | 6111 FixedArray::cast(bridge_storage)-> |
| 6130 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 6112 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
| (...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7383 | 7365 |
| 7384 void StringHasher::AddSurrogatePairNoIndex(uc32 c) { | 7366 void StringHasher::AddSurrogatePairNoIndex(uc32 c) { |
| 7385 uint16_t lead = unibrow::Utf16::LeadSurrogate(c); | 7367 uint16_t lead = unibrow::Utf16::LeadSurrogate(c); |
| 7386 AddCharacterNoIndex(lead); | 7368 AddCharacterNoIndex(lead); |
| 7387 uint16_t trail = unibrow::Utf16::TrailSurrogate(c); | 7369 uint16_t trail = unibrow::Utf16::TrailSurrogate(c); |
| 7388 AddCharacterNoIndex(trail); | 7370 AddCharacterNoIndex(trail); |
| 7389 } | 7371 } |
| 7390 | 7372 |
| 7391 | 7373 |
| 7392 uint32_t StringHasher::GetHashField() { | 7374 uint32_t StringHasher::GetHashField() { |
| 7375 ASSERT(is_valid()); |
| 7393 if (length_ <= String::kMaxHashCalcLength) { | 7376 if (length_ <= String::kMaxHashCalcLength) { |
| 7394 if (is_array_index()) { | 7377 if (is_array_index()) { |
| 7395 return MakeArrayIndexHash(array_index(), length_); | 7378 return MakeArrayIndexHash(array_index(), length_); |
| 7396 } | 7379 } |
| 7397 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask; | 7380 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask; |
| 7398 } else { | 7381 } else { |
| 7399 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; | 7382 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; |
| 7400 } | 7383 } |
| 7401 } | 7384 } |
| 7402 | 7385 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7446 | 7429 |
| 7447 // Clear a possible back pointer in case the transition leads to a dead map. | 7430 // Clear a possible back pointer in case the transition leads to a dead map. |
| 7448 // Return true in case a back pointer has been cleared and false otherwise. | 7431 // Return true in case a back pointer has been cleared and false otherwise. |
| 7449 static bool ClearBackPointer(Heap* heap, Map* target) { | 7432 static bool ClearBackPointer(Heap* heap, Map* target) { |
| 7450 if (Marking::MarkBitFrom(target).Get()) return false; | 7433 if (Marking::MarkBitFrom(target).Get()) return false; |
| 7451 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | 7434 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); |
| 7452 return true; | 7435 return true; |
| 7453 } | 7436 } |
| 7454 | 7437 |
| 7455 | 7438 |
| 7456 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) { | |
| 7457 int live_enum = map->EnumLength(); | |
| 7458 if (live_enum == Map::kInvalidEnumCache) { | |
| 7459 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); | |
| 7460 } | |
| 7461 if (live_enum == 0) return descriptors->ClearEnumCache(); | |
| 7462 | |
| 7463 FixedArray* enum_cache = descriptors->GetEnumCache(); | |
| 7464 | |
| 7465 int to_trim = enum_cache->length() - live_enum; | |
| 7466 if (to_trim <= 0) return; | |
| 7467 RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim); | |
| 7468 | |
| 7469 if (!descriptors->HasEnumIndicesCache()) return; | |
| 7470 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); | |
| 7471 RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim); | |
| 7472 } | |
| 7473 | |
| 7474 | |
| 7475 static void TrimDescriptorArray(Heap* heap, | |
| 7476 Map* map, | |
| 7477 DescriptorArray* descriptors, | |
| 7478 int number_of_own_descriptors) { | |
| 7479 int number_of_descriptors = descriptors->number_of_descriptors(); | |
| 7480 int to_trim = number_of_descriptors - number_of_own_descriptors; | |
| 7481 if (to_trim <= 0) return; | |
| 7482 | |
| 7483 // Maximally keep 50% of unused descriptors. | |
| 7484 int keep = Min(to_trim, number_of_own_descriptors / 2); | |
| 7485 for (int i = number_of_own_descriptors; | |
| 7486 i < number_of_own_descriptors + keep; | |
| 7487 ++i) { | |
| 7488 descriptors->EraseDescriptor(heap, i); | |
| 7489 } | |
| 7490 | |
| 7491 if (to_trim > keep) { | |
| 7492 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep); | |
| 7493 } | |
| 7494 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | |
| 7495 | |
| 7496 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); | |
| 7497 descriptors->Sort(); | |
| 7498 } | |
| 7499 | |
| 7500 | |
| 7501 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, | 7439 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, |
| 7502 // because it cannot be called from outside the GC and we already have methods | 7440 // because it cannot be called from outside the GC and we already have methods |
| 7503 // depending on the transitions layout in the GC anyways. | 7441 // depending on the transitions layout in the GC anyways. |
| 7504 void Map::ClearNonLiveTransitions(Heap* heap) { | 7442 void Map::ClearNonLiveTransitions(Heap* heap) { |
| 7505 // If there are no transitions to be cleared, return. | 7443 // If there are no transitions to be cleared, return. |
| 7506 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7444 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 7507 // properly cleared. | 7445 // properly cleared. |
| 7508 if (!HasTransitionArray()) return; | 7446 if (!HasTransitionArray()) return; |
| 7509 | 7447 |
| 7510 TransitionArray* t = transitions(); | 7448 TransitionArray* t = transitions(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7549 // If there are no transitions to be cleared, return. | 7487 // If there are no transitions to be cleared, return. |
| 7550 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7488 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 7551 // properly cleared. | 7489 // properly cleared. |
| 7552 if (transition_index == t->number_of_transitions()) return; | 7490 if (transition_index == t->number_of_transitions()) return; |
| 7553 } | 7491 } |
| 7554 | 7492 |
| 7555 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 7493 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 7556 | 7494 |
| 7557 if (descriptors_owner_died) { | 7495 if (descriptors_owner_died) { |
| 7558 if (number_of_own_descriptors > 0) { | 7496 if (number_of_own_descriptors > 0) { |
| 7559 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 7497 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 7498 int to_trim = number_of_descriptors - number_of_own_descriptors; |
| 7499 if (to_trim > 0) { |
| 7500 RightTrimFixedArray<FROM_GC>( |
| 7501 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize); |
| 7502 if (descriptors->HasEnumCache()) { |
| 7503 int live_enum = |
| 7504 NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); |
| 7505 if (live_enum == 0) { |
| 7506 descriptors->ClearEnumCache(); |
| 7507 } else { |
| 7508 FixedArray* enum_cache = |
| 7509 FixedArray::cast(descriptors->GetEnumCache()); |
| 7510 to_trim = enum_cache->length() - live_enum; |
| 7511 if (to_trim > 0) { |
| 7512 RightTrimFixedArray<FROM_GC>( |
| 7513 heap, FixedArray::cast(descriptors->GetEnumCache()), to_trim); |
| 7514 } |
| 7515 } |
| 7516 } |
| 7517 descriptors->Sort(); |
| 7518 } |
| 7560 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 7519 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 7561 } else { | 7520 } else { |
| 7562 t->set_descriptors(heap->empty_descriptor_array()); | 7521 t->set_descriptors(heap->empty_descriptor_array()); |
| 7563 } | 7522 } |
| 7564 set_owns_descriptors(true); | 7523 set_owns_descriptors(true); |
| 7565 } | 7524 } |
| 7566 | 7525 |
| 7567 // If the final transition array does not contain any live transitions, remove | 7526 // If the final transition array does not contain any live transitions, remove |
| 7568 // the transition array from the map. | 7527 // the transition array from the map. |
| 7569 if (transition_index == 0 && | 7528 if (transition_index == 0 && |
| 7570 !t->HasElementsTransition() && | 7529 !t->HasElementsTransition() && |
| 7571 !t->HasPrototypeTransitions() && | 7530 !t->HasPrototypeTransitions() && |
| 7572 number_of_own_descriptors == 0) { | 7531 number_of_own_descriptors == 0) { |
| 7573 ASSERT(owns_descriptors()); | 7532 ASSERT(owns_descriptors()); |
| 7574 return ClearTransitions(heap); | 7533 return ClearTransitions(heap); |
| 7575 } | 7534 } |
| 7576 | 7535 |
| 7577 int trim = t->number_of_transitions() - transition_index; | 7536 int trim = t->number_of_transitions() - transition_index; |
| 7578 if (trim > 0) { | 7537 if (trim > 0) { |
| 7579 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() | 7538 RightTrimFixedArray<FROM_GC>( |
| 7580 ? trim : trim * TransitionArray::kTransitionSize); | 7539 heap, t, trim * TransitionArray::kTransitionSize); |
| 7581 } | 7540 } |
| 7582 } | 7541 } |
| 7583 | 7542 |
| 7584 | 7543 |
| 7585 int Map::Hash() { | 7544 int Map::Hash() { |
| 7586 // For performance reasons we only hash the 3 most variable fields of a map: | 7545 // For performance reasons we only hash the 3 most variable fields of a map: |
| 7587 // constructor, prototype and bit_field2. | 7546 // constructor, prototype and bit_field2. |
| 7588 | 7547 |
| 7589 // Shift away the tag. | 7548 // Shift away the tag. |
| 7590 int hash = (static_cast<uint32_t>( | 7549 int hash = (static_cast<uint32_t>( |
| (...skipping 2926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10517 ASSERT(map()->has_indexed_interceptor()); | 10476 ASSERT(map()->has_indexed_interceptor()); |
| 10518 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 10477 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 10519 ASSERT(constructor->shared()->IsApiFunction()); | 10478 ASSERT(constructor->shared()->IsApiFunction()); |
| 10520 Object* result = | 10479 Object* result = |
| 10521 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 10480 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 10522 return InterceptorInfo::cast(result); | 10481 return InterceptorInfo::cast(result); |
| 10523 } | 10482 } |
| 10524 | 10483 |
| 10525 | 10484 |
| 10526 MaybeObject* JSObject::GetPropertyPostInterceptor( | 10485 MaybeObject* JSObject::GetPropertyPostInterceptor( |
| 10527 Object* receiver, | 10486 JSReceiver* receiver, |
| 10528 String* name, | 10487 String* name, |
| 10529 PropertyAttributes* attributes) { | 10488 PropertyAttributes* attributes) { |
| 10530 // Check local property in holder, ignore interceptor. | 10489 // Check local property in holder, ignore interceptor. |
| 10531 LookupResult result(GetIsolate()); | 10490 LookupResult result(GetIsolate()); |
| 10532 LocalLookupRealNamedProperty(name, &result); | 10491 LocalLookupRealNamedProperty(name, &result); |
| 10533 if (result.IsFound()) { | 10492 if (result.IsFound()) { |
| 10534 return GetProperty(receiver, &result, name, attributes); | 10493 return GetProperty(receiver, &result, name, attributes); |
| 10535 } | 10494 } |
| 10536 // Continue searching via the prototype chain. | 10495 // Continue searching via the prototype chain. |
| 10537 Object* pt = GetPrototype(); | 10496 Object* pt = GetPrototype(); |
| 10538 *attributes = ABSENT; | 10497 *attributes = ABSENT; |
| 10539 if (pt->IsNull()) return GetHeap()->undefined_value(); | 10498 if (pt->IsNull()) return GetHeap()->undefined_value(); |
| 10540 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 10499 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
| 10541 } | 10500 } |
| 10542 | 10501 |
| 10543 | 10502 |
| 10544 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 10503 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 10545 Object* receiver, | 10504 JSReceiver* receiver, |
| 10546 String* name, | 10505 String* name, |
| 10547 PropertyAttributes* attributes) { | 10506 PropertyAttributes* attributes) { |
| 10548 // Check local property in holder, ignore interceptor. | 10507 // Check local property in holder, ignore interceptor. |
| 10549 LookupResult result(GetIsolate()); | 10508 LookupResult result(GetIsolate()); |
| 10550 LocalLookupRealNamedProperty(name, &result); | 10509 LocalLookupRealNamedProperty(name, &result); |
| 10551 if (result.IsFound()) { | 10510 if (result.IsFound()) { |
| 10552 return GetProperty(receiver, &result, name, attributes); | 10511 return GetProperty(receiver, &result, name, attributes); |
| 10553 } | 10512 } |
| 10554 return GetHeap()->undefined_value(); | 10513 return GetHeap()->undefined_value(); |
| 10555 } | 10514 } |
| 10556 | 10515 |
| 10557 | 10516 |
| 10558 MaybeObject* JSObject::GetPropertyWithInterceptor( | 10517 MaybeObject* JSObject::GetPropertyWithInterceptor( |
| 10559 Object* receiver, | 10518 JSReceiver* receiver, |
| 10560 String* name, | 10519 String* name, |
| 10561 PropertyAttributes* attributes) { | 10520 PropertyAttributes* attributes) { |
| 10562 Isolate* isolate = GetIsolate(); | 10521 Isolate* isolate = GetIsolate(); |
| 10563 InterceptorInfo* interceptor = GetNamedInterceptor(); | 10522 InterceptorInfo* interceptor = GetNamedInterceptor(); |
| 10564 HandleScope scope(isolate); | 10523 HandleScope scope(isolate); |
| 10565 Handle<Object> receiver_handle(receiver); | 10524 Handle<JSReceiver> receiver_handle(receiver); |
| 10566 Handle<JSObject> holder_handle(this); | 10525 Handle<JSObject> holder_handle(this); |
| 10567 Handle<String> name_handle(name); | 10526 Handle<String> name_handle(name); |
| 10568 | 10527 |
| 10569 if (!interceptor->getter()->IsUndefined()) { | 10528 if (!interceptor->getter()->IsUndefined()) { |
| 10570 v8::NamedPropertyGetter getter = | 10529 v8::NamedPropertyGetter getter = |
| 10571 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 10530 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); |
| 10572 LOG(isolate, | 10531 LOG(isolate, |
| 10573 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 10532 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); |
| 10574 CustomArguments args(isolate, interceptor->data(), receiver, this); | 10533 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 10575 v8::AccessorInfo info(args.end()); | 10534 v8::AccessorInfo info(args.end()); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10687 } | 10646 } |
| 10688 } | 10647 } |
| 10689 | 10648 |
| 10690 LookupResult result(isolate); | 10649 LookupResult result(isolate); |
| 10691 LocalLookupRealNamedProperty(key, &result); | 10650 LocalLookupRealNamedProperty(key, &result); |
| 10692 return result.IsPropertyCallbacks(); | 10651 return result.IsPropertyCallbacks(); |
| 10693 } | 10652 } |
| 10694 | 10653 |
| 10695 | 10654 |
| 10696 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 10655 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| 10697 if (HasFastProperties()) { | 10656 return HasFastProperties() ? |
| 10698 Map* map = this->map(); | 10657 map()->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter) : |
| 10699 if (filter == NONE) return map->NumberOfOwnDescriptors(); | 10658 property_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 10700 if (filter == DONT_ENUM) { | |
| 10701 int result = map->EnumLength(); | |
| 10702 if (result != Map::kInvalidEnumCache) return result; | |
| 10703 } | |
| 10704 return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter); | |
| 10705 } | |
| 10706 return property_dictionary()->NumberOfElementsFilterAttributes(filter); | |
| 10707 } | 10659 } |
| 10708 | 10660 |
| 10709 | 10661 |
| 10710 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { | 10662 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { |
| 10711 Object* temp = get(i); | 10663 Object* temp = get(i); |
| 10712 set(i, get(j)); | 10664 set(i, get(j)); |
| 10713 set(j, temp); | 10665 set(j, temp); |
| 10714 if (this != numbers) { | 10666 if (this != numbers) { |
| 10715 temp = numbers->get(i); | 10667 temp = numbers->get(i); |
| 10716 numbers->set(i, Smi::cast(numbers->get(j))); | 10668 numbers->set(i, Smi::cast(numbers->get(j))); |
| (...skipping 2833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13550 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13502 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 13551 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13503 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 13552 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13504 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 13553 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13505 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 13554 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13506 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 13555 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13507 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 13556 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13508 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 13557 } | 13509 } |
| 13558 | 13510 |
| 13559 } } // namespace v8::internal | 13511 } } // namespace v8::internal |
| OLD | NEW |