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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 #include "vm-state-inl.h" | 49 #include "vm-state-inl.h" |
50 | 50 |
51 #ifdef ENABLE_DISASSEMBLER | 51 #ifdef ENABLE_DISASSEMBLER |
52 #include "disasm.h" | 52 #include "disasm.h" |
53 #include "disassembler.h" | 53 #include "disassembler.h" |
54 #endif | 54 #endif |
55 | 55 |
56 namespace v8 { | 56 namespace v8 { |
57 namespace internal { | 57 namespace internal { |
58 | 58 |
59 void PrintElementsKind(FILE* out, ElementsKind kind) { | |
60 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); | |
61 PrintF(out, "%s", accessor->name()); | |
62 } | |
63 | |
64 | 59 |
65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 60 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
66 Object* value) { | 61 Object* value) { |
67 Object* result; | 62 Object* result; |
68 { MaybeObject* maybe_result = | 63 { MaybeObject* maybe_result = |
69 constructor->GetHeap()->AllocateJSObject(constructor); | 64 constructor->GetHeap()->AllocateJSObject(constructor); |
70 if (!maybe_result->ToObject(&result)) return maybe_result; | 65 if (!maybe_result->ToObject(&result)) return maybe_result; |
71 } | 66 } |
72 JSValue::cast(result)->set_value(value); | 67 JSValue::cast(result)->set_value(value); |
73 return result; | 68 return result; |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 bool JSObject::IsDirty() { | 531 bool JSObject::IsDirty() { |
537 Object* cons_obj = map()->constructor(); | 532 Object* cons_obj = map()->constructor(); |
538 if (!cons_obj->IsJSFunction()) | 533 if (!cons_obj->IsJSFunction()) |
539 return true; | 534 return true; |
540 JSFunction* fun = JSFunction::cast(cons_obj); | 535 JSFunction* fun = JSFunction::cast(cons_obj); |
541 if (!fun->shared()->IsApiFunction()) | 536 if (!fun->shared()->IsApiFunction()) |
542 return true; | 537 return true; |
543 // If the object is fully fast case and has the same map it was | 538 // If the object is fully fast case and has the same map it was |
544 // created with then no changes can have been made to it. | 539 // created with then no changes can have been made to it. |
545 return map() != fun->initial_map() | 540 return map() != fun->initial_map() |
546 || !HasFastElements() | 541 || !HasFastObjectElements() |
547 || !HasFastProperties(); | 542 || !HasFastProperties(); |
548 } | 543 } |
549 | 544 |
550 | 545 |
551 Handle<Object> Object::GetProperty(Handle<Object> object, | 546 Handle<Object> Object::GetProperty(Handle<Object> object, |
552 Handle<Object> receiver, | 547 Handle<Object> receiver, |
553 LookupResult* result, | 548 LookupResult* result, |
554 Handle<String> key, | 549 Handle<String> key, |
555 PropertyAttributes* attributes) { | 550 PropertyAttributes* attributes) { |
556 Isolate* isolate = object->IsHeapObject() | 551 Isolate* isolate = object->IsHeapObject() |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 } | 1055 } |
1061 accumulator->Put('>'); | 1056 accumulator->Put('>'); |
1062 } | 1057 } |
1063 return; | 1058 return; |
1064 } | 1059 } |
1065 | 1060 |
1066 | 1061 |
1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) { | 1062 void JSObject::JSObjectShortPrint(StringStream* accumulator) { |
1068 switch (map()->instance_type()) { | 1063 switch (map()->instance_type()) { |
1069 case JS_ARRAY_TYPE: { | 1064 case JS_ARRAY_TYPE: { |
1070 double length = JSArray::cast(this)->length()->Number(); | 1065 double length = JSArray::cast(this)->length()->IsUndefined() |
| 1066 ? 0 |
| 1067 : JSArray::cast(this)->length()->Number(); |
1071 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); | 1068 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); |
1072 break; | 1069 break; |
1073 } | 1070 } |
1074 case JS_WEAK_MAP_TYPE: { | 1071 case JS_WEAK_MAP_TYPE: { |
1075 accumulator->Add("<JS WeakMap>"); | 1072 accumulator->Add("<JS WeakMap>"); |
1076 break; | 1073 break; |
1077 } | 1074 } |
1078 case JS_REGEXP_TYPE: { | 1075 case JS_REGEXP_TYPE: { |
1079 accumulator->Add("<JS RegExp>"); | 1076 accumulator->Add("<JS RegExp>"); |
1080 break; | 1077 break; |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2195 | 2192 |
2196 | 2193 |
2197 template <class T> | 2194 template <class T> |
2198 static Handle<T> MaybeNull(T* p) { | 2195 static Handle<T> MaybeNull(T* p) { |
2199 if (p == NULL) return Handle<T>::null(); | 2196 if (p == NULL) return Handle<T>::null(); |
2200 return Handle<T>(p); | 2197 return Handle<T>(p); |
2201 } | 2198 } |
2202 | 2199 |
2203 | 2200 |
2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { | 2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
2205 ElementsKind elms_kind = elements_kind(); | 2202 ElementsKind kind = elements_kind(); |
2206 if (elms_kind == FAST_DOUBLE_ELEMENTS) { | 2203 Handle<Map> transitioned_map = Handle<Map>::null(); |
2207 bool dummy = true; | 2204 Handle<Map> current_map(this); |
2208 Handle<Map> fast_map = | 2205 bool packed = IsFastPackedElementsKind(kind); |
2209 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); | 2206 if (IsTransitionableFastElementsKind(kind)) { |
2210 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { | 2207 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { |
2211 return fast_map; | 2208 kind = GetNextMoreGeneralFastElementsKind(kind, false); |
| 2209 bool dummy = true; |
| 2210 Handle<Map> maybe_transitioned_map = |
| 2211 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy)); |
| 2212 if (maybe_transitioned_map.is_null()) break; |
| 2213 if (ContainsMap(candidates, maybe_transitioned_map) && |
| 2214 (packed || !IsFastPackedElementsKind(kind))) { |
| 2215 transitioned_map = maybe_transitioned_map; |
| 2216 if (!IsFastPackedElementsKind(kind)) packed = false; |
| 2217 } |
| 2218 current_map = maybe_transitioned_map; |
2212 } | 2219 } |
2213 return Handle<Map>::null(); | |
2214 } | 2220 } |
2215 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { | 2221 return transitioned_map; |
2216 bool dummy = true; | |
2217 Handle<Map> double_map = | |
2218 MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy)); | |
2219 // In the current implementation, if the DOUBLE map doesn't exist, the | |
2220 // FAST map can't exist either. | |
2221 if (double_map.is_null()) return Handle<Map>::null(); | |
2222 Handle<Map> fast_map = | |
2223 MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS, | |
2224 &dummy)); | |
2225 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { | |
2226 return fast_map; | |
2227 } | |
2228 if (ContainsMap(candidates, double_map)) return double_map; | |
2229 } | |
2230 return Handle<Map>::null(); | |
2231 } | 2222 } |
2232 | 2223 |
| 2224 |
2233 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | 2225 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
2234 ElementsKind elements_kind) { | 2226 ElementsKind elements_kind) { |
2235 if (descriptor_contents->IsMap()) { | 2227 if (descriptor_contents->IsMap()) { |
2236 Map* map = Map::cast(descriptor_contents); | 2228 Map* map = Map::cast(descriptor_contents); |
2237 if (map->elements_kind() == elements_kind) { | 2229 if (map->elements_kind() == elements_kind) { |
2238 return map; | 2230 return map; |
2239 } | 2231 } |
2240 return NULL; | 2232 return NULL; |
2241 } | 2233 } |
2242 | 2234 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2331 } else { | 2323 } else { |
2332 if (safe_to_add_transition != NULL) { | 2324 if (safe_to_add_transition != NULL) { |
2333 *safe_to_add_transition = false; | 2325 *safe_to_add_transition = false; |
2334 } | 2326 } |
2335 } | 2327 } |
2336 } | 2328 } |
2337 return NULL; | 2329 return NULL; |
2338 } | 2330 } |
2339 | 2331 |
2340 | 2332 |
2341 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, | 2333 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, |
2342 bool* safe_to_add_transition) { | 2334 bool* safe_to_add_transition) { |
2343 // Special case: indirect SMI->FAST transition (cf. comment in | 2335 ElementsKind from_kind = elements_kind(); |
2344 // AddElementsTransition()). | 2336 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
2345 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2337 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
2346 elements_kind == FAST_ELEMENTS) { | 2338 if (safe_to_add_transition) *safe_to_add_transition = false; |
2347 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, | 2339 return NULL; |
2348 safe_to_add_transition); | 2340 } |
2349 if (double_map == NULL) return double_map; | 2341 ElementsKind transitioned_from_kind = |
2350 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, | 2342 GetNextMoreGeneralFastElementsKind(from_kind, false); |
| 2343 |
| 2344 |
| 2345 // If the transition is a single step in the transition sequence, fall |
| 2346 // through to looking it up and returning it. If it requires several steps, |
| 2347 // divide and conquer. |
| 2348 if (transitioned_from_kind != to_kind) { |
| 2349 // If the transition is several steps in the lattice, divide and conquer. |
| 2350 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind, |
| 2351 safe_to_add_transition); |
| 2352 if (from_map == NULL) return NULL; |
| 2353 return from_map->LookupElementsTransitionMap(to_kind, |
2351 safe_to_add_transition); | 2354 safe_to_add_transition); |
| 2355 } |
2352 } | 2356 } |
2353 Object* descriptor_contents = GetDescriptorContents( | 2357 Object* descriptor_contents = GetDescriptorContents( |
2354 elements_transition_sentinel_name(), safe_to_add_transition); | 2358 elements_transition_sentinel_name(), safe_to_add_transition); |
2355 if (descriptor_contents != NULL) { | 2359 if (descriptor_contents != NULL) { |
2356 Map* maybe_transition_map = | 2360 Map* maybe_transition_map = |
2357 GetElementsTransitionMapFromDescriptor(descriptor_contents, | 2361 GetElementsTransitionMapFromDescriptor(descriptor_contents, |
2358 elements_kind); | 2362 to_kind); |
2359 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); | 2363 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); |
2360 return maybe_transition_map; | 2364 return maybe_transition_map; |
2361 } | 2365 } |
2362 return NULL; | 2366 return NULL; |
2363 } | 2367 } |
2364 | 2368 |
2365 | 2369 |
2366 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, | 2370 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, |
2367 Map* transitioned_map) { | 2371 Map* transitioned_map) { |
2368 // The map transition graph should be a tree, therefore the transition | 2372 ElementsKind from_kind = elements_kind(); |
2369 // from SMI to FAST elements is not done directly, but by going through | 2373 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
2370 // DOUBLE elements first. | 2374 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); |
2371 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2375 ElementsKind transitioned_from_kind = |
2372 elements_kind == FAST_ELEMENTS) { | 2376 GetNextMoreGeneralFastElementsKind(from_kind, false); |
2373 bool safe_to_add = true; | 2377 // The map transitions graph should be a tree, therefore transitions to |
2374 Map* double_map = this->LookupElementsTransitionMap( | 2378 // ElementsKind that are not adjacent in the ElementsKind sequence are not |
2375 FAST_DOUBLE_ELEMENTS, &safe_to_add); | 2379 // done directly, but instead by going through intermediate ElementsKinds |
2376 // This method is only called when safe_to_add_transition has been found | 2380 // first. |
2377 // to be true earlier. | 2381 if (to_kind != transitioned_from_kind) { |
2378 ASSERT(safe_to_add); | 2382 bool safe_to_add = true; |
| 2383 Map* intermediate_map = LookupElementsTransitionMap( |
| 2384 transitioned_from_kind, &safe_to_add); |
| 2385 // This method is only called when safe_to_add has been found to be true |
| 2386 // earlier. |
| 2387 ASSERT(safe_to_add); |
2379 | 2388 |
2380 if (double_map == NULL) { | 2389 if (intermediate_map == NULL) { |
2381 MaybeObject* maybe_map = this->CopyDropTransitions(); | 2390 MaybeObject* maybe_map = CopyDropTransitions(); |
2382 if (!maybe_map->To(&double_map)) return maybe_map; | 2391 if (!maybe_map->To(&intermediate_map)) return maybe_map; |
2383 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); | 2392 intermediate_map->set_elements_kind(transitioned_from_kind); |
2384 MaybeObject* maybe_double_transition = this->AddElementsTransition( | 2393 MaybeObject* maybe_transition = AddElementsTransition( |
2385 FAST_DOUBLE_ELEMENTS, double_map); | 2394 transitioned_from_kind, intermediate_map); |
2386 if (maybe_double_transition->IsFailure()) return maybe_double_transition; | 2395 if (maybe_transition->IsFailure()) return maybe_transition; |
| 2396 } |
| 2397 return intermediate_map->AddElementsTransition(to_kind, transitioned_map); |
2387 } | 2398 } |
2388 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map); | |
2389 } | 2399 } |
2390 | 2400 |
2391 bool safe_to_add_transition = true; | 2401 bool safe_to_add_transition = true; |
2392 Object* descriptor_contents = GetDescriptorContents( | 2402 Object* descriptor_contents = GetDescriptorContents( |
2393 elements_transition_sentinel_name(), &safe_to_add_transition); | 2403 elements_transition_sentinel_name(), &safe_to_add_transition); |
2394 // This method is only called when safe_to_add_transition has been found | 2404 // This method is only called when safe_to_add_transition has been found |
2395 // to be true earlier. | 2405 // to be true earlier. |
2396 ASSERT(safe_to_add_transition); | 2406 ASSERT(safe_to_add_transition); |
2397 MaybeObject* maybe_new_contents = | 2407 MaybeObject* maybe_new_contents = |
2398 AddElementsTransitionMapToDescriptor(descriptor_contents, | 2408 AddElementsTransitionMapToDescriptor(descriptor_contents, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2430 ElementsKind from_kind = current_map->elements_kind(); | 2440 ElementsKind from_kind = current_map->elements_kind(); |
2431 | 2441 |
2432 if (from_kind == to_kind) return current_map; | 2442 if (from_kind == to_kind) return current_map; |
2433 | 2443 |
2434 // Only objects with FastProperties can have DescriptorArrays and can track | 2444 // Only objects with FastProperties can have DescriptorArrays and can track |
2435 // element-related maps. Also don't add descriptors to maps that are shared. | 2445 // element-related maps. Also don't add descriptors to maps that are shared. |
2436 bool safe_to_add_transition = HasFastProperties() && | 2446 bool safe_to_add_transition = HasFastProperties() && |
2437 !current_map->IsUndefined() && | 2447 !current_map->IsUndefined() && |
2438 !current_map->is_shared(); | 2448 !current_map->is_shared(); |
2439 | 2449 |
2440 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects | 2450 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects |
2441 // with elements that switch back and forth between dictionary and fast | 2451 // with elements that switch back and forth between dictionary and fast |
2442 // element mode. | 2452 // element modes. |
2443 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 2453 if (from_kind == DICTIONARY_ELEMENTS && |
| 2454 IsFastElementsKind(to_kind)) { |
2444 safe_to_add_transition = false; | 2455 safe_to_add_transition = false; |
2445 } | 2456 } |
2446 | 2457 |
2447 if (safe_to_add_transition) { | 2458 if (safe_to_add_transition) { |
2448 // It's only safe to manipulate the descriptor array if it would be | 2459 // It's only safe to manipulate the descriptor array if it would be |
2449 // safe to add a transition. | 2460 // safe to add a transition. |
2450 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( | 2461 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( |
2451 to_kind, &safe_to_add_transition); | 2462 to_kind, &safe_to_add_transition); |
2452 if (maybe_transition_map != NULL) { | 2463 if (maybe_transition_map != NULL) { |
2453 return maybe_transition_map; | 2464 return maybe_transition_map; |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3469 // Find the backing store. | 3480 // Find the backing store. |
3470 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 3481 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
3471 Map* old_map = array->map(); | 3482 Map* old_map = array->map(); |
3472 bool is_arguments = | 3483 bool is_arguments = |
3473 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 3484 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
3474 if (is_arguments) { | 3485 if (is_arguments) { |
3475 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 3486 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
3476 } | 3487 } |
3477 if (array->IsDictionary()) return array; | 3488 if (array->IsDictionary()) return array; |
3478 | 3489 |
3479 ASSERT(HasFastElements() || | 3490 ASSERT(HasFastSmiOrObjectElements() || |
3480 HasFastSmiOnlyElements() || | |
3481 HasFastDoubleElements() || | 3491 HasFastDoubleElements() || |
3482 HasFastArgumentsElements()); | 3492 HasFastArgumentsElements()); |
3483 // Compute the effective length and allocate a new backing store. | 3493 // Compute the effective length and allocate a new backing store. |
3484 int length = IsJSArray() | 3494 int length = IsJSArray() |
3485 ? Smi::cast(JSArray::cast(this)->length())->value() | 3495 ? Smi::cast(JSArray::cast(this)->length())->value() |
3486 : array->length(); | 3496 : array->length(); |
3487 int old_capacity = 0; | 3497 int old_capacity = 0; |
3488 int used_elements = 0; | 3498 int used_elements = 0; |
3489 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 3499 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
3490 SeededNumberDictionary* dictionary = NULL; | 3500 SeededNumberDictionary* dictionary = NULL; |
(...skipping 14 matching lines...) Expand all Loading... |
3505 } else { | 3515 } else { |
3506 // Objects must be allocated in the old object space, since the | 3516 // Objects must be allocated in the old object space, since the |
3507 // overall number of HeapNumbers needed for the conversion might | 3517 // overall number of HeapNumbers needed for the conversion might |
3508 // exceed the capacity of new space, and we would fail repeatedly | 3518 // exceed the capacity of new space, and we would fail repeatedly |
3509 // trying to convert the FixedDoubleArray. | 3519 // trying to convert the FixedDoubleArray. |
3510 MaybeObject* maybe_value_object = | 3520 MaybeObject* maybe_value_object = |
3511 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 3521 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
3512 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 3522 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
3513 } | 3523 } |
3514 } else { | 3524 } else { |
3515 ASSERT(old_map->has_fast_elements() || | 3525 ASSERT(old_map->has_fast_smi_or_object_elements()); |
3516 old_map->has_fast_smi_only_elements()); | |
3517 value = FixedArray::cast(array)->get(i); | 3526 value = FixedArray::cast(array)->get(i); |
3518 } | 3527 } |
3519 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 3528 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
3520 if (!value->IsTheHole()) { | 3529 if (!value->IsTheHole()) { |
3521 Object* result; | 3530 Object* result; |
3522 MaybeObject* maybe_result = | 3531 MaybeObject* maybe_result = |
3523 dictionary->AddNumberEntry(i, value, details); | 3532 dictionary->AddNumberEntry(i, value, details); |
3524 if (!maybe_result->ToObject(&result)) return maybe_result; | 3533 if (!maybe_result->ToObject(&result)) return maybe_result; |
3525 dictionary = SeededNumberDictionary::cast(result); | 3534 dictionary = SeededNumberDictionary::cast(result); |
3526 } | 3535 } |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3993 if (IsJSProxy()) { | 4002 if (IsJSProxy()) { |
3994 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); | 4003 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
3995 } | 4004 } |
3996 return JSObject::cast(this)->DeleteProperty(name, mode); | 4005 return JSObject::cast(this)->DeleteProperty(name, mode); |
3997 } | 4006 } |
3998 | 4007 |
3999 | 4008 |
4000 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 4009 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
4001 ElementsKind kind, | 4010 ElementsKind kind, |
4002 Object* object) { | 4011 Object* object) { |
4003 ASSERT(kind == FAST_ELEMENTS || | 4012 ASSERT(IsFastObjectElementsKind(kind) || |
4004 kind == DICTIONARY_ELEMENTS); | 4013 kind == DICTIONARY_ELEMENTS); |
4005 if (kind == FAST_ELEMENTS) { | 4014 if (IsFastObjectElementsKind(kind)) { |
4006 int length = IsJSArray() | 4015 int length = IsJSArray() |
4007 ? Smi::cast(JSArray::cast(this)->length())->value() | 4016 ? Smi::cast(JSArray::cast(this)->length())->value() |
4008 : elements->length(); | 4017 : elements->length(); |
4009 for (int i = 0; i < length; ++i) { | 4018 for (int i = 0; i < length; ++i) { |
4010 Object* element = elements->get(i); | 4019 Object* element = elements->get(i); |
4011 if (!element->IsTheHole() && element == object) return true; | 4020 if (!element->IsTheHole() && element == object) return true; |
4012 } | 4021 } |
4013 } else { | 4022 } else { |
4014 Object* key = | 4023 Object* key = |
4015 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); | 4024 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4047 case EXTERNAL_PIXEL_ELEMENTS: | 4056 case EXTERNAL_PIXEL_ELEMENTS: |
4048 case EXTERNAL_BYTE_ELEMENTS: | 4057 case EXTERNAL_BYTE_ELEMENTS: |
4049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4058 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4050 case EXTERNAL_SHORT_ELEMENTS: | 4059 case EXTERNAL_SHORT_ELEMENTS: |
4051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4060 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4052 case EXTERNAL_INT_ELEMENTS: | 4061 case EXTERNAL_INT_ELEMENTS: |
4053 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4062 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4054 case EXTERNAL_FLOAT_ELEMENTS: | 4063 case EXTERNAL_FLOAT_ELEMENTS: |
4055 case EXTERNAL_DOUBLE_ELEMENTS: | 4064 case EXTERNAL_DOUBLE_ELEMENTS: |
4056 case FAST_DOUBLE_ELEMENTS: | 4065 case FAST_DOUBLE_ELEMENTS: |
| 4066 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4057 // Raw pixels and external arrays do not reference other | 4067 // Raw pixels and external arrays do not reference other |
4058 // objects. | 4068 // objects. |
4059 break; | 4069 break; |
4060 case FAST_SMI_ONLY_ELEMENTS: | 4070 case FAST_SMI_ELEMENTS: |
| 4071 case FAST_HOLEY_SMI_ELEMENTS: |
4061 break; | 4072 break; |
4062 case FAST_ELEMENTS: | 4073 case FAST_ELEMENTS: |
| 4074 case FAST_HOLEY_ELEMENTS: |
4063 case DICTIONARY_ELEMENTS: { | 4075 case DICTIONARY_ELEMENTS: { |
4064 FixedArray* elements = FixedArray::cast(this->elements()); | 4076 FixedArray* elements = FixedArray::cast(this->elements()); |
4065 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 4077 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
4066 break; | 4078 break; |
4067 } | 4079 } |
4068 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 4080 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
4069 FixedArray* parameter_map = FixedArray::cast(elements()); | 4081 FixedArray* parameter_map = FixedArray::cast(elements()); |
4070 // Check the mapped parameters. | 4082 // Check the mapped parameters. |
4071 int length = parameter_map->length(); | 4083 int length = parameter_map->length(); |
4072 for (int i = 2; i < length; ++i) { | 4084 for (int i = 2; i < length; ++i) { |
4073 Object* value = parameter_map->get(i); | 4085 Object* value = parameter_map->get(i); |
4074 if (!value->IsTheHole() && value == obj) return true; | 4086 if (!value->IsTheHole() && value == obj) return true; |
4075 } | 4087 } |
4076 // Check the arguments. | 4088 // Check the arguments. |
4077 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 4089 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
4078 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; | 4090 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
| 4091 FAST_HOLEY_ELEMENTS; |
4079 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 4092 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
4080 break; | 4093 break; |
4081 } | 4094 } |
4082 } | 4095 } |
4083 | 4096 |
4084 // For functions check the context. | 4097 // For functions check the context. |
4085 if (IsJSFunction()) { | 4098 if (IsJSFunction()) { |
4086 // Get the constructor function for arguments array. | 4099 // Get the constructor function for arguments array. |
4087 JSObject* arguments_boilerplate = | 4100 JSObject* arguments_boilerplate = |
4088 heap->isolate()->context()->global_context()-> | 4101 heap->isolate()->context()->global_context()-> |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4302 for (Object* current = this; | 4315 for (Object* current = this; |
4303 current != heap->null_value(); | 4316 current != heap->null_value(); |
4304 current = JSObject::cast(current)->GetPrototype()) { | 4317 current = JSObject::cast(current)->GetPrototype()) { |
4305 JSReceiver::cast(current)->LocalLookup(name, result); | 4318 JSReceiver::cast(current)->LocalLookup(name, result); |
4306 if (result->IsProperty()) return; | 4319 if (result->IsProperty()) return; |
4307 } | 4320 } |
4308 result->NotFound(); | 4321 result->NotFound(); |
4309 } | 4322 } |
4310 | 4323 |
4311 | 4324 |
4312 // Search object and it's prototype chain for callback properties. | 4325 // Search object and its prototype chain for callback properties. |
4313 void JSObject::LookupCallback(String* name, LookupResult* result) { | 4326 void JSObject::LookupCallback(String* name, LookupResult* result) { |
4314 Heap* heap = GetHeap(); | 4327 Heap* heap = GetHeap(); |
4315 for (Object* current = this; | 4328 for (Object* current = this; |
4316 current != heap->null_value() && current->IsJSObject(); | 4329 current != heap->null_value() && current->IsJSObject(); |
4317 current = JSObject::cast(current)->GetPrototype()) { | 4330 current = JSObject::cast(current)->GetPrototype()) { |
4318 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4331 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
4319 if (result->IsFound() && result->type() == CALLBACKS) return; | 4332 if (result->IsFound() && result->type() == CALLBACKS) return; |
4320 } | 4333 } |
4321 result->NotFound(); | 4334 result->NotFound(); |
4322 } | 4335 } |
(...skipping 23 matching lines...) Expand all Loading... |
4346 } | 4359 } |
4347 return false; | 4360 return false; |
4348 } | 4361 } |
4349 | 4362 |
4350 | 4363 |
4351 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 4364 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, |
4352 Object* getter, | 4365 Object* getter, |
4353 Object* setter, | 4366 Object* setter, |
4354 PropertyAttributes attributes) { | 4367 PropertyAttributes attributes) { |
4355 switch (GetElementsKind()) { | 4368 switch (GetElementsKind()) { |
4356 case FAST_SMI_ONLY_ELEMENTS: | 4369 case FAST_SMI_ELEMENTS: |
4357 case FAST_ELEMENTS: | 4370 case FAST_ELEMENTS: |
4358 case FAST_DOUBLE_ELEMENTS: | 4371 case FAST_DOUBLE_ELEMENTS: |
| 4372 case FAST_HOLEY_SMI_ELEMENTS: |
| 4373 case FAST_HOLEY_ELEMENTS: |
| 4374 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4359 break; | 4375 break; |
4360 case EXTERNAL_PIXEL_ELEMENTS: | 4376 case EXTERNAL_PIXEL_ELEMENTS: |
4361 case EXTERNAL_BYTE_ELEMENTS: | 4377 case EXTERNAL_BYTE_ELEMENTS: |
4362 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4378 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4363 case EXTERNAL_SHORT_ELEMENTS: | 4379 case EXTERNAL_SHORT_ELEMENTS: |
4364 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4380 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4365 case EXTERNAL_INT_ELEMENTS: | 4381 case EXTERNAL_INT_ELEMENTS: |
4366 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4382 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4367 case EXTERNAL_FLOAT_ELEMENTS: | 4383 case EXTERNAL_FLOAT_ELEMENTS: |
4368 case EXTERNAL_DOUBLE_ELEMENTS: | 4384 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4465 accessors->SetComponents(getter, setter); | 4481 accessors->SetComponents(getter, setter); |
4466 return SetPropertyCallback(name, accessors, attributes); | 4482 return SetPropertyCallback(name, accessors, attributes); |
4467 } | 4483 } |
4468 | 4484 |
4469 | 4485 |
4470 bool JSObject::CanSetCallback(String* name) { | 4486 bool JSObject::CanSetCallback(String* name) { |
4471 ASSERT(!IsAccessCheckNeeded() || | 4487 ASSERT(!IsAccessCheckNeeded() || |
4472 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4488 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
4473 | 4489 |
4474 // Check if there is an API defined callback object which prohibits | 4490 // Check if there is an API defined callback object which prohibits |
4475 // callback overwriting in this object or it's prototype chain. | 4491 // callback overwriting in this object or its prototype chain. |
4476 // This mechanism is needed for instance in a browser setting, where | 4492 // This mechanism is needed for instance in a browser setting, where |
4477 // certain accessors such as window.location should not be allowed | 4493 // certain accessors such as window.location should not be allowed |
4478 // to be overwritten because allowing overwriting could potentially | 4494 // to be overwritten because allowing overwriting could potentially |
4479 // cause security problems. | 4495 // cause security problems. |
4480 LookupResult callback_result(GetIsolate()); | 4496 LookupResult callback_result(GetIsolate()); |
4481 LookupCallback(name, &callback_result); | 4497 LookupCallback(name, &callback_result); |
4482 if (callback_result.IsProperty()) { | 4498 if (callback_result.IsProperty()) { |
4483 Object* obj = callback_result.GetCallbackObject(); | 4499 Object* obj = callback_result.GetCallbackObject(); |
4484 if (obj->IsAccessorInfo() && | 4500 if (obj->IsAccessorInfo() && |
4485 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4501 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4789 } | 4805 } |
4790 | 4806 |
4791 uint32_t index = 0; | 4807 uint32_t index = 0; |
4792 bool is_element = name->AsArrayIndex(&index); | 4808 bool is_element = name->AsArrayIndex(&index); |
4793 | 4809 |
4794 if (is_element) { | 4810 if (is_element) { |
4795 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4811 if (IsJSArray()) return isolate->heap()->undefined_value(); |
4796 | 4812 |
4797 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4813 // Accessors overwrite previous callbacks (cf. with getters/setters). |
4798 switch (GetElementsKind()) { | 4814 switch (GetElementsKind()) { |
4799 case FAST_SMI_ONLY_ELEMENTS: | 4815 case FAST_SMI_ELEMENTS: |
4800 case FAST_ELEMENTS: | 4816 case FAST_ELEMENTS: |
4801 case FAST_DOUBLE_ELEMENTS: | 4817 case FAST_DOUBLE_ELEMENTS: |
| 4818 case FAST_HOLEY_SMI_ELEMENTS: |
| 4819 case FAST_HOLEY_ELEMENTS: |
| 4820 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4802 break; | 4821 break; |
4803 case EXTERNAL_PIXEL_ELEMENTS: | 4822 case EXTERNAL_PIXEL_ELEMENTS: |
4804 case EXTERNAL_BYTE_ELEMENTS: | 4823 case EXTERNAL_BYTE_ELEMENTS: |
4805 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4824 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4806 case EXTERNAL_SHORT_ELEMENTS: | 4825 case EXTERNAL_SHORT_ELEMENTS: |
4807 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4826 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4808 case EXTERNAL_INT_ELEMENTS: | 4827 case EXTERNAL_INT_ELEMENTS: |
4809 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4828 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4810 case EXTERNAL_FLOAT_ELEMENTS: | 4829 case EXTERNAL_FLOAT_ELEMENTS: |
4811 case EXTERNAL_DOUBLE_ELEMENTS: | 4830 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8580 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 8599 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
8581 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8600 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
8582 PrintF(out, "\n"); | 8601 PrintF(out, "\n"); |
8583 } | 8602 } |
8584 #endif // ENABLE_DISASSEMBLER | 8603 #endif // ENABLE_DISASSEMBLER |
8585 | 8604 |
8586 | 8605 |
8587 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8606 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
8588 int capacity, | 8607 int capacity, |
8589 int length, | 8608 int length, |
8590 SetFastElementsCapacityMode set_capacity_mode) { | 8609 SetFastElementsCapacitySmiMode smi_mode) { |
8591 Heap* heap = GetHeap(); | 8610 Heap* heap = GetHeap(); |
8592 // We should never end in here with a pixel or external array. | 8611 // We should never end in here with a pixel or external array. |
8593 ASSERT(!HasExternalArrayElements()); | 8612 ASSERT(!HasExternalArrayElements()); |
8594 | 8613 |
8595 // Allocate a new fast elements backing store. | 8614 // Allocate a new fast elements backing store. |
8596 FixedArray* new_elements; | 8615 FixedArray* new_elements; |
8597 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 8616 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
8598 if (!maybe->To(&new_elements)) return maybe; | 8617 if (!maybe->To(&new_elements)) return maybe; |
8599 } | 8618 } |
8600 | 8619 |
8601 // Find the new map to use for this object if there is a map change. | 8620 ElementsKind elements_kind = GetElementsKind(); |
8602 Map* new_map = NULL; | 8621 ElementsKind new_elements_kind; |
8603 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 8622 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
8604 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces | 8623 // or if it's allowed and the old elements array contained only SMIs. |
8605 // it, or if it's allowed and the old elements array contained only SMIs. | 8624 bool has_fast_smi_elements = |
8606 bool has_fast_smi_only_elements = | 8625 (smi_mode == kForceSmiElements) || |
8607 (set_capacity_mode == kForceSmiOnlyElements) || | 8626 ((smi_mode == kAllowSmiElements) && HasFastSmiElements()); |
8608 ((set_capacity_mode == kAllowSmiOnlyElements) && | 8627 if (has_fast_smi_elements) { |
8609 (elements()->map()->has_fast_smi_only_elements() || | 8628 if (IsHoleyElementsKind(elements_kind)) { |
8610 elements() == heap->empty_fixed_array())); | 8629 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; |
8611 ElementsKind elements_kind = has_fast_smi_only_elements | 8630 } else { |
8612 ? FAST_SMI_ONLY_ELEMENTS | 8631 new_elements_kind = FAST_SMI_ELEMENTS; |
8613 : FAST_ELEMENTS; | 8632 } |
8614 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | 8633 } else { |
8615 if (!maybe->To(&new_map)) return maybe; | 8634 if (IsHoleyElementsKind(elements_kind)) { |
| 8635 new_elements_kind = FAST_HOLEY_ELEMENTS; |
| 8636 } else { |
| 8637 new_elements_kind = FAST_ELEMENTS; |
| 8638 } |
8616 } | 8639 } |
8617 | |
8618 FixedArrayBase* old_elements = elements(); | 8640 FixedArrayBase* old_elements = elements(); |
8619 ElementsKind elements_kind = GetElementsKind(); | |
8620 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8641 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8621 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) | |
8622 ? FAST_SMI_ONLY_ELEMENTS | |
8623 : FAST_ELEMENTS; | |
8624 { MaybeObject* maybe_obj = | 8642 { MaybeObject* maybe_obj = |
8625 accessor->CopyElements(this, new_elements, to_kind); | 8643 accessor->CopyElements(this, new_elements, new_elements_kind); |
8626 if (maybe_obj->IsFailure()) return maybe_obj; | 8644 if (maybe_obj->IsFailure()) return maybe_obj; |
8627 } | 8645 } |
8628 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8646 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8647 Map* new_map = map(); |
| 8648 if (new_elements_kind != elements_kind) { |
| 8649 MaybeObject* maybe = |
| 8650 GetElementsTransitionMap(GetIsolate(), new_elements_kind); |
| 8651 if (!maybe->To(&new_map)) return maybe; |
| 8652 } |
| 8653 ValidateElements(); |
8629 set_map_and_elements(new_map, new_elements); | 8654 set_map_and_elements(new_map, new_elements); |
8630 } else { | 8655 } else { |
8631 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8656 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8632 parameter_map->set(1, new_elements); | 8657 parameter_map->set(1, new_elements); |
8633 } | 8658 } |
8634 | 8659 |
8635 if (FLAG_trace_elements_transitions) { | 8660 if (FLAG_trace_elements_transitions) { |
8636 PrintElementsTransition(stdout, elements_kind, old_elements, | 8661 PrintElementsTransition(stdout, elements_kind, old_elements, |
8637 GetElementsKind(), new_elements); | 8662 GetElementsKind(), new_elements); |
8638 } | 8663 } |
8639 | 8664 |
8640 // Update the length if necessary. | |
8641 if (IsJSArray()) { | 8665 if (IsJSArray()) { |
8642 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8666 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8643 } | 8667 } |
8644 | |
8645 return new_elements; | 8668 return new_elements; |
8646 } | 8669 } |
8647 | 8670 |
8648 | 8671 |
8649 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8672 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
8650 int capacity, | 8673 int capacity, |
8651 int length) { | 8674 int length) { |
8652 Heap* heap = GetHeap(); | 8675 Heap* heap = GetHeap(); |
8653 // We should never end in here with a pixel or external array. | 8676 // We should never end in here with a pixel or external array. |
8654 ASSERT(!HasExternalArrayElements()); | 8677 ASSERT(!HasExternalArrayElements()); |
8655 | 8678 |
8656 FixedArrayBase* elems; | 8679 FixedArrayBase* elems; |
8657 { MaybeObject* maybe_obj = | 8680 { MaybeObject* maybe_obj = |
8658 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8681 heap->AllocateUninitializedFixedDoubleArray(capacity); |
8659 if (!maybe_obj->To(&elems)) return maybe_obj; | 8682 if (!maybe_obj->To(&elems)) return maybe_obj; |
8660 } | 8683 } |
8661 | 8684 |
| 8685 ElementsKind elements_kind = GetElementsKind(); |
| 8686 ElementsKind new_elements_kind = elements_kind; |
| 8687 if (IsHoleyElementsKind(elements_kind)) { |
| 8688 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; |
| 8689 } else { |
| 8690 new_elements_kind = FAST_DOUBLE_ELEMENTS; |
| 8691 } |
| 8692 |
8662 Map* new_map; | 8693 Map* new_map; |
8663 { MaybeObject* maybe_obj = | 8694 { MaybeObject* maybe_obj = |
8664 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); | 8695 GetElementsTransitionMap(heap->isolate(), new_elements_kind); |
8665 if (!maybe_obj->To(&new_map)) return maybe_obj; | 8696 if (!maybe_obj->To(&new_map)) return maybe_obj; |
8666 } | 8697 } |
8667 | 8698 |
8668 FixedArrayBase* old_elements = elements(); | 8699 FixedArrayBase* old_elements = elements(); |
8669 ElementsKind elements_kind = GetElementsKind(); | |
8670 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8700 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8671 { MaybeObject* maybe_obj = | 8701 { MaybeObject* maybe_obj = |
8672 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); | 8702 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); |
8673 if (maybe_obj->IsFailure()) return maybe_obj; | 8703 if (maybe_obj->IsFailure()) return maybe_obj; |
8674 } | 8704 } |
8675 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8705 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8706 ValidateElements(); |
8676 set_map_and_elements(new_map, elems); | 8707 set_map_and_elements(new_map, elems); |
8677 } else { | 8708 } else { |
8678 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8709 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8679 parameter_map->set(1, elems); | 8710 parameter_map->set(1, elems); |
8680 } | 8711 } |
8681 | 8712 |
8682 if (FLAG_trace_elements_transitions) { | 8713 if (FLAG_trace_elements_transitions) { |
8683 PrintElementsTransition(stdout, elements_kind, old_elements, | 8714 PrintElementsTransition(stdout, elements_kind, old_elements, |
8684 FAST_DOUBLE_ELEMENTS, elems); | 8715 GetElementsKind(), elems); |
8685 } | 8716 } |
8686 | 8717 |
8687 if (IsJSArray()) { | 8718 if (IsJSArray()) { |
8688 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8719 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8689 } | 8720 } |
8690 | 8721 |
8691 return this; | 8722 return this; |
8692 } | 8723 } |
8693 | 8724 |
8694 | 8725 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8954 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8985 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
8955 : UNDEFINED_ELEMENT; | 8986 : UNDEFINED_ELEMENT; |
8956 } | 8987 } |
8957 | 8988 |
8958 // Handle [] on String objects. | 8989 // Handle [] on String objects. |
8959 if (this->IsStringObjectWithCharacterAt(index)) { | 8990 if (this->IsStringObjectWithCharacterAt(index)) { |
8960 return STRING_CHARACTER_ELEMENT; | 8991 return STRING_CHARACTER_ELEMENT; |
8961 } | 8992 } |
8962 | 8993 |
8963 switch (GetElementsKind()) { | 8994 switch (GetElementsKind()) { |
8964 case FAST_SMI_ONLY_ELEMENTS: | 8995 case FAST_SMI_ELEMENTS: |
8965 case FAST_ELEMENTS: { | 8996 case FAST_ELEMENTS: |
| 8997 case FAST_HOLEY_SMI_ELEMENTS: |
| 8998 case FAST_HOLEY_ELEMENTS: { |
8966 uint32_t length = IsJSArray() ? | 8999 uint32_t length = IsJSArray() ? |
8967 static_cast<uint32_t> | 9000 static_cast<uint32_t> |
8968 (Smi::cast(JSArray::cast(this)->length())->value()) : | 9001 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8969 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9002 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
8970 if ((index < length) && | 9003 if ((index < length) && |
8971 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 9004 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
8972 return FAST_ELEMENT; | 9005 return FAST_ELEMENT; |
8973 } | 9006 } |
8974 break; | 9007 break; |
8975 } | 9008 } |
8976 case FAST_DOUBLE_ELEMENTS: { | 9009 case FAST_DOUBLE_ELEMENTS: |
| 9010 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
8977 uint32_t length = IsJSArray() ? | 9011 uint32_t length = IsJSArray() ? |
8978 static_cast<uint32_t> | 9012 static_cast<uint32_t> |
8979 (Smi::cast(JSArray::cast(this)->length())->value()) : | 9013 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8980 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 9014 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
8981 if ((index < length) && | 9015 if ((index < length) && |
8982 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | 9016 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
8983 return FAST_ELEMENT; | 9017 return FAST_ELEMENT; |
8984 } | 9018 } |
8985 break; | 9019 break; |
8986 } | 9020 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9250 } | 9284 } |
9251 | 9285 |
9252 | 9286 |
9253 // Adding n elements in fast case is O(n*n). | 9287 // Adding n elements in fast case is O(n*n). |
9254 // Note: revisit design to have dual undefined values to capture absent | 9288 // Note: revisit design to have dual undefined values to capture absent |
9255 // elements. | 9289 // elements. |
9256 MaybeObject* JSObject::SetFastElement(uint32_t index, | 9290 MaybeObject* JSObject::SetFastElement(uint32_t index, |
9257 Object* value, | 9291 Object* value, |
9258 StrictModeFlag strict_mode, | 9292 StrictModeFlag strict_mode, |
9259 bool check_prototype) { | 9293 bool check_prototype) { |
9260 ASSERT(HasFastTypeElements() || | 9294 ASSERT(HasFastSmiOrObjectElements() || |
9261 HasFastArgumentsElements()); | 9295 HasFastArgumentsElements()); |
9262 | 9296 |
9263 FixedArray* backing_store = FixedArray::cast(elements()); | 9297 FixedArray* backing_store = FixedArray::cast(elements()); |
9264 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9298 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
9265 backing_store = FixedArray::cast(backing_store->get(1)); | 9299 backing_store = FixedArray::cast(backing_store->get(1)); |
9266 } else { | 9300 } else { |
9267 MaybeObject* maybe = EnsureWritableFastElements(); | 9301 MaybeObject* maybe = EnsureWritableFastElements(); |
9268 if (!maybe->To(&backing_store)) return maybe; | 9302 if (!maybe->To(&backing_store)) return maybe; |
9269 } | 9303 } |
9270 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 9304 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
9271 | 9305 |
9272 if (check_prototype && | 9306 if (check_prototype && |
9273 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 9307 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
9274 bool found; | 9308 bool found; |
9275 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9309 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9276 value, | 9310 value, |
9277 &found, | 9311 &found, |
9278 strict_mode); | 9312 strict_mode); |
9279 if (found) return result; | 9313 if (found) return result; |
9280 } | 9314 } |
9281 | 9315 |
9282 uint32_t new_capacity = capacity; | 9316 uint32_t new_capacity = capacity; |
9283 // Check if the length property of this object needs to be updated. | 9317 // Check if the length property of this object needs to be updated. |
9284 uint32_t array_length = 0; | 9318 uint32_t array_length = 0; |
9285 bool must_update_array_length = false; | 9319 bool must_update_array_length = false; |
| 9320 bool introduces_holes = true; |
9286 if (IsJSArray()) { | 9321 if (IsJSArray()) { |
9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9322 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 9323 introduces_holes = index > array_length; |
9288 if (index >= array_length) { | 9324 if (index >= array_length) { |
9289 must_update_array_length = true; | 9325 must_update_array_length = true; |
9290 array_length = index + 1; | 9326 array_length = index + 1; |
9291 } | 9327 } |
| 9328 } else { |
| 9329 introduces_holes = index >= capacity; |
9292 } | 9330 } |
| 9331 |
| 9332 // If the array is growing, and it's not growth by a single element at the |
| 9333 // end, make sure that the ElementsKind is HOLEY. |
| 9334 ElementsKind elements_kind = GetElementsKind(); |
| 9335 if (introduces_holes && |
| 9336 IsFastElementsKind(elements_kind) && |
| 9337 !IsFastHoleyElementsKind(elements_kind)) { |
| 9338 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 9339 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); |
| 9340 if (maybe->IsFailure()) return maybe; |
| 9341 } |
| 9342 |
9293 // Check if the capacity of the backing store needs to be increased, or if | 9343 // Check if the capacity of the backing store needs to be increased, or if |
9294 // a transition to slow elements is necessary. | 9344 // a transition to slow elements is necessary. |
9295 if (index >= capacity) { | 9345 if (index >= capacity) { |
9296 bool convert_to_slow = true; | 9346 bool convert_to_slow = true; |
9297 if ((index - capacity) < kMaxGap) { | 9347 if ((index - capacity) < kMaxGap) { |
9298 new_capacity = NewElementsCapacity(index + 1); | 9348 new_capacity = NewElementsCapacity(index + 1); |
9299 ASSERT(new_capacity > index); | 9349 ASSERT(new_capacity > index); |
9300 if (!ShouldConvertToSlowElements(new_capacity)) { | 9350 if (!ShouldConvertToSlowElements(new_capacity)) { |
9301 convert_to_slow = false; | 9351 convert_to_slow = false; |
9302 } | 9352 } |
9303 } | 9353 } |
9304 if (convert_to_slow) { | 9354 if (convert_to_slow) { |
9305 MaybeObject* result = NormalizeElements(); | 9355 MaybeObject* result = NormalizeElements(); |
9306 if (result->IsFailure()) return result; | 9356 if (result->IsFailure()) return result; |
9307 return SetDictionaryElement(index, value, NONE, strict_mode, | 9357 return SetDictionaryElement(index, value, NONE, strict_mode, |
9308 check_prototype); | 9358 check_prototype); |
9309 } | 9359 } |
9310 } | 9360 } |
9311 // Convert to fast double elements if appropriate. | 9361 // Convert to fast double elements if appropriate. |
9312 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { | 9362 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
9313 MaybeObject* maybe = | 9363 MaybeObject* maybe = |
9314 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9364 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
9315 if (maybe->IsFailure()) return maybe; | 9365 if (maybe->IsFailure()) return maybe; |
9316 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9366 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 9367 ValidateElements(); |
9317 return value; | 9368 return value; |
9318 } | 9369 } |
9319 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9370 // Change elements kind from Smi-only to generic FAST if necessary. |
9320 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9371 if (HasFastSmiElements() && !value->IsSmi()) { |
9321 Map* new_map; | 9372 Map* new_map; |
9322 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 9373 ElementsKind kind = HasFastHoleyElements() |
9323 FAST_ELEMENTS); | 9374 ? FAST_HOLEY_ELEMENTS |
9324 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9375 : FAST_ELEMENTS; |
9325 } | 9376 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
| 9377 kind); |
| 9378 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 9379 |
9326 set_map(new_map); | 9380 set_map(new_map); |
9327 if (FLAG_trace_elements_transitions) { | |
9328 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), | |
9329 FAST_ELEMENTS, elements()); | |
9330 } | |
9331 } | 9381 } |
9332 // Increase backing store capacity if that's been decided previously. | 9382 // Increase backing store capacity if that's been decided previously. |
9333 if (new_capacity != capacity) { | 9383 if (new_capacity != capacity) { |
9334 FixedArray* new_elements; | 9384 FixedArray* new_elements; |
9335 SetFastElementsCapacityMode set_capacity_mode = | 9385 SetFastElementsCapacitySmiMode smi_mode = |
9336 value->IsSmi() && HasFastSmiOnlyElements() | 9386 value->IsSmi() && HasFastSmiElements() |
9337 ? kAllowSmiOnlyElements | 9387 ? kAllowSmiElements |
9338 : kDontAllowSmiOnlyElements; | 9388 : kDontAllowSmiElements; |
9339 { MaybeObject* maybe = | 9389 { MaybeObject* maybe = |
9340 SetFastElementsCapacityAndLength(new_capacity, | 9390 SetFastElementsCapacityAndLength(new_capacity, |
9341 array_length, | 9391 array_length, |
9342 set_capacity_mode); | 9392 smi_mode); |
9343 if (!maybe->To(&new_elements)) return maybe; | 9393 if (!maybe->To(&new_elements)) return maybe; |
9344 } | 9394 } |
9345 new_elements->set(index, value); | 9395 new_elements->set(index, value); |
| 9396 ValidateElements(); |
9346 return value; | 9397 return value; |
9347 } | 9398 } |
| 9399 |
9348 // Finally, set the new element and length. | 9400 // Finally, set the new element and length. |
9349 ASSERT(elements()->IsFixedArray()); | 9401 ASSERT(elements()->IsFixedArray()); |
9350 backing_store->set(index, value); | 9402 backing_store->set(index, value); |
9351 if (must_update_array_length) { | 9403 if (must_update_array_length) { |
9352 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 9404 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); |
9353 } | 9405 } |
9354 return value; | 9406 return value; |
9355 } | 9407 } |
9356 | 9408 |
9357 | 9409 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9461 } | 9513 } |
9462 | 9514 |
9463 // Attempt to put this object back in fast case. | 9515 // Attempt to put this object back in fast case. |
9464 if (ShouldConvertToFastElements()) { | 9516 if (ShouldConvertToFastElements()) { |
9465 uint32_t new_length = 0; | 9517 uint32_t new_length = 0; |
9466 if (IsJSArray()) { | 9518 if (IsJSArray()) { |
9467 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 9519 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
9468 } else { | 9520 } else { |
9469 new_length = dictionary->max_number_key() + 1; | 9521 new_length = dictionary->max_number_key() + 1; |
9470 } | 9522 } |
9471 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays | 9523 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays |
9472 ? kAllowSmiOnlyElements | 9524 ? kAllowSmiElements |
9473 : kDontAllowSmiOnlyElements; | 9525 : kDontAllowSmiElements; |
9474 bool has_smi_only_elements = false; | 9526 bool has_smi_only_elements = false; |
9475 bool should_convert_to_fast_double_elements = | 9527 bool should_convert_to_fast_double_elements = |
9476 ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 9528 ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
9477 if (has_smi_only_elements) { | 9529 if (has_smi_only_elements) { |
9478 set_capacity_mode = kForceSmiOnlyElements; | 9530 smi_mode = kForceSmiElements; |
9479 } | 9531 } |
9480 MaybeObject* result = should_convert_to_fast_double_elements | 9532 MaybeObject* result = should_convert_to_fast_double_elements |
9481 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 9533 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
9482 : SetFastElementsCapacityAndLength(new_length, | 9534 : SetFastElementsCapacityAndLength(new_length, |
9483 new_length, | 9535 new_length, |
9484 set_capacity_mode); | 9536 smi_mode); |
| 9537 ValidateElements(); |
9485 if (result->IsFailure()) return result; | 9538 if (result->IsFailure()) return result; |
9486 #ifdef DEBUG | 9539 #ifdef DEBUG |
9487 if (FLAG_trace_normalization) { | 9540 if (FLAG_trace_normalization) { |
9488 PrintF("Object elements are fast case again:\n"); | 9541 PrintF("Object elements are fast case again:\n"); |
9489 Print(); | 9542 Print(); |
9490 } | 9543 } |
9491 #endif | 9544 #endif |
9492 } | 9545 } |
9493 return value; | 9546 return value; |
9494 } | 9547 } |
(...skipping 18 matching lines...) Expand all Loading... |
9513 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9566 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9514 value, | 9567 value, |
9515 &found, | 9568 &found, |
9516 strict_mode); | 9569 strict_mode); |
9517 if (found) return result; | 9570 if (found) return result; |
9518 } | 9571 } |
9519 | 9572 |
9520 // If the value object is not a heap number, switch to fast elements and try | 9573 // If the value object is not a heap number, switch to fast elements and try |
9521 // again. | 9574 // again. |
9522 bool value_is_smi = value->IsSmi(); | 9575 bool value_is_smi = value->IsSmi(); |
| 9576 bool introduces_holes = true; |
| 9577 uint32_t length = elms_length; |
| 9578 if (IsJSArray()) { |
| 9579 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9580 introduces_holes = index > length; |
| 9581 } else { |
| 9582 introduces_holes = index >= elms_length; |
| 9583 } |
| 9584 |
9523 if (!value->IsNumber()) { | 9585 if (!value->IsNumber()) { |
9524 Object* obj; | |
9525 uint32_t length = elms_length; | |
9526 if (IsJSArray()) { | |
9527 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
9528 } | |
9529 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 9586 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
9530 elms_length, | 9587 elms_length, |
9531 length, | 9588 length, |
9532 kDontAllowSmiOnlyElements); | 9589 kDontAllowSmiElements); |
9533 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9590 if (maybe_obj->IsFailure()) return maybe_obj; |
9534 return SetFastElement(index, | 9591 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); |
9535 value, | 9592 if (maybe_obj->IsFailure()) return maybe_obj; |
9536 strict_mode, | 9593 ValidateElements(); |
9537 check_prototype); | 9594 return maybe_obj; |
9538 } | 9595 } |
9539 | 9596 |
9540 double double_value = value_is_smi | 9597 double double_value = value_is_smi |
9541 ? static_cast<double>(Smi::cast(value)->value()) | 9598 ? static_cast<double>(Smi::cast(value)->value()) |
9542 : HeapNumber::cast(value)->value(); | 9599 : HeapNumber::cast(value)->value(); |
9543 | 9600 |
| 9601 // If the array is growing, and it's not growth by a single element at the |
| 9602 // end, make sure that the ElementsKind is HOLEY. |
| 9603 ElementsKind elements_kind = GetElementsKind(); |
| 9604 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { |
| 9605 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 9606 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); |
| 9607 if (maybe->IsFailure()) return maybe; |
| 9608 } |
| 9609 |
9544 // Check whether there is extra space in the fixed array. | 9610 // Check whether there is extra space in the fixed array. |
9545 if (index < elms_length) { | 9611 if (index < elms_length) { |
9546 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9612 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9547 elms->set(index, double_value); | 9613 elms->set(index, double_value); |
9548 if (IsJSArray()) { | 9614 if (IsJSArray()) { |
9549 // Update the length of the array if needed. | 9615 // Update the length of the array if needed. |
9550 uint32_t array_length = 0; | 9616 uint32_t array_length = 0; |
9551 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9617 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9552 if (index >= array_length) { | 9618 if (index >= array_length) { |
9553 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 9619 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
9554 } | 9620 } |
9555 } | 9621 } |
9556 return value; | 9622 return value; |
9557 } | 9623 } |
9558 | 9624 |
9559 // Allow gap in fast case. | 9625 // Allow gap in fast case. |
9560 if ((index - elms_length) < kMaxGap) { | 9626 if ((index - elms_length) < kMaxGap) { |
9561 // Try allocating extra space. | 9627 // Try allocating extra space. |
9562 int new_capacity = NewElementsCapacity(index+1); | 9628 int new_capacity = NewElementsCapacity(index+1); |
9563 if (!ShouldConvertToSlowElements(new_capacity)) { | 9629 if (!ShouldConvertToSlowElements(new_capacity)) { |
9564 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 9630 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
9565 Object* obj; | 9631 MaybeObject* maybe_obj = |
9566 { MaybeObject* maybe_obj = | 9632 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); |
9567 SetFastDoubleElementsCapacityAndLength(new_capacity, | 9633 if (maybe_obj->IsFailure()) return maybe_obj; |
9568 index + 1); | |
9569 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
9570 } | |
9571 FixedDoubleArray::cast(elements())->set(index, double_value); | 9634 FixedDoubleArray::cast(elements())->set(index, double_value); |
| 9635 ValidateElements(); |
9572 return value; | 9636 return value; |
9573 } | 9637 } |
9574 } | 9638 } |
9575 | 9639 |
9576 // Otherwise default to slow case. | 9640 // Otherwise default to slow case. |
9577 ASSERT(HasFastDoubleElements()); | 9641 ASSERT(HasFastDoubleElements()); |
9578 ASSERT(map()->has_fast_double_elements()); | 9642 ASSERT(map()->has_fast_double_elements()); |
9579 ASSERT(elements()->IsFixedDoubleArray()); | 9643 ASSERT(elements()->IsFixedDoubleArray()); |
9580 Object* obj; | 9644 Object* obj; |
9581 { MaybeObject* maybe_obj = NormalizeElements(); | 9645 { MaybeObject* maybe_obj = NormalizeElements(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9705 Object* value, | 9769 Object* value, |
9706 PropertyAttributes attr, | 9770 PropertyAttributes attr, |
9707 StrictModeFlag strict_mode, | 9771 StrictModeFlag strict_mode, |
9708 bool check_prototype, | 9772 bool check_prototype, |
9709 SetPropertyMode set_mode) { | 9773 SetPropertyMode set_mode) { |
9710 ASSERT(HasDictionaryElements() || | 9774 ASSERT(HasDictionaryElements() || |
9711 HasDictionaryArgumentsElements() || | 9775 HasDictionaryArgumentsElements() || |
9712 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 9776 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
9713 Isolate* isolate = GetIsolate(); | 9777 Isolate* isolate = GetIsolate(); |
9714 switch (GetElementsKind()) { | 9778 switch (GetElementsKind()) { |
9715 case FAST_SMI_ONLY_ELEMENTS: | 9779 case FAST_SMI_ELEMENTS: |
9716 case FAST_ELEMENTS: | 9780 case FAST_ELEMENTS: |
| 9781 case FAST_HOLEY_SMI_ELEMENTS: |
| 9782 case FAST_HOLEY_ELEMENTS: |
9717 return SetFastElement(index, value, strict_mode, check_prototype); | 9783 return SetFastElement(index, value, strict_mode, check_prototype); |
9718 case FAST_DOUBLE_ELEMENTS: | 9784 case FAST_DOUBLE_ELEMENTS: |
| 9785 case FAST_HOLEY_DOUBLE_ELEMENTS: |
9719 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 9786 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
9720 case EXTERNAL_PIXEL_ELEMENTS: { | 9787 case EXTERNAL_PIXEL_ELEMENTS: { |
9721 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9788 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
9722 return pixels->SetValue(index, value); | 9789 return pixels->SetValue(index, value); |
9723 } | 9790 } |
9724 case EXTERNAL_BYTE_ELEMENTS: { | 9791 case EXTERNAL_BYTE_ELEMENTS: { |
9725 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 9792 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
9726 return array->SetValue(index, value); | 9793 return array->SetValue(index, value); |
9727 } | 9794 } |
9728 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 9795 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9799 ElementsKind to_kind) { | 9866 ElementsKind to_kind) { |
9800 CALL_HEAP_FUNCTION(object->GetIsolate(), | 9867 CALL_HEAP_FUNCTION(object->GetIsolate(), |
9801 object->TransitionElementsKind(to_kind), | 9868 object->TransitionElementsKind(to_kind), |
9802 Object); | 9869 Object); |
9803 } | 9870 } |
9804 | 9871 |
9805 | 9872 |
9806 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 9873 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
9807 ElementsKind from_kind = map()->elements_kind(); | 9874 ElementsKind from_kind = map()->elements_kind(); |
9808 | 9875 |
| 9876 if (IsFastHoleyElementsKind(from_kind)) { |
| 9877 to_kind = GetHoleyElementsKind(to_kind); |
| 9878 } |
| 9879 |
9809 Isolate* isolate = GetIsolate(); | 9880 Isolate* isolate = GetIsolate(); |
9810 if ((from_kind == FAST_SMI_ONLY_ELEMENTS || | 9881 if (elements() == isolate->heap()->empty_fixed_array() || |
9811 elements() == isolate->heap()->empty_fixed_array()) && | 9882 (IsFastSmiOrObjectElementsKind(from_kind) && |
9812 to_kind == FAST_ELEMENTS) { | 9883 IsFastSmiOrObjectElementsKind(to_kind)) || |
9813 ASSERT(from_kind != FAST_ELEMENTS); | 9884 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 9885 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 9886 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 9887 // No change is needed to the elements() buffer, the transition |
| 9888 // only requires a map change. |
9814 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 9889 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
9815 Map* new_map; | 9890 Map* new_map; |
9816 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9891 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9817 set_map(new_map); | 9892 set_map(new_map); |
9818 if (FLAG_trace_elements_transitions) { | 9893 if (FLAG_trace_elements_transitions) { |
9819 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9894 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9820 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 9895 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
9821 } | 9896 } |
9822 return this; | 9897 return this; |
9823 } | 9898 } |
9824 | 9899 |
9825 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9900 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9826 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9901 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9827 uint32_t length = capacity; | 9902 uint32_t length = capacity; |
9828 | 9903 |
9829 if (IsJSArray()) { | 9904 if (IsJSArray()) { |
9830 Object* raw_length = JSArray::cast(this)->length(); | 9905 Object* raw_length = JSArray::cast(this)->length(); |
9831 if (raw_length->IsUndefined()) { | 9906 if (raw_length->IsUndefined()) { |
9832 // If length is undefined, then JSArray is being initialized and has no | 9907 // If length is undefined, then JSArray is being initialized and has no |
9833 // elements, assume a length of zero. | 9908 // elements, assume a length of zero. |
9834 length = 0; | 9909 length = 0; |
9835 } else { | 9910 } else { |
9836 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9911 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
9837 } | 9912 } |
9838 } | 9913 } |
9839 | 9914 |
9840 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9915 if (IsFastSmiElementsKind(from_kind) && |
9841 to_kind == FAST_DOUBLE_ELEMENTS) { | 9916 IsFastDoubleElementsKind(to_kind)) { |
9842 MaybeObject* maybe_result = | 9917 MaybeObject* maybe_result = |
9843 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9918 SetFastDoubleElementsCapacityAndLength(capacity, length); |
9844 if (maybe_result->IsFailure()) return maybe_result; | 9919 if (maybe_result->IsFailure()) return maybe_result; |
| 9920 ValidateElements(); |
9845 return this; | 9921 return this; |
9846 } | 9922 } |
9847 | 9923 |
9848 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 9924 if (IsFastDoubleElementsKind(from_kind) && |
| 9925 IsFastObjectElementsKind(to_kind)) { |
9849 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9926 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
9850 capacity, length, kDontAllowSmiOnlyElements); | 9927 capacity, length, kDontAllowSmiElements); |
9851 if (maybe_result->IsFailure()) return maybe_result; | 9928 if (maybe_result->IsFailure()) return maybe_result; |
| 9929 ValidateElements(); |
9852 return this; | 9930 return this; |
9853 } | 9931 } |
9854 | 9932 |
9855 // This method should never be called for any other case than the ones | 9933 // This method should never be called for any other case than the ones |
9856 // handled above. | 9934 // handled above. |
9857 UNREACHABLE(); | 9935 UNREACHABLE(); |
9858 return GetIsolate()->heap()->null_value(); | 9936 return GetIsolate()->heap()->null_value(); |
9859 } | 9937 } |
9860 | 9938 |
9861 | 9939 |
9862 // static | 9940 // static |
9863 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9941 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
9864 ElementsKind to_kind) { | 9942 ElementsKind to_kind) { |
9865 return | 9943 // Transitions can't go backwards. |
9866 (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9944 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
9867 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || | 9945 return false; |
9868 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); | 9946 } |
| 9947 |
| 9948 // Transitions from HOLEY -> PACKED are not allowed. |
| 9949 return !IsFastHoleyElementsKind(from_kind) || |
| 9950 IsFastHoleyElementsKind(to_kind); |
9869 } | 9951 } |
9870 | 9952 |
9871 | 9953 |
9872 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 9954 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
9873 Object* value) { | 9955 Object* value) { |
9874 uint32_t old_len = 0; | 9956 uint32_t old_len = 0; |
9875 CHECK(length()->ToArrayIndex(&old_len)); | 9957 CHECK(length()->ToArrayIndex(&old_len)); |
9876 // Check to see if we need to update the length. For now, we make | 9958 // Check to see if we need to update the length. For now, we make |
9877 // sure that the length stays within 32-bits (unsigned). | 9959 // sure that the length stays within 32-bits (unsigned). |
9878 if (index >= old_len && index != 0xffffffff) { | 9960 if (index >= old_len && index != 0xffffffff) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9949 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 10031 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
9950 backing_store = FixedArray::cast(backing_store_base); | 10032 backing_store = FixedArray::cast(backing_store_base); |
9951 if (backing_store->IsDictionary()) { | 10033 if (backing_store->IsDictionary()) { |
9952 SeededNumberDictionary* dictionary = | 10034 SeededNumberDictionary* dictionary = |
9953 SeededNumberDictionary::cast(backing_store); | 10035 SeededNumberDictionary::cast(backing_store); |
9954 *capacity = dictionary->Capacity(); | 10036 *capacity = dictionary->Capacity(); |
9955 *used = dictionary->NumberOfElements(); | 10037 *used = dictionary->NumberOfElements(); |
9956 break; | 10038 break; |
9957 } | 10039 } |
9958 // Fall through. | 10040 // Fall through. |
9959 case FAST_SMI_ONLY_ELEMENTS: | 10041 case FAST_SMI_ELEMENTS: |
9960 case FAST_ELEMENTS: | 10042 case FAST_ELEMENTS: |
| 10043 case FAST_HOLEY_SMI_ELEMENTS: |
| 10044 case FAST_HOLEY_ELEMENTS: |
9961 backing_store = FixedArray::cast(backing_store_base); | 10045 backing_store = FixedArray::cast(backing_store_base); |
9962 *capacity = backing_store->length(); | 10046 *capacity = backing_store->length(); |
9963 for (int i = 0; i < *capacity; ++i) { | 10047 for (int i = 0; i < *capacity; ++i) { |
9964 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 10048 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
9965 } | 10049 } |
9966 break; | 10050 break; |
9967 case DICTIONARY_ELEMENTS: { | 10051 case DICTIONARY_ELEMENTS: { |
9968 SeededNumberDictionary* dictionary = | 10052 SeededNumberDictionary* dictionary = |
9969 SeededNumberDictionary::cast(FixedArray::cast(elements())); | 10053 SeededNumberDictionary::cast(FixedArray::cast(elements())); |
9970 *capacity = dictionary->Capacity(); | 10054 *capacity = dictionary->Capacity(); |
9971 *used = dictionary->NumberOfElements(); | 10055 *used = dictionary->NumberOfElements(); |
9972 break; | 10056 break; |
9973 } | 10057 } |
9974 case FAST_DOUBLE_ELEMENTS: { | 10058 case FAST_DOUBLE_ELEMENTS: |
| 10059 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
9975 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 10060 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9976 *capacity = elms->length(); | 10061 *capacity = elms->length(); |
9977 for (int i = 0; i < *capacity; i++) { | 10062 for (int i = 0; i < *capacity; i++) { |
9978 if (!elms->is_the_hole(i)) ++(*used); | 10063 if (!elms->is_the_hole(i)) ++(*used); |
9979 } | 10064 } |
9980 break; | 10065 break; |
9981 } | 10066 } |
9982 case EXTERNAL_BYTE_ELEMENTS: | 10067 case EXTERNAL_BYTE_ELEMENTS: |
9983 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 10068 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
9984 case EXTERNAL_SHORT_ELEMENTS: | 10069 case EXTERNAL_SHORT_ELEMENTS: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10234 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10319 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
10235 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 10320 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
10236 return false; | 10321 return false; |
10237 } | 10322 } |
10238 } | 10323 } |
10239 | 10324 |
10240 // Handle [] on String objects. | 10325 // Handle [] on String objects. |
10241 if (this->IsStringObjectWithCharacterAt(index)) return true; | 10326 if (this->IsStringObjectWithCharacterAt(index)) return true; |
10242 | 10327 |
10243 switch (GetElementsKind()) { | 10328 switch (GetElementsKind()) { |
10244 case FAST_SMI_ONLY_ELEMENTS: | 10329 case FAST_SMI_ELEMENTS: |
10245 case FAST_ELEMENTS: { | 10330 case FAST_ELEMENTS: |
10246 uint32_t length = IsJSArray() ? | 10331 case FAST_HOLEY_SMI_ELEMENTS: |
| 10332 case FAST_HOLEY_ELEMENTS: { |
| 10333 uint32_t length = IsJSArray() ? |
10247 static_cast<uint32_t>( | 10334 static_cast<uint32_t>( |
10248 Smi::cast(JSArray::cast(this)->length())->value()) : | 10335 Smi::cast(JSArray::cast(this)->length())->value()) : |
10249 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10336 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10250 return (index < length) && | 10337 return (index < length) && |
10251 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 10338 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
10252 } | 10339 } |
10253 case FAST_DOUBLE_ELEMENTS: { | 10340 case FAST_DOUBLE_ELEMENTS: |
| 10341 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
10254 uint32_t length = IsJSArray() ? | 10342 uint32_t length = IsJSArray() ? |
10255 static_cast<uint32_t>( | 10343 static_cast<uint32_t>( |
10256 Smi::cast(JSArray::cast(this)->length())->value()) : | 10344 Smi::cast(JSArray::cast(this)->length())->value()) : |
10257 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 10345 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
10258 return (index < length) && | 10346 return (index < length) && |
10259 !FixedDoubleArray::cast(elements())->is_the_hole(index); | 10347 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
10260 break; | 10348 break; |
10261 } | 10349 } |
10262 case EXTERNAL_PIXEL_ELEMENTS: { | 10350 case EXTERNAL_PIXEL_ELEMENTS: { |
10263 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 10351 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10443 } | 10531 } |
10444 | 10532 |
10445 | 10533 |
10446 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 10534 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
10447 return GetLocalElementKeys(NULL, filter); | 10535 return GetLocalElementKeys(NULL, filter); |
10448 } | 10536 } |
10449 | 10537 |
10450 | 10538 |
10451 int JSObject::NumberOfEnumElements() { | 10539 int JSObject::NumberOfEnumElements() { |
10452 // Fast case for objects with no elements. | 10540 // Fast case for objects with no elements. |
10453 if (!IsJSValue() && HasFastElements()) { | 10541 if (!IsJSValue() && HasFastObjectElements()) { |
10454 uint32_t length = IsJSArray() ? | 10542 uint32_t length = IsJSArray() ? |
10455 static_cast<uint32_t>( | 10543 static_cast<uint32_t>( |
10456 Smi::cast(JSArray::cast(this)->length())->value()) : | 10544 Smi::cast(JSArray::cast(this)->length())->value()) : |
10457 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10545 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10458 if (length == 0) return 0; | 10546 if (length == 0) return 0; |
10459 } | 10547 } |
10460 // Compute the number of enumerable elements. | 10548 // Compute the number of enumerable elements. |
10461 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 10549 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
10462 } | 10550 } |
10463 | 10551 |
10464 | 10552 |
10465 int JSObject::GetLocalElementKeys(FixedArray* storage, | 10553 int JSObject::GetLocalElementKeys(FixedArray* storage, |
10466 PropertyAttributes filter) { | 10554 PropertyAttributes filter) { |
10467 int counter = 0; | 10555 int counter = 0; |
10468 switch (GetElementsKind()) { | 10556 switch (GetElementsKind()) { |
10469 case FAST_SMI_ONLY_ELEMENTS: | 10557 case FAST_SMI_ELEMENTS: |
10470 case FAST_ELEMENTS: { | 10558 case FAST_ELEMENTS: |
| 10559 case FAST_HOLEY_SMI_ELEMENTS: |
| 10560 case FAST_HOLEY_ELEMENTS: { |
10471 int length = IsJSArray() ? | 10561 int length = IsJSArray() ? |
10472 Smi::cast(JSArray::cast(this)->length())->value() : | 10562 Smi::cast(JSArray::cast(this)->length())->value() : |
10473 FixedArray::cast(elements())->length(); | 10563 FixedArray::cast(elements())->length(); |
10474 for (int i = 0; i < length; i++) { | 10564 for (int i = 0; i < length; i++) { |
10475 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 10565 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
10476 if (storage != NULL) { | 10566 if (storage != NULL) { |
10477 storage->set(counter, Smi::FromInt(i)); | 10567 storage->set(counter, Smi::FromInt(i)); |
10478 } | 10568 } |
10479 counter++; | 10569 counter++; |
10480 } | 10570 } |
10481 } | 10571 } |
10482 ASSERT(!storage || storage->length() >= counter); | 10572 ASSERT(!storage || storage->length() >= counter); |
10483 break; | 10573 break; |
10484 } | 10574 } |
10485 case FAST_DOUBLE_ELEMENTS: { | 10575 case FAST_DOUBLE_ELEMENTS: |
| 10576 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
10486 int length = IsJSArray() ? | 10577 int length = IsJSArray() ? |
10487 Smi::cast(JSArray::cast(this)->length())->value() : | 10578 Smi::cast(JSArray::cast(this)->length())->value() : |
10488 FixedDoubleArray::cast(elements())->length(); | 10579 FixedDoubleArray::cast(elements())->length(); |
10489 for (int i = 0; i < length; i++) { | 10580 for (int i = 0; i < length; i++) { |
10490 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 10581 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
10491 if (storage != NULL) { | 10582 if (storage != NULL) { |
10492 storage->set(counter, Smi::FromInt(i)); | 10583 storage->set(counter, Smi::FromInt(i)); |
10493 } | 10584 } |
10494 counter++; | 10585 counter++; |
10495 } | 10586 } |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11408 // Convert to fast elements containing only the existing properties. | 11499 // Convert to fast elements containing only the existing properties. |
11409 // Ordering is irrelevant, since we are going to sort anyway. | 11500 // Ordering is irrelevant, since we are going to sort anyway. |
11410 SeededNumberDictionary* dict = element_dictionary(); | 11501 SeededNumberDictionary* dict = element_dictionary(); |
11411 if (IsJSArray() || dict->requires_slow_elements() || | 11502 if (IsJSArray() || dict->requires_slow_elements() || |
11412 dict->max_number_key() >= limit) { | 11503 dict->max_number_key() >= limit) { |
11413 return PrepareSlowElementsForSort(limit); | 11504 return PrepareSlowElementsForSort(limit); |
11414 } | 11505 } |
11415 // Convert to fast elements. | 11506 // Convert to fast elements. |
11416 | 11507 |
11417 Object* obj; | 11508 Object* obj; |
11418 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 11509 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
11419 FAST_ELEMENTS); | 11510 FAST_HOLEY_ELEMENTS); |
11420 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11511 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11421 } | |
11422 Map* new_map = Map::cast(obj); | 11512 Map* new_map = Map::cast(obj); |
11423 | 11513 |
11424 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 11514 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
11425 Object* new_array; | 11515 Object* new_array; |
11426 { MaybeObject* maybe_new_array = | 11516 { MaybeObject* maybe_new_array = |
11427 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 11517 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
11428 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 11518 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
11429 } | 11519 } |
11430 FixedArray* fast_elements = FixedArray::cast(new_array); | 11520 FixedArray* fast_elements = FixedArray::cast(new_array); |
11431 dict->CopyValuesTo(fast_elements); | 11521 dict->CopyValuesTo(fast_elements); |
| 11522 ValidateElements(); |
11432 | 11523 |
11433 set_map(new_map); | 11524 set_map_and_elements(new_map, fast_elements); |
11434 set_elements(fast_elements); | |
11435 } else if (HasExternalArrayElements()) { | 11525 } else if (HasExternalArrayElements()) { |
11436 // External arrays cannot have holes or undefined elements. | 11526 // External arrays cannot have holes or undefined elements. |
11437 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 11527 return Smi::FromInt(ExternalArray::cast(elements())->length()); |
11438 } else if (!HasFastDoubleElements()) { | 11528 } else if (!HasFastDoubleElements()) { |
11439 Object* obj; | 11529 Object* obj; |
11440 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 11530 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
11441 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11531 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11442 } | 11532 } |
11443 } | 11533 } |
11444 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); | 11534 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); |
11445 | 11535 |
11446 // Collect holes at the end, undefined before that and the rest at the | 11536 // Collect holes at the end, undefined before that and the rest at the |
11447 // start, and return the number of non-hole, non-undefined values. | 11537 // start, and return the number of non-hole, non-undefined values. |
11448 | 11538 |
11449 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 11539 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
11450 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 11540 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
11451 if (limit > elements_length) { | 11541 if (limit > elements_length) { |
11452 limit = elements_length ; | 11542 limit = elements_length ; |
11453 } | 11543 } |
11454 if (limit == 0) { | 11544 if (limit == 0) { |
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13111 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13201 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13112 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13202 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13113 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13203 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13114 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13204 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13115 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13205 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13116 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13206 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13117 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13207 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13118 } | 13208 } |
13119 | 13209 |
13120 } } // namespace v8::internal | 13210 } } // namespace v8::internal |
OLD | NEW |