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 |