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 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2236 current_map = maybe_transitioned_map; | 2236 current_map = maybe_transitioned_map; |
2237 } | 2237 } |
2238 } | 2238 } |
2239 return transitioned_map; | 2239 return transitioned_map; |
2240 } | 2240 } |
2241 | 2241 |
2242 | 2242 |
2243 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { | 2243 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) { |
2244 Map* current_map = map; | 2244 Map* current_map = map; |
2245 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); | 2245 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
2246 int to_index = GetSequenceIndexFromFastElementsKind(to_kind); | 2246 int to_index = IsFastElementsKind(to_kind) |
| 2247 ? GetSequenceIndexFromFastElementsKind(to_kind) |
| 2248 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
| 2249 |
| 2250 ASSERT(index <= to_index); |
| 2251 |
2247 for (; index < to_index; ++index) { | 2252 for (; index < to_index; ++index) { |
2248 Map* next_map = current_map->elements_transition_map(); | 2253 Map* next_map = current_map->elements_transition_map(); |
2249 if (next_map == NULL) { | 2254 if (next_map == NULL) { |
2250 return current_map; | 2255 return current_map; |
2251 } | 2256 } |
2252 current_map = next_map; | 2257 current_map = next_map; |
2253 } | 2258 } |
2254 ASSERT(current_map->elements_kind() == to_kind); | 2259 if (!IsFastElementsKind(to_kind)) { |
| 2260 Map* next_map = current_map->elements_transition_map(); |
| 2261 if (next_map != NULL && next_map->elements_kind() == to_kind) { |
| 2262 return next_map; |
| 2263 } |
| 2264 ASSERT(current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND); |
| 2265 } else { |
| 2266 ASSERT(current_map->elements_kind() == to_kind); |
| 2267 } |
2255 return current_map; | 2268 return current_map; |
2256 } | 2269 } |
2257 | 2270 |
2258 | 2271 |
2259 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 2272 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
2260 if (this->instance_descriptors()->MayContainTransitions() && | 2273 Map* to_map = FindClosestElementsTransition(this, to_kind); |
2261 IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) { | 2274 if (to_map->elements_kind() == to_kind) return to_map; |
2262 Map* to_map = FindClosestElementsTransition(this, to_kind); | |
2263 if (to_map->elements_kind() == to_kind) { | |
2264 return to_map; | |
2265 } | |
2266 } | |
2267 return NULL; | 2275 return NULL; |
2268 } | 2276 } |
2269 | 2277 |
2270 | 2278 |
2271 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { | 2279 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) { |
2272 ASSERT(elements_transition_map() == NULL); | 2280 ASSERT(elements_transition_map() == NULL || |
2273 ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) == | 2281 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
2274 (GetSequenceIndexFromFastElementsKind(next_kind) - 1)); | 2282 IsExternalArrayElementsKind( |
| 2283 elements_transition_map()->elements_kind())) && |
| 2284 (next_kind == DICTIONARY_ELEMENTS || |
| 2285 IsExternalArrayElementsKind(next_kind)))); |
| 2286 ASSERT(!IsFastElementsKind(next_kind) || |
| 2287 IsMoreGeneralElementsKindTransition(elements_kind(), next_kind)); |
| 2288 ASSERT(next_kind != elements_kind()); |
2275 | 2289 |
2276 Map* next_map; | 2290 Map* next_map; |
2277 MaybeObject* maybe_next_map = | 2291 MaybeObject* maybe_next_map = |
2278 this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED); | 2292 this->CopyDropTransitions(DescriptorArray::CANNOT_BE_SHARED); |
2279 if (!maybe_next_map->To(&next_map)) return maybe_next_map; | 2293 if (!maybe_next_map->To(&next_map)) return maybe_next_map; |
2280 | 2294 |
2281 next_map->set_elements_kind(next_kind); | 2295 next_map->set_elements_kind(next_kind); |
2282 next_map->SetBackPointer(this); | 2296 next_map->SetBackPointer(this); |
2283 this->set_elements_transition_map(next_map); | 2297 this->set_elements_transition_map(next_map); |
2284 return next_map; | 2298 return next_map; |
2285 } | 2299 } |
2286 | 2300 |
2287 | 2301 |
2288 static MaybeObject* AddMissingElementsTransitions(Map* map, | 2302 static MaybeObject* AddMissingElementsTransitions(Map* map, |
2289 ElementsKind to_kind) { | 2303 ElementsKind to_kind) { |
2290 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1; | 2304 ASSERT(IsFastElementsKind(map->elements_kind())); |
2291 int to_index = GetSequenceIndexFromFastElementsKind(to_kind); | 2305 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()); |
| 2306 int to_index = IsFastElementsKind(to_kind) |
| 2307 ? GetSequenceIndexFromFastElementsKind(to_kind) |
| 2308 : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
| 2309 |
2292 ASSERT(index <= to_index); | 2310 ASSERT(index <= to_index); |
2293 | 2311 |
2294 Map* current_map = map; | 2312 Map* current_map = map; |
2295 | 2313 |
2296 for (; index <= to_index; ++index) { | 2314 for (; index < to_index; ++index) { |
2297 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index); | 2315 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1); |
2298 MaybeObject* maybe_next_map = | 2316 MaybeObject* maybe_next_map = |
2299 current_map->CreateNextElementsTransition(next_kind); | 2317 current_map->CreateNextElementsTransition(next_kind); |
2300 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; | 2318 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
2301 } | 2319 } |
2302 | 2320 |
| 2321 // In case we are exiting the fast elements kind system, just add the map in |
| 2322 // the end. |
| 2323 if (!IsFastElementsKind(to_kind)) { |
| 2324 MaybeObject* maybe_next_map = |
| 2325 current_map->CreateNextElementsTransition(to_kind); |
| 2326 if (!maybe_next_map->To(¤t_map)) return maybe_next_map; |
| 2327 } |
| 2328 |
2303 ASSERT(current_map->elements_kind() == to_kind); | 2329 ASSERT(current_map->elements_kind() == to_kind); |
2304 return current_map; | 2330 return current_map; |
2305 } | 2331 } |
2306 | 2332 |
2307 | 2333 |
2308 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, | 2334 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
2309 ElementsKind to_kind) { | 2335 ElementsKind to_kind) { |
2310 Isolate* isolate = object->GetIsolate(); | 2336 Isolate* isolate = object->GetIsolate(); |
2311 CALL_HEAP_FUNCTION(isolate, | 2337 CALL_HEAP_FUNCTION(isolate, |
2312 object->GetElementsTransitionMap(isolate, to_kind), | 2338 object->GetElementsTransitionMap(isolate, to_kind), |
(...skipping 25 matching lines...) Expand all Loading... |
2338 return start_map; | 2364 return start_map; |
2339 } | 2365 } |
2340 | 2366 |
2341 Context* global_context = GetIsolate()->context()->global_context(); | 2367 Context* global_context = GetIsolate()->context()->global_context(); |
2342 bool allow_store_transition = | 2368 bool allow_store_transition = |
2343 // Only remember the map transition if the object's map is NOT equal to | 2369 // Only remember the map transition if the object's map is NOT equal to |
2344 // the global object_function's map and there is not an already existing | 2370 // the global object_function's map and there is not an already existing |
2345 // non-matching element transition. | 2371 // non-matching element transition. |
2346 (global_context->object_function()->map() != map()) && | 2372 (global_context->object_function()->map() != map()) && |
2347 !start_map->IsUndefined() && !start_map->is_shared() && | 2373 !start_map->IsUndefined() && !start_map->is_shared() && |
2348 // Only store fast element maps in ascending generality. | 2374 IsFastElementsKind(from_kind); |
2349 IsTransitionableFastElementsKind(from_kind) && | 2375 |
2350 IsFastElementsKind(to_kind) && | 2376 // Only store fast element maps in ascending generality. |
2351 IsMoreGeneralElementsKindTransition(from_kind, to_kind); | 2377 if (IsFastElementsKind(to_kind)) { |
| 2378 allow_store_transition &= |
| 2379 IsTransitionableFastElementsKind(from_kind) && |
| 2380 IsMoreGeneralElementsKindTransition(from_kind, to_kind); |
| 2381 } |
2352 | 2382 |
2353 if (!allow_store_transition) { | 2383 if (!allow_store_transition) { |
2354 // Create a new free-floating map only if we are not allowed to store it. | 2384 // Create a new free-floating map only if we are not allowed to store it. |
2355 Map* new_map = NULL; | 2385 Map* new_map = NULL; |
2356 MaybeObject* maybe_new_map = | 2386 MaybeObject* maybe_new_map = |
2357 start_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); | 2387 start_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED); |
2358 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2388 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
2359 new_map->set_elements_kind(to_kind); | 2389 new_map->set_elements_kind(to_kind); |
2360 return new_map; | 2390 return new_map; |
2361 } | 2391 } |
(...skipping 2694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5056 case NULL_DESCRIPTOR: | 5086 case NULL_DESCRIPTOR: |
5057 // We definitely have no map transition. | 5087 // We definitely have no map transition. |
5058 raw_index += 2; | 5088 raw_index += 2; |
5059 ++index; | 5089 ++index; |
5060 break; | 5090 break; |
5061 } | 5091 } |
5062 } | 5092 } |
5063 if (index == descriptor_array_->number_of_descriptors()) { | 5093 if (index == descriptor_array_->number_of_descriptors()) { |
5064 Map* elements_transition = descriptor_array_->elements_transition_map(); | 5094 Map* elements_transition = descriptor_array_->elements_transition_map(); |
5065 if (elements_transition != NULL) { | 5095 if (elements_transition != NULL) { |
5066 *DescriptorArrayHeader() = Smi::FromInt(index + 1); | 5096 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); |
5067 return elements_transition; | 5097 return elements_transition; |
5068 } | 5098 } |
5069 } | 5099 } |
5070 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); | 5100 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); |
5071 return NULL; | 5101 return NULL; |
5072 } | 5102 } |
5073 | 5103 |
5074 private: | 5104 private: |
5075 Object** DescriptorArrayHeader() { | 5105 Object** DescriptorArrayHeader() { |
5076 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); | 5106 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5758 return true; | 5788 return true; |
5759 } | 5789 } |
5760 #endif | 5790 #endif |
5761 | 5791 |
5762 | 5792 |
5763 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, | 5793 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, |
5764 SharedMode shared_mode) { | 5794 SharedMode shared_mode) { |
5765 Heap* heap = Isolate::Current()->heap(); | 5795 Heap* heap = Isolate::Current()->heap(); |
5766 // Do not use DescriptorArray::cast on incomplete object. | 5796 // Do not use DescriptorArray::cast on incomplete object. |
5767 FixedArray* result; | 5797 FixedArray* result; |
5768 if (number_of_descriptors == 0) { | 5798 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { |
5769 if (shared_mode == MAY_BE_SHARED) { | 5799 return heap->empty_descriptor_array(); |
5770 return heap->empty_descriptor_array(); | |
5771 } | |
5772 { MaybeObject* maybe_array = | |
5773 heap->AllocateFixedArray(kTransitionsIndex + 1); | |
5774 if (!maybe_array->To(&result)) return maybe_array; | |
5775 } | |
5776 } else { | |
5777 // Allocate the array of keys. | |
5778 { MaybeObject* maybe_array = | |
5779 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | |
5780 if (!maybe_array->To(&result)) return maybe_array; | |
5781 } | |
5782 result->set(kEnumerationIndexIndex, | |
5783 Smi::FromInt(PropertyDetails::kInitialIndex)); | |
5784 } | 5800 } |
| 5801 // Allocate the array of keys. |
| 5802 { MaybeObject* maybe_array = |
| 5803 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
| 5804 if (!maybe_array->To(&result)) return maybe_array; |
| 5805 } |
| 5806 |
5785 result->set(kBitField3StorageIndex, Smi::FromInt(0)); | 5807 result->set(kBitField3StorageIndex, Smi::FromInt(0)); |
| 5808 result->set(kEnumerationIndexIndex, |
| 5809 Smi::FromInt(PropertyDetails::kInitialIndex)); |
5786 result->set(kTransitionsIndex, Smi::FromInt(0)); | 5810 result->set(kTransitionsIndex, Smi::FromInt(0)); |
5787 return result; | 5811 return result; |
5788 } | 5812 } |
5789 | 5813 |
5790 | 5814 |
5791 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 5815 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
5792 FixedArray* new_cache, | 5816 FixedArray* new_cache, |
5793 Object* new_index_cache) { | 5817 Object* new_index_cache) { |
5794 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 5818 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
5795 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); | 5819 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
(...skipping 1711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7507 if (code->kind() != Code::FUNCTION) return true; | 7531 if (code->kind() != Code::FUNCTION) return true; |
7508 return code->optimizable(); | 7532 return code->optimizable(); |
7509 } | 7533 } |
7510 | 7534 |
7511 | 7535 |
7512 MaybeObject* JSObject::OptimizeAsPrototype() { | 7536 MaybeObject* JSObject::OptimizeAsPrototype() { |
7513 if (IsGlobalObject()) return this; | 7537 if (IsGlobalObject()) return this; |
7514 | 7538 |
7515 // Make sure prototypes are fast objects and their maps have the bit set | 7539 // Make sure prototypes are fast objects and their maps have the bit set |
7516 // so they remain fast. | 7540 // so they remain fast. |
7517 Map* proto_map = map(); | |
7518 if (!HasFastProperties()) { | 7541 if (!HasFastProperties()) { |
7519 MaybeObject* new_proto = TransformToFastProperties(0); | 7542 MaybeObject* new_proto = TransformToFastProperties(0); |
7520 if (new_proto->IsFailure()) return new_proto; | 7543 if (new_proto->IsFailure()) return new_proto; |
7521 ASSERT(new_proto == this); | 7544 ASSERT(new_proto == this); |
7522 proto_map = map(); | |
7523 } | 7545 } |
7524 return this; | 7546 return this; |
7525 } | 7547 } |
7526 | 7548 |
7527 | 7549 |
7528 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { | 7550 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
7529 ASSERT(value->IsJSReceiver()); | 7551 ASSERT(value->IsJSReceiver()); |
7530 Heap* heap = GetHeap(); | 7552 Heap* heap = GetHeap(); |
7531 | 7553 |
7532 // First some logic for the map of the prototype to make sure it is in fast | 7554 // First some logic for the map of the prototype to make sure it is in fast |
(...skipping 5650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13183 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13205 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13184 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13206 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13185 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13207 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13186 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13208 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13187 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13209 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13188 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13210 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13189 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13211 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13190 } | 13212 } |
13191 | 13213 |
13192 } } // namespace v8::internal | 13214 } } // namespace v8::internal |
OLD | NEW |