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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4438 accessors->SetComponents(getter, setter); | 4454 accessors->SetComponents(getter, setter); |
4439 return SetPropertyCallback(name, accessors, attributes); | 4455 return SetPropertyCallback(name, accessors, attributes); |
4440 } | 4456 } |
4441 | 4457 |
4442 | 4458 |
4443 bool JSObject::CanSetCallback(String* name) { | 4459 bool JSObject::CanSetCallback(String* name) { |
4444 ASSERT(!IsAccessCheckNeeded() || | 4460 ASSERT(!IsAccessCheckNeeded() || |
4445 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4461 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
4446 | 4462 |
4447 // Check if there is an API defined callback object which prohibits | 4463 // Check if there is an API defined callback object which prohibits |
4448 // callback overwriting in this object or it's prototype chain. | 4464 // callback overwriting in this object or its prototype chain. |
4449 // This mechanism is needed for instance in a browser setting, where | 4465 // This mechanism is needed for instance in a browser setting, where |
4450 // certain accessors such as window.location should not be allowed | 4466 // certain accessors such as window.location should not be allowed |
4451 // to be overwritten because allowing overwriting could potentially | 4467 // to be overwritten because allowing overwriting could potentially |
4452 // cause security problems. | 4468 // cause security problems. |
4453 LookupResult callback_result(GetIsolate()); | 4469 LookupResult callback_result(GetIsolate()); |
4454 LookupCallback(name, &callback_result); | 4470 LookupCallback(name, &callback_result); |
4455 if (callback_result.IsProperty()) { | 4471 if (callback_result.IsProperty()) { |
4456 Object* obj = callback_result.GetCallbackObject(); | 4472 Object* obj = callback_result.GetCallbackObject(); |
4457 if (obj->IsAccessorInfo() && | 4473 if (obj->IsAccessorInfo() && |
4458 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4474 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4609 } | 4625 } |
4610 | 4626 |
4611 uint32_t index = 0; | 4627 uint32_t index = 0; |
4612 bool is_element = name->AsArrayIndex(&index); | 4628 bool is_element = name->AsArrayIndex(&index); |
4613 | 4629 |
4614 if (is_element) { | 4630 if (is_element) { |
4615 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4631 if (IsJSArray()) return isolate->heap()->undefined_value(); |
4616 | 4632 |
4617 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4633 // Accessors overwrite previous callbacks (cf. with getters/setters). |
4618 switch (GetElementsKind()) { | 4634 switch (GetElementsKind()) { |
4619 case FAST_SMI_ONLY_ELEMENTS: | 4635 case FAST_SMI_ELEMENTS: |
4620 case FAST_ELEMENTS: | 4636 case FAST_ELEMENTS: |
4621 case FAST_DOUBLE_ELEMENTS: | 4637 case FAST_DOUBLE_ELEMENTS: |
| 4638 case FAST_HOLEY_SMI_ELEMENTS: |
| 4639 case FAST_HOLEY_ELEMENTS: |
| 4640 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4622 break; | 4641 break; |
4623 case EXTERNAL_PIXEL_ELEMENTS: | 4642 case EXTERNAL_PIXEL_ELEMENTS: |
4624 case EXTERNAL_BYTE_ELEMENTS: | 4643 case EXTERNAL_BYTE_ELEMENTS: |
4625 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4644 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4626 case EXTERNAL_SHORT_ELEMENTS: | 4645 case EXTERNAL_SHORT_ELEMENTS: |
4627 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4646 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4628 case EXTERNAL_INT_ELEMENTS: | 4647 case EXTERNAL_INT_ELEMENTS: |
4629 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4648 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4630 case EXTERNAL_FLOAT_ELEMENTS: | 4649 case EXTERNAL_FLOAT_ELEMENTS: |
4631 case EXTERNAL_DOUBLE_ELEMENTS: | 4650 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8400 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 8419 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
8401 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8420 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
8402 PrintF(out, "\n"); | 8421 PrintF(out, "\n"); |
8403 } | 8422 } |
8404 #endif // ENABLE_DISASSEMBLER | 8423 #endif // ENABLE_DISASSEMBLER |
8405 | 8424 |
8406 | 8425 |
8407 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8426 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
8408 int capacity, | 8427 int capacity, |
8409 int length, | 8428 int length, |
8410 SetFastElementsCapacityMode set_capacity_mode) { | 8429 SetFastElementsCapacitySmiMode smi_mode) { |
8411 Heap* heap = GetHeap(); | 8430 Heap* heap = GetHeap(); |
8412 // We should never end in here with a pixel or external array. | 8431 // We should never end in here with a pixel or external array. |
8413 ASSERT(!HasExternalArrayElements()); | 8432 ASSERT(!HasExternalArrayElements()); |
8414 | 8433 |
8415 // Allocate a new fast elements backing store. | 8434 // Allocate a new fast elements backing store. |
8416 FixedArray* new_elements; | 8435 FixedArray* new_elements; |
8417 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 8436 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
8418 if (!maybe->To(&new_elements)) return maybe; | 8437 if (!maybe->To(&new_elements)) return maybe; |
8419 } | 8438 } |
8420 | 8439 |
8421 // Find the new map to use for this object if there is a map change. | 8440 ElementsKind elements_kind = GetElementsKind(); |
8422 Map* new_map = NULL; | 8441 ElementsKind new_elements_kind; |
8423 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 8442 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
8424 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces | 8443 // or if it's allowed and the old elements array contained only SMIs. |
8425 // it, or if it's allowed and the old elements array contained only SMIs. | 8444 bool has_fast_smi_elements = |
8426 bool has_fast_smi_only_elements = | 8445 (smi_mode == kForceSmiElements) || |
8427 (set_capacity_mode == kForceSmiOnlyElements) || | 8446 ((smi_mode == kAllowSmiElements) && HasFastSmiElements()); |
8428 ((set_capacity_mode == kAllowSmiOnlyElements) && | 8447 if (has_fast_smi_elements) { |
8429 (elements()->map()->has_fast_smi_only_elements() || | 8448 if (IsHoleyElementsKind(elements_kind)) { |
8430 elements() == heap->empty_fixed_array())); | 8449 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; |
8431 ElementsKind elements_kind = has_fast_smi_only_elements | 8450 } else { |
8432 ? FAST_SMI_ONLY_ELEMENTS | 8451 new_elements_kind = FAST_SMI_ELEMENTS; |
8433 : FAST_ELEMENTS; | 8452 } |
8434 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | 8453 } else { |
8435 if (!maybe->To(&new_map)) return maybe; | 8454 if (IsHoleyElementsKind(elements_kind)) { |
| 8455 new_elements_kind = FAST_HOLEY_ELEMENTS; |
| 8456 } else { |
| 8457 new_elements_kind = FAST_ELEMENTS; |
| 8458 } |
8436 } | 8459 } |
8437 | |
8438 FixedArrayBase* old_elements = elements(); | 8460 FixedArrayBase* old_elements = elements(); |
8439 ElementsKind elements_kind = GetElementsKind(); | |
8440 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8461 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8441 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) | |
8442 ? FAST_SMI_ONLY_ELEMENTS | |
8443 : FAST_ELEMENTS; | |
8444 { MaybeObject* maybe_obj = | 8462 { MaybeObject* maybe_obj = |
8445 accessor->CopyElements(this, new_elements, to_kind); | 8463 accessor->CopyElements(this, new_elements, new_elements_kind); |
8446 if (maybe_obj->IsFailure()) return maybe_obj; | 8464 if (maybe_obj->IsFailure()) return maybe_obj; |
8447 } | 8465 } |
8448 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8466 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8467 Map* new_map = map(); |
| 8468 if (new_elements_kind != elements_kind) { |
| 8469 MaybeObject* maybe = |
| 8470 GetElementsTransitionMap(GetIsolate(), new_elements_kind); |
| 8471 if (!maybe->To(&new_map)) return maybe; |
| 8472 } |
| 8473 ValidateElements(); |
8449 set_map_and_elements(new_map, new_elements); | 8474 set_map_and_elements(new_map, new_elements); |
8450 } else { | 8475 } else { |
8451 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8476 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8452 parameter_map->set(1, new_elements); | 8477 parameter_map->set(1, new_elements); |
8453 } | 8478 } |
8454 | 8479 |
8455 if (FLAG_trace_elements_transitions) { | 8480 if (FLAG_trace_elements_transitions) { |
8456 PrintElementsTransition(stdout, elements_kind, old_elements, | 8481 PrintElementsTransition(stdout, elements_kind, old_elements, |
8457 GetElementsKind(), new_elements); | 8482 GetElementsKind(), new_elements); |
8458 } | 8483 } |
8459 | 8484 |
8460 // Update the length if necessary. | |
8461 if (IsJSArray()) { | 8485 if (IsJSArray()) { |
8462 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8486 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8463 } | 8487 } |
8464 | |
8465 return new_elements; | 8488 return new_elements; |
8466 } | 8489 } |
8467 | 8490 |
8468 | 8491 |
8469 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8492 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
8470 int capacity, | 8493 int capacity, |
8471 int length) { | 8494 int length) { |
8472 Heap* heap = GetHeap(); | 8495 Heap* heap = GetHeap(); |
8473 // We should never end in here with a pixel or external array. | 8496 // We should never end in here with a pixel or external array. |
8474 ASSERT(!HasExternalArrayElements()); | 8497 ASSERT(!HasExternalArrayElements()); |
8475 | 8498 |
8476 FixedArrayBase* elems; | 8499 FixedArrayBase* elems; |
8477 { MaybeObject* maybe_obj = | 8500 { MaybeObject* maybe_obj = |
8478 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8501 heap->AllocateUninitializedFixedDoubleArray(capacity); |
8479 if (!maybe_obj->To(&elems)) return maybe_obj; | 8502 if (!maybe_obj->To(&elems)) return maybe_obj; |
8480 } | 8503 } |
8481 | 8504 |
| 8505 ElementsKind elements_kind = GetElementsKind(); |
| 8506 ElementsKind new_elements_kind = elements_kind; |
| 8507 if (IsHoleyElementsKind(elements_kind)) { |
| 8508 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; |
| 8509 } else { |
| 8510 new_elements_kind = FAST_DOUBLE_ELEMENTS; |
| 8511 } |
| 8512 |
8482 Map* new_map; | 8513 Map* new_map; |
8483 { MaybeObject* maybe_obj = | 8514 { MaybeObject* maybe_obj = |
8484 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); | 8515 GetElementsTransitionMap(heap->isolate(), new_elements_kind); |
8485 if (!maybe_obj->To(&new_map)) return maybe_obj; | 8516 if (!maybe_obj->To(&new_map)) return maybe_obj; |
8486 } | 8517 } |
8487 | 8518 |
8488 FixedArrayBase* old_elements = elements(); | 8519 FixedArrayBase* old_elements = elements(); |
8489 ElementsKind elements_kind = GetElementsKind(); | |
8490 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8520 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8491 { MaybeObject* maybe_obj = | 8521 { MaybeObject* maybe_obj = |
8492 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); | 8522 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); |
8493 if (maybe_obj->IsFailure()) return maybe_obj; | 8523 if (maybe_obj->IsFailure()) return maybe_obj; |
8494 } | 8524 } |
8495 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8525 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8526 ValidateElements(); |
8496 set_map_and_elements(new_map, elems); | 8527 set_map_and_elements(new_map, elems); |
8497 } else { | 8528 } else { |
8498 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8529 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8499 parameter_map->set(1, elems); | 8530 parameter_map->set(1, elems); |
8500 } | 8531 } |
8501 | 8532 |
8502 if (FLAG_trace_elements_transitions) { | 8533 if (FLAG_trace_elements_transitions) { |
8503 PrintElementsTransition(stdout, elements_kind, old_elements, | 8534 PrintElementsTransition(stdout, elements_kind, old_elements, |
8504 FAST_DOUBLE_ELEMENTS, elems); | 8535 GetElementsKind(), elems); |
8505 } | 8536 } |
8506 | 8537 |
8507 if (IsJSArray()) { | 8538 if (IsJSArray()) { |
8508 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8539 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8509 } | 8540 } |
8510 | 8541 |
8511 return this; | 8542 return this; |
8512 } | 8543 } |
8513 | 8544 |
8514 | 8545 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8774 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8805 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
8775 : UNDEFINED_ELEMENT; | 8806 : UNDEFINED_ELEMENT; |
8776 } | 8807 } |
8777 | 8808 |
8778 // Handle [] on String objects. | 8809 // Handle [] on String objects. |
8779 if (this->IsStringObjectWithCharacterAt(index)) { | 8810 if (this->IsStringObjectWithCharacterAt(index)) { |
8780 return STRING_CHARACTER_ELEMENT; | 8811 return STRING_CHARACTER_ELEMENT; |
8781 } | 8812 } |
8782 | 8813 |
8783 switch (GetElementsKind()) { | 8814 switch (GetElementsKind()) { |
8784 case FAST_SMI_ONLY_ELEMENTS: | 8815 case FAST_SMI_ELEMENTS: |
8785 case FAST_ELEMENTS: { | 8816 case FAST_ELEMENTS: |
| 8817 case FAST_HOLEY_SMI_ELEMENTS: |
| 8818 case FAST_HOLEY_ELEMENTS: { |
8786 uint32_t length = IsJSArray() ? | 8819 uint32_t length = IsJSArray() ? |
8787 static_cast<uint32_t> | 8820 static_cast<uint32_t> |
8788 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8821 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8789 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8822 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
8790 if ((index < length) && | 8823 if ((index < length) && |
8791 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8824 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
8792 return FAST_ELEMENT; | 8825 return FAST_ELEMENT; |
8793 } | 8826 } |
8794 break; | 8827 break; |
8795 } | 8828 } |
8796 case FAST_DOUBLE_ELEMENTS: { | 8829 case FAST_DOUBLE_ELEMENTS: |
| 8830 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
8797 uint32_t length = IsJSArray() ? | 8831 uint32_t length = IsJSArray() ? |
8798 static_cast<uint32_t> | 8832 static_cast<uint32_t> |
8799 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8833 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8800 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
8801 if ((index < length) && | 8835 if ((index < length) && |
8802 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | 8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
8803 return FAST_ELEMENT; | 8837 return FAST_ELEMENT; |
8804 } | 8838 } |
8805 break; | 8839 break; |
8806 } | 8840 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9070 } | 9104 } |
9071 | 9105 |
9072 | 9106 |
9073 // Adding n elements in fast case is O(n*n). | 9107 // Adding n elements in fast case is O(n*n). |
9074 // Note: revisit design to have dual undefined values to capture absent | 9108 // Note: revisit design to have dual undefined values to capture absent |
9075 // elements. | 9109 // elements. |
9076 MaybeObject* JSObject::SetFastElement(uint32_t index, | 9110 MaybeObject* JSObject::SetFastElement(uint32_t index, |
9077 Object* value, | 9111 Object* value, |
9078 StrictModeFlag strict_mode, | 9112 StrictModeFlag strict_mode, |
9079 bool check_prototype) { | 9113 bool check_prototype) { |
9080 ASSERT(HasFastTypeElements() || | 9114 ASSERT(HasFastSmiOrObjectElements() || |
9081 HasFastArgumentsElements()); | 9115 HasFastArgumentsElements()); |
9082 | 9116 |
9083 FixedArray* backing_store = FixedArray::cast(elements()); | 9117 FixedArray* backing_store = FixedArray::cast(elements()); |
9084 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
9085 backing_store = FixedArray::cast(backing_store->get(1)); | 9119 backing_store = FixedArray::cast(backing_store->get(1)); |
9086 } else { | 9120 } else { |
9087 MaybeObject* maybe = EnsureWritableFastElements(); | 9121 MaybeObject* maybe = EnsureWritableFastElements(); |
9088 if (!maybe->To(&backing_store)) return maybe; | 9122 if (!maybe->To(&backing_store)) return maybe; |
9089 } | 9123 } |
9090 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
9091 | 9125 |
9092 if (check_prototype && | 9126 if (check_prototype && |
9093 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 9127 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
9094 bool found; | 9128 bool found; |
9095 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9096 value, | 9130 value, |
9097 &found, | 9131 &found, |
9098 strict_mode); | 9132 strict_mode); |
9099 if (found) return result; | 9133 if (found) return result; |
9100 } | 9134 } |
9101 | 9135 |
9102 uint32_t new_capacity = capacity; | 9136 uint32_t new_capacity = capacity; |
9103 // Check if the length property of this object needs to be updated. | 9137 // Check if the length property of this object needs to be updated. |
9104 uint32_t array_length = 0; | 9138 uint32_t array_length = 0; |
9105 bool must_update_array_length = false; | 9139 bool must_update_array_length = false; |
| 9140 bool introduces_holes = true; |
9106 if (IsJSArray()) { | 9141 if (IsJSArray()) { |
9107 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9142 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 9143 introduces_holes = index > array_length; |
9108 if (index >= array_length) { | 9144 if (index >= array_length) { |
9109 must_update_array_length = true; | 9145 must_update_array_length = true; |
9110 array_length = index + 1; | 9146 array_length = index + 1; |
9111 } | 9147 } |
| 9148 } else { |
| 9149 introduces_holes = index >= capacity; |
9112 } | 9150 } |
| 9151 |
| 9152 // If the array is growing, and it's not growth by a single element at the |
| 9153 // end, make sure that the ElementsKind is HOLEY. |
| 9154 ElementsKind elements_kind = GetElementsKind(); |
| 9155 if (introduces_holes && |
| 9156 IsFastElementsKind(elements_kind) && |
| 9157 !IsFastHoleyElementsKind(elements_kind)) { |
| 9158 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 9159 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); |
| 9160 if (maybe->IsFailure()) return maybe; |
| 9161 } |
| 9162 |
9113 // Check if the capacity of the backing store needs to be increased, or if | 9163 // Check if the capacity of the backing store needs to be increased, or if |
9114 // a transition to slow elements is necessary. | 9164 // a transition to slow elements is necessary. |
9115 if (index >= capacity) { | 9165 if (index >= capacity) { |
9116 bool convert_to_slow = true; | 9166 bool convert_to_slow = true; |
9117 if ((index - capacity) < kMaxGap) { | 9167 if ((index - capacity) < kMaxGap) { |
9118 new_capacity = NewElementsCapacity(index + 1); | 9168 new_capacity = NewElementsCapacity(index + 1); |
9119 ASSERT(new_capacity > index); | 9169 ASSERT(new_capacity > index); |
9120 if (!ShouldConvertToSlowElements(new_capacity)) { | 9170 if (!ShouldConvertToSlowElements(new_capacity)) { |
9121 convert_to_slow = false; | 9171 convert_to_slow = false; |
9122 } | 9172 } |
9123 } | 9173 } |
9124 if (convert_to_slow) { | 9174 if (convert_to_slow) { |
9125 MaybeObject* result = NormalizeElements(); | 9175 MaybeObject* result = NormalizeElements(); |
9126 if (result->IsFailure()) return result; | 9176 if (result->IsFailure()) return result; |
9127 return SetDictionaryElement(index, value, NONE, strict_mode, | 9177 return SetDictionaryElement(index, value, NONE, strict_mode, |
9128 check_prototype); | 9178 check_prototype); |
9129 } | 9179 } |
9130 } | 9180 } |
9131 // Convert to fast double elements if appropriate. | 9181 // Convert to fast double elements if appropriate. |
9132 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { | 9182 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
9133 MaybeObject* maybe = | 9183 MaybeObject* maybe = |
9134 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9184 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
9135 if (maybe->IsFailure()) return maybe; | 9185 if (maybe->IsFailure()) return maybe; |
9136 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9186 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 9187 ValidateElements(); |
9137 return value; | 9188 return value; |
9138 } | 9189 } |
9139 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9190 // Change elements kind from Smi-only to generic FAST if necessary. |
9140 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9191 if (HasFastSmiElements() && !value->IsSmi()) { |
9141 Map* new_map; | 9192 Map* new_map; |
9142 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 9193 ElementsKind kind = HasFastHoleyElements() |
9143 FAST_ELEMENTS); | 9194 ? FAST_HOLEY_ELEMENTS |
9144 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9195 : FAST_ELEMENTS; |
9145 } | 9196 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
| 9197 kind); |
| 9198 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 9199 |
9146 set_map(new_map); | 9200 set_map(new_map); |
9147 if (FLAG_trace_elements_transitions) { | |
9148 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), | |
9149 FAST_ELEMENTS, elements()); | |
9150 } | |
9151 } | 9201 } |
9152 // Increase backing store capacity if that's been decided previously. | 9202 // Increase backing store capacity if that's been decided previously. |
9153 if (new_capacity != capacity) { | 9203 if (new_capacity != capacity) { |
9154 FixedArray* new_elements; | 9204 FixedArray* new_elements; |
9155 SetFastElementsCapacityMode set_capacity_mode = | 9205 SetFastElementsCapacitySmiMode smi_mode = |
9156 value->IsSmi() && HasFastSmiOnlyElements() | 9206 value->IsSmi() && HasFastSmiElements() |
9157 ? kAllowSmiOnlyElements | 9207 ? kAllowSmiElements |
9158 : kDontAllowSmiOnlyElements; | 9208 : kDontAllowSmiElements; |
9159 { MaybeObject* maybe = | 9209 { MaybeObject* maybe = |
9160 SetFastElementsCapacityAndLength(new_capacity, | 9210 SetFastElementsCapacityAndLength(new_capacity, |
9161 array_length, | 9211 array_length, |
9162 set_capacity_mode); | 9212 smi_mode); |
9163 if (!maybe->To(&new_elements)) return maybe; | 9213 if (!maybe->To(&new_elements)) return maybe; |
9164 } | 9214 } |
9165 new_elements->set(index, value); | 9215 new_elements->set(index, value); |
| 9216 ValidateElements(); |
9166 return value; | 9217 return value; |
9167 } | 9218 } |
| 9219 |
9168 // Finally, set the new element and length. | 9220 // Finally, set the new element and length. |
9169 ASSERT(elements()->IsFixedArray()); | 9221 ASSERT(elements()->IsFixedArray()); |
9170 backing_store->set(index, value); | 9222 backing_store->set(index, value); |
9171 if (must_update_array_length) { | 9223 if (must_update_array_length) { |
9172 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 9224 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); |
9173 } | 9225 } |
9174 return value; | 9226 return value; |
9175 } | 9227 } |
9176 | 9228 |
9177 | 9229 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9281 } | 9333 } |
9282 | 9334 |
9283 // Attempt to put this object back in fast case. | 9335 // Attempt to put this object back in fast case. |
9284 if (ShouldConvertToFastElements()) { | 9336 if (ShouldConvertToFastElements()) { |
9285 uint32_t new_length = 0; | 9337 uint32_t new_length = 0; |
9286 if (IsJSArray()) { | 9338 if (IsJSArray()) { |
9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 9339 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
9288 } else { | 9340 } else { |
9289 new_length = dictionary->max_number_key() + 1; | 9341 new_length = dictionary->max_number_key() + 1; |
9290 } | 9342 } |
9291 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays | 9343 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays |
9292 ? kAllowSmiOnlyElements | 9344 ? kAllowSmiElements |
9293 : kDontAllowSmiOnlyElements; | 9345 : kDontAllowSmiElements; |
9294 bool has_smi_only_elements = false; | 9346 bool has_smi_only_elements = false; |
9295 bool should_convert_to_fast_double_elements = | 9347 bool should_convert_to_fast_double_elements = |
9296 ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 9348 ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
9297 if (has_smi_only_elements) { | 9349 if (has_smi_only_elements) { |
9298 set_capacity_mode = kForceSmiOnlyElements; | 9350 smi_mode = kForceSmiElements; |
9299 } | 9351 } |
9300 MaybeObject* result = should_convert_to_fast_double_elements | 9352 MaybeObject* result = should_convert_to_fast_double_elements |
9301 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 9353 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
9302 : SetFastElementsCapacityAndLength(new_length, | 9354 : SetFastElementsCapacityAndLength(new_length, |
9303 new_length, | 9355 new_length, |
9304 set_capacity_mode); | 9356 smi_mode); |
| 9357 ValidateElements(); |
9305 if (result->IsFailure()) return result; | 9358 if (result->IsFailure()) return result; |
9306 #ifdef DEBUG | 9359 #ifdef DEBUG |
9307 if (FLAG_trace_normalization) { | 9360 if (FLAG_trace_normalization) { |
9308 PrintF("Object elements are fast case again:\n"); | 9361 PrintF("Object elements are fast case again:\n"); |
9309 Print(); | 9362 Print(); |
9310 } | 9363 } |
9311 #endif | 9364 #endif |
9312 } | 9365 } |
9313 return value; | 9366 return value; |
9314 } | 9367 } |
(...skipping 18 matching lines...) Expand all Loading... |
9333 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9386 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9334 value, | 9387 value, |
9335 &found, | 9388 &found, |
9336 strict_mode); | 9389 strict_mode); |
9337 if (found) return result; | 9390 if (found) return result; |
9338 } | 9391 } |
9339 | 9392 |
9340 // If the value object is not a heap number, switch to fast elements and try | 9393 // If the value object is not a heap number, switch to fast elements and try |
9341 // again. | 9394 // again. |
9342 bool value_is_smi = value->IsSmi(); | 9395 bool value_is_smi = value->IsSmi(); |
| 9396 bool introduces_holes = true; |
| 9397 uint32_t length = elms_length; |
| 9398 if (IsJSArray()) { |
| 9399 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9400 introduces_holes = index > length; |
| 9401 } else { |
| 9402 introduces_holes = index >= elms_length; |
| 9403 } |
| 9404 |
9343 if (!value->IsNumber()) { | 9405 if (!value->IsNumber()) { |
9344 Object* obj; | |
9345 uint32_t length = elms_length; | |
9346 if (IsJSArray()) { | |
9347 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
9348 } | |
9349 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 9406 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
9350 elms_length, | 9407 elms_length, |
9351 length, | 9408 length, |
9352 kDontAllowSmiOnlyElements); | 9409 kDontAllowSmiElements); |
9353 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9410 if (maybe_obj->IsFailure()) return maybe_obj; |
9354 return SetFastElement(index, | 9411 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); |
9355 value, | 9412 if (maybe_obj->IsFailure()) return maybe_obj; |
9356 strict_mode, | 9413 ValidateElements(); |
9357 check_prototype); | 9414 return maybe_obj; |
9358 } | 9415 } |
9359 | 9416 |
9360 double double_value = value_is_smi | 9417 double double_value = value_is_smi |
9361 ? static_cast<double>(Smi::cast(value)->value()) | 9418 ? static_cast<double>(Smi::cast(value)->value()) |
9362 : HeapNumber::cast(value)->value(); | 9419 : HeapNumber::cast(value)->value(); |
9363 | 9420 |
| 9421 // If the array is growing, and it's not growth by a single element at the |
| 9422 // end, make sure that the ElementsKind is HOLEY. |
| 9423 ElementsKind elements_kind = GetElementsKind(); |
| 9424 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { |
| 9425 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 9426 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); |
| 9427 if (maybe->IsFailure()) return maybe; |
| 9428 } |
| 9429 |
9364 // Check whether there is extra space in the fixed array. | 9430 // Check whether there is extra space in the fixed array. |
9365 if (index < elms_length) { | 9431 if (index < elms_length) { |
9366 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9432 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9367 elms->set(index, double_value); | 9433 elms->set(index, double_value); |
9368 if (IsJSArray()) { | 9434 if (IsJSArray()) { |
9369 // Update the length of the array if needed. | 9435 // Update the length of the array if needed. |
9370 uint32_t array_length = 0; | 9436 uint32_t array_length = 0; |
9371 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9437 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9372 if (index >= array_length) { | 9438 if (index >= array_length) { |
9373 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 9439 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
9374 } | 9440 } |
9375 } | 9441 } |
9376 return value; | 9442 return value; |
9377 } | 9443 } |
9378 | 9444 |
9379 // Allow gap in fast case. | 9445 // Allow gap in fast case. |
9380 if ((index - elms_length) < kMaxGap) { | 9446 if ((index - elms_length) < kMaxGap) { |
9381 // Try allocating extra space. | 9447 // Try allocating extra space. |
9382 int new_capacity = NewElementsCapacity(index+1); | 9448 int new_capacity = NewElementsCapacity(index+1); |
9383 if (!ShouldConvertToSlowElements(new_capacity)) { | 9449 if (!ShouldConvertToSlowElements(new_capacity)) { |
9384 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 9450 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
9385 Object* obj; | 9451 MaybeObject* maybe_obj = |
9386 { MaybeObject* maybe_obj = | 9452 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); |
9387 SetFastDoubleElementsCapacityAndLength(new_capacity, | 9453 if (maybe_obj->IsFailure()) return maybe_obj; |
9388 index + 1); | |
9389 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
9390 } | |
9391 FixedDoubleArray::cast(elements())->set(index, double_value); | 9454 FixedDoubleArray::cast(elements())->set(index, double_value); |
| 9455 ValidateElements(); |
9392 return value; | 9456 return value; |
9393 } | 9457 } |
9394 } | 9458 } |
9395 | 9459 |
9396 // Otherwise default to slow case. | 9460 // Otherwise default to slow case. |
9397 ASSERT(HasFastDoubleElements()); | 9461 ASSERT(HasFastDoubleElements()); |
9398 ASSERT(map()->has_fast_double_elements()); | 9462 ASSERT(map()->has_fast_double_elements()); |
9399 ASSERT(elements()->IsFixedDoubleArray()); | 9463 ASSERT(elements()->IsFixedDoubleArray()); |
9400 Object* obj; | 9464 Object* obj; |
9401 { MaybeObject* maybe_obj = NormalizeElements(); | 9465 { MaybeObject* maybe_obj = NormalizeElements(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9525 Object* value, | 9589 Object* value, |
9526 PropertyAttributes attr, | 9590 PropertyAttributes attr, |
9527 StrictModeFlag strict_mode, | 9591 StrictModeFlag strict_mode, |
9528 bool check_prototype, | 9592 bool check_prototype, |
9529 SetPropertyMode set_mode) { | 9593 SetPropertyMode set_mode) { |
9530 ASSERT(HasDictionaryElements() || | 9594 ASSERT(HasDictionaryElements() || |
9531 HasDictionaryArgumentsElements() || | 9595 HasDictionaryArgumentsElements() || |
9532 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 9596 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
9533 Isolate* isolate = GetIsolate(); | 9597 Isolate* isolate = GetIsolate(); |
9534 switch (GetElementsKind()) { | 9598 switch (GetElementsKind()) { |
9535 case FAST_SMI_ONLY_ELEMENTS: | 9599 case FAST_SMI_ELEMENTS: |
9536 case FAST_ELEMENTS: | 9600 case FAST_ELEMENTS: |
| 9601 case FAST_HOLEY_SMI_ELEMENTS: |
| 9602 case FAST_HOLEY_ELEMENTS: |
9537 return SetFastElement(index, value, strict_mode, check_prototype); | 9603 return SetFastElement(index, value, strict_mode, check_prototype); |
9538 case FAST_DOUBLE_ELEMENTS: | 9604 case FAST_DOUBLE_ELEMENTS: |
| 9605 case FAST_HOLEY_DOUBLE_ELEMENTS: |
9539 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 9606 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
9540 case EXTERNAL_PIXEL_ELEMENTS: { | 9607 case EXTERNAL_PIXEL_ELEMENTS: { |
9541 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9608 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
9542 return pixels->SetValue(index, value); | 9609 return pixels->SetValue(index, value); |
9543 } | 9610 } |
9544 case EXTERNAL_BYTE_ELEMENTS: { | 9611 case EXTERNAL_BYTE_ELEMENTS: { |
9545 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 9612 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
9546 return array->SetValue(index, value); | 9613 return array->SetValue(index, value); |
9547 } | 9614 } |
9548 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 9615 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9619 ElementsKind to_kind) { | 9686 ElementsKind to_kind) { |
9620 CALL_HEAP_FUNCTION(object->GetIsolate(), | 9687 CALL_HEAP_FUNCTION(object->GetIsolate(), |
9621 object->TransitionElementsKind(to_kind), | 9688 object->TransitionElementsKind(to_kind), |
9622 Object); | 9689 Object); |
9623 } | 9690 } |
9624 | 9691 |
9625 | 9692 |
9626 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 9693 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
9627 ElementsKind from_kind = map()->elements_kind(); | 9694 ElementsKind from_kind = map()->elements_kind(); |
9628 | 9695 |
| 9696 if (IsFastHoleyElementsKind(from_kind)) { |
| 9697 to_kind = GetHoleyElementsKind(to_kind); |
| 9698 } |
| 9699 |
9629 Isolate* isolate = GetIsolate(); | 9700 Isolate* isolate = GetIsolate(); |
9630 if ((from_kind == FAST_SMI_ONLY_ELEMENTS || | 9701 if (elements() == isolate->heap()->empty_fixed_array() || |
9631 elements() == isolate->heap()->empty_fixed_array()) && | 9702 (IsFastSmiOrObjectElementsKind(from_kind) && |
9632 to_kind == FAST_ELEMENTS) { | 9703 IsFastSmiOrObjectElementsKind(to_kind)) || |
9633 ASSERT(from_kind != FAST_ELEMENTS); | 9704 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 9705 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 9706 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 9707 // No change is needed to the elements() buffer, the transition |
| 9708 // only requires a map change. |
9634 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 9709 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
9635 Map* new_map; | 9710 Map* new_map; |
9636 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9711 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9637 set_map(new_map); | 9712 set_map(new_map); |
9638 if (FLAG_trace_elements_transitions) { | 9713 if (FLAG_trace_elements_transitions) { |
9639 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9714 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9640 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 9715 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
9641 } | 9716 } |
9642 return this; | 9717 return this; |
9643 } | 9718 } |
9644 | 9719 |
9645 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9720 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9646 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9721 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9647 uint32_t length = capacity; | 9722 uint32_t length = capacity; |
9648 | 9723 |
9649 if (IsJSArray()) { | 9724 if (IsJSArray()) { |
9650 Object* raw_length = JSArray::cast(this)->length(); | 9725 Object* raw_length = JSArray::cast(this)->length(); |
9651 if (raw_length->IsUndefined()) { | 9726 if (raw_length->IsUndefined()) { |
9652 // If length is undefined, then JSArray is being initialized and has no | 9727 // If length is undefined, then JSArray is being initialized and has no |
9653 // elements, assume a length of zero. | 9728 // elements, assume a length of zero. |
9654 length = 0; | 9729 length = 0; |
9655 } else { | 9730 } else { |
9656 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9731 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
9657 } | 9732 } |
9658 } | 9733 } |
9659 | 9734 |
9660 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9735 if (IsFastSmiElementsKind(from_kind) && |
9661 to_kind == FAST_DOUBLE_ELEMENTS) { | 9736 IsFastDoubleElementsKind(to_kind)) { |
9662 MaybeObject* maybe_result = | 9737 MaybeObject* maybe_result = |
9663 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9738 SetFastDoubleElementsCapacityAndLength(capacity, length); |
9664 if (maybe_result->IsFailure()) return maybe_result; | 9739 if (maybe_result->IsFailure()) return maybe_result; |
| 9740 ValidateElements(); |
9665 return this; | 9741 return this; |
9666 } | 9742 } |
9667 | 9743 |
9668 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 9744 if (IsFastDoubleElementsKind(from_kind) && |
| 9745 IsFastObjectElementsKind(to_kind)) { |
9669 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9746 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
9670 capacity, length, kDontAllowSmiOnlyElements); | 9747 capacity, length, kDontAllowSmiElements); |
9671 if (maybe_result->IsFailure()) return maybe_result; | 9748 if (maybe_result->IsFailure()) return maybe_result; |
| 9749 ValidateElements(); |
9672 return this; | 9750 return this; |
9673 } | 9751 } |
9674 | 9752 |
9675 // This method should never be called for any other case than the ones | 9753 // This method should never be called for any other case than the ones |
9676 // handled above. | 9754 // handled above. |
9677 UNREACHABLE(); | 9755 UNREACHABLE(); |
9678 return GetIsolate()->heap()->null_value(); | 9756 return GetIsolate()->heap()->null_value(); |
9679 } | 9757 } |
9680 | 9758 |
9681 | 9759 |
9682 // static | 9760 // static |
9683 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9761 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
9684 ElementsKind to_kind) { | 9762 ElementsKind to_kind) { |
9685 return | 9763 // Transitions can't go backwards. |
9686 (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9764 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
9687 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || | 9765 return false; |
9688 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); | 9766 } |
| 9767 |
| 9768 // Transitions from HOLEY -> PACKED are not allowed. |
| 9769 return !IsFastHoleyElementsKind(from_kind) || |
| 9770 IsFastHoleyElementsKind(to_kind); |
9689 } | 9771 } |
9690 | 9772 |
9691 | 9773 |
9692 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 9774 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
9693 Object* value) { | 9775 Object* value) { |
9694 uint32_t old_len = 0; | 9776 uint32_t old_len = 0; |
9695 CHECK(length()->ToArrayIndex(&old_len)); | 9777 CHECK(length()->ToArrayIndex(&old_len)); |
9696 // Check to see if we need to update the length. For now, we make | 9778 // Check to see if we need to update the length. For now, we make |
9697 // sure that the length stays within 32-bits (unsigned). | 9779 // sure that the length stays within 32-bits (unsigned). |
9698 if (index >= old_len && index != 0xffffffff) { | 9780 if (index >= old_len && index != 0xffffffff) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9769 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 9851 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
9770 backing_store = FixedArray::cast(backing_store_base); | 9852 backing_store = FixedArray::cast(backing_store_base); |
9771 if (backing_store->IsDictionary()) { | 9853 if (backing_store->IsDictionary()) { |
9772 SeededNumberDictionary* dictionary = | 9854 SeededNumberDictionary* dictionary = |
9773 SeededNumberDictionary::cast(backing_store); | 9855 SeededNumberDictionary::cast(backing_store); |
9774 *capacity = dictionary->Capacity(); | 9856 *capacity = dictionary->Capacity(); |
9775 *used = dictionary->NumberOfElements(); | 9857 *used = dictionary->NumberOfElements(); |
9776 break; | 9858 break; |
9777 } | 9859 } |
9778 // Fall through. | 9860 // Fall through. |
9779 case FAST_SMI_ONLY_ELEMENTS: | 9861 case FAST_SMI_ELEMENTS: |
9780 case FAST_ELEMENTS: | 9862 case FAST_ELEMENTS: |
| 9863 case FAST_HOLEY_SMI_ELEMENTS: |
| 9864 case FAST_HOLEY_ELEMENTS: |
9781 backing_store = FixedArray::cast(backing_store_base); | 9865 backing_store = FixedArray::cast(backing_store_base); |
9782 *capacity = backing_store->length(); | 9866 *capacity = backing_store->length(); |
9783 for (int i = 0; i < *capacity; ++i) { | 9867 for (int i = 0; i < *capacity; ++i) { |
9784 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 9868 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
9785 } | 9869 } |
9786 break; | 9870 break; |
9787 case DICTIONARY_ELEMENTS: { | 9871 case DICTIONARY_ELEMENTS: { |
9788 SeededNumberDictionary* dictionary = | 9872 SeededNumberDictionary* dictionary = |
9789 SeededNumberDictionary::cast(FixedArray::cast(elements())); | 9873 SeededNumberDictionary::cast(FixedArray::cast(elements())); |
9790 *capacity = dictionary->Capacity(); | 9874 *capacity = dictionary->Capacity(); |
9791 *used = dictionary->NumberOfElements(); | 9875 *used = dictionary->NumberOfElements(); |
9792 break; | 9876 break; |
9793 } | 9877 } |
9794 case FAST_DOUBLE_ELEMENTS: { | 9878 case FAST_DOUBLE_ELEMENTS: |
| 9879 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
9795 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9880 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9796 *capacity = elms->length(); | 9881 *capacity = elms->length(); |
9797 for (int i = 0; i < *capacity; i++) { | 9882 for (int i = 0; i < *capacity; i++) { |
9798 if (!elms->is_the_hole(i)) ++(*used); | 9883 if (!elms->is_the_hole(i)) ++(*used); |
9799 } | 9884 } |
9800 break; | 9885 break; |
9801 } | 9886 } |
9802 case EXTERNAL_BYTE_ELEMENTS: | 9887 case EXTERNAL_BYTE_ELEMENTS: |
9803 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9888 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
9804 case EXTERNAL_SHORT_ELEMENTS: | 9889 case EXTERNAL_SHORT_ELEMENTS: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10054 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10139 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
10055 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 10140 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
10056 return false; | 10141 return false; |
10057 } | 10142 } |
10058 } | 10143 } |
10059 | 10144 |
10060 // Handle [] on String objects. | 10145 // Handle [] on String objects. |
10061 if (this->IsStringObjectWithCharacterAt(index)) return true; | 10146 if (this->IsStringObjectWithCharacterAt(index)) return true; |
10062 | 10147 |
10063 switch (GetElementsKind()) { | 10148 switch (GetElementsKind()) { |
10064 case FAST_SMI_ONLY_ELEMENTS: | 10149 case FAST_SMI_ELEMENTS: |
10065 case FAST_ELEMENTS: { | 10150 case FAST_ELEMENTS: |
10066 uint32_t length = IsJSArray() ? | 10151 case FAST_HOLEY_SMI_ELEMENTS: |
| 10152 case FAST_HOLEY_ELEMENTS: { |
| 10153 uint32_t length = IsJSArray() ? |
10067 static_cast<uint32_t>( | 10154 static_cast<uint32_t>( |
10068 Smi::cast(JSArray::cast(this)->length())->value()) : | 10155 Smi::cast(JSArray::cast(this)->length())->value()) : |
10069 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10156 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10070 return (index < length) && | 10157 return (index < length) && |
10071 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 10158 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
10072 } | 10159 } |
10073 case FAST_DOUBLE_ELEMENTS: { | 10160 case FAST_DOUBLE_ELEMENTS: |
| 10161 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
10074 uint32_t length = IsJSArray() ? | 10162 uint32_t length = IsJSArray() ? |
10075 static_cast<uint32_t>( | 10163 static_cast<uint32_t>( |
10076 Smi::cast(JSArray::cast(this)->length())->value()) : | 10164 Smi::cast(JSArray::cast(this)->length())->value()) : |
10077 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 10165 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
10078 return (index < length) && | 10166 return (index < length) && |
10079 !FixedDoubleArray::cast(elements())->is_the_hole(index); | 10167 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
10080 break; | 10168 break; |
10081 } | 10169 } |
10082 case EXTERNAL_PIXEL_ELEMENTS: { | 10170 case EXTERNAL_PIXEL_ELEMENTS: { |
10083 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 10171 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10263 } | 10351 } |
10264 | 10352 |
10265 | 10353 |
10266 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 10354 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
10267 return GetLocalElementKeys(NULL, filter); | 10355 return GetLocalElementKeys(NULL, filter); |
10268 } | 10356 } |
10269 | 10357 |
10270 | 10358 |
10271 int JSObject::NumberOfEnumElements() { | 10359 int JSObject::NumberOfEnumElements() { |
10272 // Fast case for objects with no elements. | 10360 // Fast case for objects with no elements. |
10273 if (!IsJSValue() && HasFastElements()) { | 10361 if (!IsJSValue() && HasFastObjectElements()) { |
10274 uint32_t length = IsJSArray() ? | 10362 uint32_t length = IsJSArray() ? |
10275 static_cast<uint32_t>( | 10363 static_cast<uint32_t>( |
10276 Smi::cast(JSArray::cast(this)->length())->value()) : | 10364 Smi::cast(JSArray::cast(this)->length())->value()) : |
10277 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10365 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10278 if (length == 0) return 0; | 10366 if (length == 0) return 0; |
10279 } | 10367 } |
10280 // Compute the number of enumerable elements. | 10368 // Compute the number of enumerable elements. |
10281 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 10369 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
10282 } | 10370 } |
10283 | 10371 |
10284 | 10372 |
10285 int JSObject::GetLocalElementKeys(FixedArray* storage, | 10373 int JSObject::GetLocalElementKeys(FixedArray* storage, |
10286 PropertyAttributes filter) { | 10374 PropertyAttributes filter) { |
10287 int counter = 0; | 10375 int counter = 0; |
10288 switch (GetElementsKind()) { | 10376 switch (GetElementsKind()) { |
10289 case FAST_SMI_ONLY_ELEMENTS: | 10377 case FAST_SMI_ELEMENTS: |
10290 case FAST_ELEMENTS: { | 10378 case FAST_ELEMENTS: |
| 10379 case FAST_HOLEY_SMI_ELEMENTS: |
| 10380 case FAST_HOLEY_ELEMENTS: { |
10291 int length = IsJSArray() ? | 10381 int length = IsJSArray() ? |
10292 Smi::cast(JSArray::cast(this)->length())->value() : | 10382 Smi::cast(JSArray::cast(this)->length())->value() : |
10293 FixedArray::cast(elements())->length(); | 10383 FixedArray::cast(elements())->length(); |
10294 for (int i = 0; i < length; i++) { | 10384 for (int i = 0; i < length; i++) { |
10295 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 10385 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
10296 if (storage != NULL) { | 10386 if (storage != NULL) { |
10297 storage->set(counter, Smi::FromInt(i)); | 10387 storage->set(counter, Smi::FromInt(i)); |
10298 } | 10388 } |
10299 counter++; | 10389 counter++; |
10300 } | 10390 } |
10301 } | 10391 } |
10302 ASSERT(!storage || storage->length() >= counter); | 10392 ASSERT(!storage || storage->length() >= counter); |
10303 break; | 10393 break; |
10304 } | 10394 } |
10305 case FAST_DOUBLE_ELEMENTS: { | 10395 case FAST_DOUBLE_ELEMENTS: |
| 10396 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
10306 int length = IsJSArray() ? | 10397 int length = IsJSArray() ? |
10307 Smi::cast(JSArray::cast(this)->length())->value() : | 10398 Smi::cast(JSArray::cast(this)->length())->value() : |
10308 FixedDoubleArray::cast(elements())->length(); | 10399 FixedDoubleArray::cast(elements())->length(); |
10309 for (int i = 0; i < length; i++) { | 10400 for (int i = 0; i < length; i++) { |
10310 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 10401 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
10311 if (storage != NULL) { | 10402 if (storage != NULL) { |
10312 storage->set(counter, Smi::FromInt(i)); | 10403 storage->set(counter, Smi::FromInt(i)); |
10313 } | 10404 } |
10314 counter++; | 10405 counter++; |
10315 } | 10406 } |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11228 // Convert to fast elements containing only the existing properties. | 11319 // Convert to fast elements containing only the existing properties. |
11229 // Ordering is irrelevant, since we are going to sort anyway. | 11320 // Ordering is irrelevant, since we are going to sort anyway. |
11230 SeededNumberDictionary* dict = element_dictionary(); | 11321 SeededNumberDictionary* dict = element_dictionary(); |
11231 if (IsJSArray() || dict->requires_slow_elements() || | 11322 if (IsJSArray() || dict->requires_slow_elements() || |
11232 dict->max_number_key() >= limit) { | 11323 dict->max_number_key() >= limit) { |
11233 return PrepareSlowElementsForSort(limit); | 11324 return PrepareSlowElementsForSort(limit); |
11234 } | 11325 } |
11235 // Convert to fast elements. | 11326 // Convert to fast elements. |
11236 | 11327 |
11237 Object* obj; | 11328 Object* obj; |
11238 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 11329 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
11239 FAST_ELEMENTS); | 11330 FAST_HOLEY_ELEMENTS); |
11240 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11331 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11241 } | |
11242 Map* new_map = Map::cast(obj); | 11332 Map* new_map = Map::cast(obj); |
11243 | 11333 |
11244 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 11334 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
11245 Object* new_array; | 11335 Object* new_array; |
11246 { MaybeObject* maybe_new_array = | 11336 { MaybeObject* maybe_new_array = |
11247 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 11337 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
11248 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 11338 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
11249 } | 11339 } |
11250 FixedArray* fast_elements = FixedArray::cast(new_array); | 11340 FixedArray* fast_elements = FixedArray::cast(new_array); |
11251 dict->CopyValuesTo(fast_elements); | 11341 dict->CopyValuesTo(fast_elements); |
| 11342 ValidateElements(); |
11252 | 11343 |
11253 set_map(new_map); | 11344 set_map_and_elements(new_map, fast_elements); |
11254 set_elements(fast_elements); | |
11255 } else if (HasExternalArrayElements()) { | 11345 } else if (HasExternalArrayElements()) { |
11256 // External arrays cannot have holes or undefined elements. | 11346 // External arrays cannot have holes or undefined elements. |
11257 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 11347 return Smi::FromInt(ExternalArray::cast(elements())->length()); |
11258 } else if (!HasFastDoubleElements()) { | 11348 } else if (!HasFastDoubleElements()) { |
11259 Object* obj; | 11349 Object* obj; |
11260 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 11350 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
11261 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11351 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11262 } | 11352 } |
11263 } | 11353 } |
11264 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); | 11354 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); |
11265 | 11355 |
11266 // Collect holes at the end, undefined before that and the rest at the | 11356 // Collect holes at the end, undefined before that and the rest at the |
11267 // start, and return the number of non-hole, non-undefined values. | 11357 // start, and return the number of non-hole, non-undefined values. |
11268 | 11358 |
11269 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 11359 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
11270 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 11360 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
11271 if (limit > elements_length) { | 11361 if (limit > elements_length) { |
11272 limit = elements_length ; | 11362 limit = elements_length ; |
11273 } | 11363 } |
11274 if (limit == 0) { | 11364 if (limit == 0) { |
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13021 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13022 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13023 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13024 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13025 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13026 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13027 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
12938 } | 13028 } |
12939 | 13029 |
12940 } } // namespace v8::internal | 13030 } } // namespace v8::internal |
OLD | NEW |