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 |
59 | 64 |
60 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
61 Object* value) { | 66 Object* value) { |
62 Object* result; | 67 Object* result; |
63 { MaybeObject* maybe_result = | 68 { MaybeObject* maybe_result = |
64 constructor->GetHeap()->AllocateJSObject(constructor); | 69 constructor->GetHeap()->AllocateJSObject(constructor); |
65 if (!maybe_result->ToObject(&result)) return maybe_result; | 70 if (!maybe_result->ToObject(&result)) return maybe_result; |
66 } | 71 } |
67 JSValue::cast(result)->set_value(value); | 72 JSValue::cast(result)->set_value(value); |
68 return result; | 73 return result; |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 bool JSObject::IsDirty() { | 536 bool JSObject::IsDirty() { |
532 Object* cons_obj = map()->constructor(); | 537 Object* cons_obj = map()->constructor(); |
533 if (!cons_obj->IsJSFunction()) | 538 if (!cons_obj->IsJSFunction()) |
534 return true; | 539 return true; |
535 JSFunction* fun = JSFunction::cast(cons_obj); | 540 JSFunction* fun = JSFunction::cast(cons_obj); |
536 if (!fun->shared()->IsApiFunction()) | 541 if (!fun->shared()->IsApiFunction()) |
537 return true; | 542 return true; |
538 // If the object is fully fast case and has the same map it was | 543 // If the object is fully fast case and has the same map it was |
539 // created with then no changes can have been made to it. | 544 // created with then no changes can have been made to it. |
540 return map() != fun->initial_map() | 545 return map() != fun->initial_map() |
541 || !HasFastObjectElements() | 546 || !HasFastElements() |
542 || !HasFastProperties(); | 547 || !HasFastProperties(); |
543 } | 548 } |
544 | 549 |
545 | 550 |
546 Handle<Object> Object::GetProperty(Handle<Object> object, | 551 Handle<Object> Object::GetProperty(Handle<Object> object, |
547 Handle<Object> receiver, | 552 Handle<Object> receiver, |
548 LookupResult* result, | 553 LookupResult* result, |
549 Handle<String> key, | 554 Handle<String> key, |
550 PropertyAttributes* attributes) { | 555 PropertyAttributes* attributes) { |
551 Isolate* isolate = object->IsHeapObject() | 556 Isolate* isolate = object->IsHeapObject() |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 } | 1060 } |
1056 accumulator->Put('>'); | 1061 accumulator->Put('>'); |
1057 } | 1062 } |
1058 return; | 1063 return; |
1059 } | 1064 } |
1060 | 1065 |
1061 | 1066 |
1062 void JSObject::JSObjectShortPrint(StringStream* accumulator) { | 1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) { |
1063 switch (map()->instance_type()) { | 1068 switch (map()->instance_type()) { |
1064 case JS_ARRAY_TYPE: { | 1069 case JS_ARRAY_TYPE: { |
1065 double length = JSArray::cast(this)->length()->IsUndefined() | 1070 double length = JSArray::cast(this)->length()->Number(); |
1066 ? 0 | |
1067 : JSArray::cast(this)->length()->Number(); | |
1068 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); | 1071 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); |
1069 break; | 1072 break; |
1070 } | 1073 } |
1071 case JS_WEAK_MAP_TYPE: { | 1074 case JS_WEAK_MAP_TYPE: { |
1072 accumulator->Add("<JS WeakMap>"); | 1075 accumulator->Add("<JS WeakMap>"); |
1073 break; | 1076 break; |
1074 } | 1077 } |
1075 case JS_REGEXP_TYPE: { | 1078 case JS_REGEXP_TYPE: { |
1076 accumulator->Add("<JS RegExp>"); | 1079 accumulator->Add("<JS RegExp>"); |
1077 break; | 1080 break; |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2192 | 2195 |
2193 | 2196 |
2194 template <class T> | 2197 template <class T> |
2195 static Handle<T> MaybeNull(T* p) { | 2198 static Handle<T> MaybeNull(T* p) { |
2196 if (p == NULL) return Handle<T>::null(); | 2199 if (p == NULL) return Handle<T>::null(); |
2197 return Handle<T>(p); | 2200 return Handle<T>(p); |
2198 } | 2201 } |
2199 | 2202 |
2200 | 2203 |
2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { | 2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
2202 ElementsKind kind = elements_kind(); | 2205 ElementsKind elms_kind = elements_kind(); |
2203 Handle<Map> transitioned_map = Handle<Map>::null(); | 2206 if (elms_kind == FAST_DOUBLE_ELEMENTS) { |
2204 Handle<Map> current_map(this); | 2207 bool dummy = true; |
2205 bool packed = IsFastPackedElementsKind(kind); | 2208 Handle<Map> fast_map = |
2206 if (IsTransitionableFastElementsKind(kind)) { | 2209 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); |
2207 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { | 2210 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { |
2208 kind = GetNextMoreGeneralFastElementsKind(kind, false); | 2211 return fast_map; |
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; | |
2219 } | 2212 } |
| 2213 return Handle<Map>::null(); |
2220 } | 2214 } |
2221 return transitioned_map; | 2215 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 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(); |
2222 } | 2231 } |
2223 | 2232 |
2224 | |
2225 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | 2233 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
2226 ElementsKind elements_kind) { | 2234 ElementsKind elements_kind) { |
2227 if (descriptor_contents->IsMap()) { | 2235 if (descriptor_contents->IsMap()) { |
2228 Map* map = Map::cast(descriptor_contents); | 2236 Map* map = Map::cast(descriptor_contents); |
2229 if (map->elements_kind() == elements_kind) { | 2237 if (map->elements_kind() == elements_kind) { |
2230 return map; | 2238 return map; |
2231 } | 2239 } |
2232 return NULL; | 2240 return NULL; |
2233 } | 2241 } |
2234 | 2242 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2323 } else { | 2331 } else { |
2324 if (safe_to_add_transition != NULL) { | 2332 if (safe_to_add_transition != NULL) { |
2325 *safe_to_add_transition = false; | 2333 *safe_to_add_transition = false; |
2326 } | 2334 } |
2327 } | 2335 } |
2328 } | 2336 } |
2329 return NULL; | 2337 return NULL; |
2330 } | 2338 } |
2331 | 2339 |
2332 | 2340 |
2333 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, | 2341 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, |
2334 bool* safe_to_add_transition) { | 2342 bool* safe_to_add_transition) { |
2335 ElementsKind from_kind = elements_kind(); | 2343 // Special case: indirect SMI->FAST transition (cf. comment in |
2336 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { | 2344 // AddElementsTransition()). |
2337 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { | 2345 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && |
2338 if (safe_to_add_transition) *safe_to_add_transition = false; | 2346 elements_kind == FAST_ELEMENTS) { |
2339 return NULL; | 2347 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, |
2340 } | 2348 safe_to_add_transition); |
2341 ElementsKind transitioned_from_kind = | 2349 if (double_map == NULL) return double_map; |
2342 GetNextMoreGeneralFastElementsKind(from_kind, false); | 2350 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, |
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, | |
2354 safe_to_add_transition); | 2351 safe_to_add_transition); |
2355 } | |
2356 } | 2352 } |
2357 Object* descriptor_contents = GetDescriptorContents( | 2353 Object* descriptor_contents = GetDescriptorContents( |
2358 elements_transition_sentinel_name(), safe_to_add_transition); | 2354 elements_transition_sentinel_name(), safe_to_add_transition); |
2359 if (descriptor_contents != NULL) { | 2355 if (descriptor_contents != NULL) { |
2360 Map* maybe_transition_map = | 2356 Map* maybe_transition_map = |
2361 GetElementsTransitionMapFromDescriptor(descriptor_contents, | 2357 GetElementsTransitionMapFromDescriptor(descriptor_contents, |
2362 to_kind); | 2358 elements_kind); |
2363 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); | 2359 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); |
2364 return maybe_transition_map; | 2360 return maybe_transition_map; |
2365 } | 2361 } |
2366 return NULL; | 2362 return NULL; |
2367 } | 2363 } |
2368 | 2364 |
2369 | 2365 |
2370 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, | 2366 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, |
2371 Map* transitioned_map) { | 2367 Map* transitioned_map) { |
2372 ElementsKind from_kind = elements_kind(); | 2368 // The map transition graph should be a tree, therefore the transition |
2373 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { | 2369 // from SMI to FAST elements is not done directly, but by going through |
2374 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); | 2370 // DOUBLE elements first. |
2375 ElementsKind transitioned_from_kind = | 2371 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && |
2376 GetNextMoreGeneralFastElementsKind(from_kind, false); | 2372 elements_kind == FAST_ELEMENTS) { |
2377 // The map transitions graph should be a tree, therefore transitions to | 2373 bool safe_to_add = true; |
2378 // ElementsKind that are not adjacent in the ElementsKind sequence are not | 2374 Map* double_map = this->LookupElementsTransitionMap( |
2379 // done directly, but instead by going through intermediate ElementsKinds | 2375 FAST_DOUBLE_ELEMENTS, &safe_to_add); |
2380 // first. | 2376 // This method is only called when safe_to_add_transition has been found |
2381 if (to_kind != transitioned_from_kind) { | 2377 // to be true earlier. |
2382 bool safe_to_add = true; | 2378 ASSERT(safe_to_add); |
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); | |
2388 | 2379 |
2389 if (intermediate_map == NULL) { | 2380 if (double_map == NULL) { |
2390 MaybeObject* maybe_map = CopyDropTransitions(); | 2381 MaybeObject* maybe_map = this->CopyDropTransitions(); |
2391 if (!maybe_map->To(&intermediate_map)) return maybe_map; | 2382 if (!maybe_map->To(&double_map)) return maybe_map; |
2392 intermediate_map->set_elements_kind(transitioned_from_kind); | 2383 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); |
2393 MaybeObject* maybe_transition = AddElementsTransition( | 2384 MaybeObject* maybe_double_transition = this->AddElementsTransition( |
2394 transitioned_from_kind, intermediate_map); | 2385 FAST_DOUBLE_ELEMENTS, double_map); |
2395 if (maybe_transition->IsFailure()) return maybe_transition; | 2386 if (maybe_double_transition->IsFailure()) return maybe_double_transition; |
2396 } | |
2397 return intermediate_map->AddElementsTransition(to_kind, transitioned_map); | |
2398 } | 2387 } |
| 2388 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map); |
2399 } | 2389 } |
2400 | 2390 |
2401 bool safe_to_add_transition = true; | 2391 bool safe_to_add_transition = true; |
2402 Object* descriptor_contents = GetDescriptorContents( | 2392 Object* descriptor_contents = GetDescriptorContents( |
2403 elements_transition_sentinel_name(), &safe_to_add_transition); | 2393 elements_transition_sentinel_name(), &safe_to_add_transition); |
2404 // This method is only called when safe_to_add_transition has been found | 2394 // This method is only called when safe_to_add_transition has been found |
2405 // to be true earlier. | 2395 // to be true earlier. |
2406 ASSERT(safe_to_add_transition); | 2396 ASSERT(safe_to_add_transition); |
2407 MaybeObject* maybe_new_contents = | 2397 MaybeObject* maybe_new_contents = |
2408 AddElementsTransitionMapToDescriptor(descriptor_contents, | 2398 AddElementsTransitionMapToDescriptor(descriptor_contents, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2440 ElementsKind from_kind = current_map->elements_kind(); | 2430 ElementsKind from_kind = current_map->elements_kind(); |
2441 | 2431 |
2442 if (from_kind == to_kind) return current_map; | 2432 if (from_kind == to_kind) return current_map; |
2443 | 2433 |
2444 // Only objects with FastProperties can have DescriptorArrays and can track | 2434 // Only objects with FastProperties can have DescriptorArrays and can track |
2445 // element-related maps. Also don't add descriptors to maps that are shared. | 2435 // element-related maps. Also don't add descriptors to maps that are shared. |
2446 bool safe_to_add_transition = HasFastProperties() && | 2436 bool safe_to_add_transition = HasFastProperties() && |
2447 !current_map->IsUndefined() && | 2437 !current_map->IsUndefined() && |
2448 !current_map->is_shared(); | 2438 !current_map->is_shared(); |
2449 | 2439 |
2450 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects | 2440 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects |
2451 // with elements that switch back and forth between dictionary and fast | 2441 // with elements that switch back and forth between dictionary and fast |
2452 // element modes. | 2442 // element mode. |
2453 if (from_kind == DICTIONARY_ELEMENTS && | 2443 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { |
2454 IsFastElementsKind(to_kind)) { | |
2455 safe_to_add_transition = false; | 2444 safe_to_add_transition = false; |
2456 } | 2445 } |
2457 | 2446 |
2458 if (safe_to_add_transition) { | 2447 if (safe_to_add_transition) { |
2459 // It's only safe to manipulate the descriptor array if it would be | 2448 // It's only safe to manipulate the descriptor array if it would be |
2460 // safe to add a transition. | 2449 // safe to add a transition. |
2461 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( | 2450 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( |
2462 to_kind, &safe_to_add_transition); | 2451 to_kind, &safe_to_add_transition); |
2463 if (maybe_transition_map != NULL) { | 2452 if (maybe_transition_map != NULL) { |
2464 return maybe_transition_map; | 2453 return maybe_transition_map; |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3480 // Find the backing store. | 3469 // Find the backing store. |
3481 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 3470 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
3482 Map* old_map = array->map(); | 3471 Map* old_map = array->map(); |
3483 bool is_arguments = | 3472 bool is_arguments = |
3484 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 3473 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
3485 if (is_arguments) { | 3474 if (is_arguments) { |
3486 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 3475 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
3487 } | 3476 } |
3488 if (array->IsDictionary()) return array; | 3477 if (array->IsDictionary()) return array; |
3489 | 3478 |
3490 ASSERT(HasFastSmiOrObjectElements() || | 3479 ASSERT(HasFastElements() || |
| 3480 HasFastSmiOnlyElements() || |
3491 HasFastDoubleElements() || | 3481 HasFastDoubleElements() || |
3492 HasFastArgumentsElements()); | 3482 HasFastArgumentsElements()); |
3493 // Compute the effective length and allocate a new backing store. | 3483 // Compute the effective length and allocate a new backing store. |
3494 int length = IsJSArray() | 3484 int length = IsJSArray() |
3495 ? Smi::cast(JSArray::cast(this)->length())->value() | 3485 ? Smi::cast(JSArray::cast(this)->length())->value() |
3496 : array->length(); | 3486 : array->length(); |
3497 int old_capacity = 0; | 3487 int old_capacity = 0; |
3498 int used_elements = 0; | 3488 int used_elements = 0; |
3499 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 3489 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
3500 SeededNumberDictionary* dictionary = NULL; | 3490 SeededNumberDictionary* dictionary = NULL; |
(...skipping 14 matching lines...) Expand all Loading... |
3515 } else { | 3505 } else { |
3516 // Objects must be allocated in the old object space, since the | 3506 // Objects must be allocated in the old object space, since the |
3517 // overall number of HeapNumbers needed for the conversion might | 3507 // overall number of HeapNumbers needed for the conversion might |
3518 // exceed the capacity of new space, and we would fail repeatedly | 3508 // exceed the capacity of new space, and we would fail repeatedly |
3519 // trying to convert the FixedDoubleArray. | 3509 // trying to convert the FixedDoubleArray. |
3520 MaybeObject* maybe_value_object = | 3510 MaybeObject* maybe_value_object = |
3521 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 3511 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
3522 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 3512 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
3523 } | 3513 } |
3524 } else { | 3514 } else { |
3525 ASSERT(old_map->has_fast_smi_or_object_elements()); | 3515 ASSERT(old_map->has_fast_elements() || |
| 3516 old_map->has_fast_smi_only_elements()); |
3526 value = FixedArray::cast(array)->get(i); | 3517 value = FixedArray::cast(array)->get(i); |
3527 } | 3518 } |
3528 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 3519 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
3529 if (!value->IsTheHole()) { | 3520 if (!value->IsTheHole()) { |
3530 Object* result; | 3521 Object* result; |
3531 MaybeObject* maybe_result = | 3522 MaybeObject* maybe_result = |
3532 dictionary->AddNumberEntry(i, value, details); | 3523 dictionary->AddNumberEntry(i, value, details); |
3533 if (!maybe_result->ToObject(&result)) return maybe_result; | 3524 if (!maybe_result->ToObject(&result)) return maybe_result; |
3534 dictionary = SeededNumberDictionary::cast(result); | 3525 dictionary = SeededNumberDictionary::cast(result); |
3535 } | 3526 } |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4002 if (IsJSProxy()) { | 3993 if (IsJSProxy()) { |
4003 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); | 3994 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
4004 } | 3995 } |
4005 return JSObject::cast(this)->DeleteProperty(name, mode); | 3996 return JSObject::cast(this)->DeleteProperty(name, mode); |
4006 } | 3997 } |
4007 | 3998 |
4008 | 3999 |
4009 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 4000 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
4010 ElementsKind kind, | 4001 ElementsKind kind, |
4011 Object* object) { | 4002 Object* object) { |
4012 ASSERT(IsFastObjectElementsKind(kind) || | 4003 ASSERT(kind == FAST_ELEMENTS || |
4013 kind == DICTIONARY_ELEMENTS); | 4004 kind == DICTIONARY_ELEMENTS); |
4014 if (IsFastObjectElementsKind(kind)) { | 4005 if (kind == FAST_ELEMENTS) { |
4015 int length = IsJSArray() | 4006 int length = IsJSArray() |
4016 ? Smi::cast(JSArray::cast(this)->length())->value() | 4007 ? Smi::cast(JSArray::cast(this)->length())->value() |
4017 : elements->length(); | 4008 : elements->length(); |
4018 for (int i = 0; i < length; ++i) { | 4009 for (int i = 0; i < length; ++i) { |
4019 Object* element = elements->get(i); | 4010 Object* element = elements->get(i); |
4020 if (!element->IsTheHole() && element == object) return true; | 4011 if (!element->IsTheHole() && element == object) return true; |
4021 } | 4012 } |
4022 } else { | 4013 } else { |
4023 Object* key = | 4014 Object* key = |
4024 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); | 4015 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4056 case EXTERNAL_PIXEL_ELEMENTS: | 4047 case EXTERNAL_PIXEL_ELEMENTS: |
4057 case EXTERNAL_BYTE_ELEMENTS: | 4048 case EXTERNAL_BYTE_ELEMENTS: |
4058 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4059 case EXTERNAL_SHORT_ELEMENTS: | 4050 case EXTERNAL_SHORT_ELEMENTS: |
4060 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4061 case EXTERNAL_INT_ELEMENTS: | 4052 case EXTERNAL_INT_ELEMENTS: |
4062 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4053 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4063 case EXTERNAL_FLOAT_ELEMENTS: | 4054 case EXTERNAL_FLOAT_ELEMENTS: |
4064 case EXTERNAL_DOUBLE_ELEMENTS: | 4055 case EXTERNAL_DOUBLE_ELEMENTS: |
4065 case FAST_DOUBLE_ELEMENTS: | 4056 case FAST_DOUBLE_ELEMENTS: |
4066 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4067 // Raw pixels and external arrays do not reference other | 4057 // Raw pixels and external arrays do not reference other |
4068 // objects. | 4058 // objects. |
4069 break; | 4059 break; |
4070 case FAST_SMI_ELEMENTS: | 4060 case FAST_SMI_ONLY_ELEMENTS: |
4071 case FAST_HOLEY_SMI_ELEMENTS: | |
4072 break; | 4061 break; |
4073 case FAST_ELEMENTS: | 4062 case FAST_ELEMENTS: |
4074 case FAST_HOLEY_ELEMENTS: | |
4075 case DICTIONARY_ELEMENTS: { | 4063 case DICTIONARY_ELEMENTS: { |
4076 FixedArray* elements = FixedArray::cast(this->elements()); | 4064 FixedArray* elements = FixedArray::cast(this->elements()); |
4077 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 4065 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
4078 break; | 4066 break; |
4079 } | 4067 } |
4080 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 4068 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
4081 FixedArray* parameter_map = FixedArray::cast(elements()); | 4069 FixedArray* parameter_map = FixedArray::cast(elements()); |
4082 // Check the mapped parameters. | 4070 // Check the mapped parameters. |
4083 int length = parameter_map->length(); | 4071 int length = parameter_map->length(); |
4084 for (int i = 2; i < length; ++i) { | 4072 for (int i = 2; i < length; ++i) { |
4085 Object* value = parameter_map->get(i); | 4073 Object* value = parameter_map->get(i); |
4086 if (!value->IsTheHole() && value == obj) return true; | 4074 if (!value->IsTheHole() && value == obj) return true; |
4087 } | 4075 } |
4088 // Check the arguments. | 4076 // Check the arguments. |
4089 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 4077 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
4090 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : | 4078 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; |
4091 FAST_HOLEY_ELEMENTS; | |
4092 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 4079 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
4093 break; | 4080 break; |
4094 } | 4081 } |
4095 } | 4082 } |
4096 | 4083 |
4097 // For functions check the context. | 4084 // For functions check the context. |
4098 if (IsJSFunction()) { | 4085 if (IsJSFunction()) { |
4099 // Get the constructor function for arguments array. | 4086 // Get the constructor function for arguments array. |
4100 JSObject* arguments_boilerplate = | 4087 JSObject* arguments_boilerplate = |
4101 heap->isolate()->context()->global_context()-> | 4088 heap->isolate()->context()->global_context()-> |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4315 for (Object* current = this; | 4302 for (Object* current = this; |
4316 current != heap->null_value(); | 4303 current != heap->null_value(); |
4317 current = JSObject::cast(current)->GetPrototype()) { | 4304 current = JSObject::cast(current)->GetPrototype()) { |
4318 JSReceiver::cast(current)->LocalLookup(name, result); | 4305 JSReceiver::cast(current)->LocalLookup(name, result); |
4319 if (result->IsProperty()) return; | 4306 if (result->IsProperty()) return; |
4320 } | 4307 } |
4321 result->NotFound(); | 4308 result->NotFound(); |
4322 } | 4309 } |
4323 | 4310 |
4324 | 4311 |
4325 // Search object and its prototype chain for callback properties. | 4312 // Search object and it's prototype chain for callback properties. |
4326 void JSObject::LookupCallback(String* name, LookupResult* result) { | 4313 void JSObject::LookupCallback(String* name, LookupResult* result) { |
4327 Heap* heap = GetHeap(); | 4314 Heap* heap = GetHeap(); |
4328 for (Object* current = this; | 4315 for (Object* current = this; |
4329 current != heap->null_value() && current->IsJSObject(); | 4316 current != heap->null_value() && current->IsJSObject(); |
4330 current = JSObject::cast(current)->GetPrototype()) { | 4317 current = JSObject::cast(current)->GetPrototype()) { |
4331 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4318 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
4332 if (result->IsFound() && result->type() == CALLBACKS) return; | 4319 if (result->IsFound() && result->type() == CALLBACKS) return; |
4333 } | 4320 } |
4334 result->NotFound(); | 4321 result->NotFound(); |
4335 } | 4322 } |
(...skipping 23 matching lines...) Expand all Loading... |
4359 } | 4346 } |
4360 return false; | 4347 return false; |
4361 } | 4348 } |
4362 | 4349 |
4363 | 4350 |
4364 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 4351 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, |
4365 Object* getter, | 4352 Object* getter, |
4366 Object* setter, | 4353 Object* setter, |
4367 PropertyAttributes attributes) { | 4354 PropertyAttributes attributes) { |
4368 switch (GetElementsKind()) { | 4355 switch (GetElementsKind()) { |
4369 case FAST_SMI_ELEMENTS: | 4356 case FAST_SMI_ONLY_ELEMENTS: |
4370 case FAST_ELEMENTS: | 4357 case FAST_ELEMENTS: |
4371 case FAST_DOUBLE_ELEMENTS: | 4358 case FAST_DOUBLE_ELEMENTS: |
4372 case FAST_HOLEY_SMI_ELEMENTS: | |
4373 case FAST_HOLEY_ELEMENTS: | |
4374 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4375 break; | 4359 break; |
4376 case EXTERNAL_PIXEL_ELEMENTS: | 4360 case EXTERNAL_PIXEL_ELEMENTS: |
4377 case EXTERNAL_BYTE_ELEMENTS: | 4361 case EXTERNAL_BYTE_ELEMENTS: |
4378 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4362 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4379 case EXTERNAL_SHORT_ELEMENTS: | 4363 case EXTERNAL_SHORT_ELEMENTS: |
4380 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4364 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4381 case EXTERNAL_INT_ELEMENTS: | 4365 case EXTERNAL_INT_ELEMENTS: |
4382 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4366 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4383 case EXTERNAL_FLOAT_ELEMENTS: | 4367 case EXTERNAL_FLOAT_ELEMENTS: |
4384 case EXTERNAL_DOUBLE_ELEMENTS: | 4368 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4454 accessors->SetComponents(getter, setter); | 4438 accessors->SetComponents(getter, setter); |
4455 return SetPropertyCallback(name, accessors, attributes); | 4439 return SetPropertyCallback(name, accessors, attributes); |
4456 } | 4440 } |
4457 | 4441 |
4458 | 4442 |
4459 bool JSObject::CanSetCallback(String* name) { | 4443 bool JSObject::CanSetCallback(String* name) { |
4460 ASSERT(!IsAccessCheckNeeded() || | 4444 ASSERT(!IsAccessCheckNeeded() || |
4461 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4445 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
4462 | 4446 |
4463 // Check if there is an API defined callback object which prohibits | 4447 // Check if there is an API defined callback object which prohibits |
4464 // callback overwriting in this object or its prototype chain. | 4448 // callback overwriting in this object or it's prototype chain. |
4465 // This mechanism is needed for instance in a browser setting, where | 4449 // This mechanism is needed for instance in a browser setting, where |
4466 // certain accessors such as window.location should not be allowed | 4450 // certain accessors such as window.location should not be allowed |
4467 // to be overwritten because allowing overwriting could potentially | 4451 // to be overwritten because allowing overwriting could potentially |
4468 // cause security problems. | 4452 // cause security problems. |
4469 LookupResult callback_result(GetIsolate()); | 4453 LookupResult callback_result(GetIsolate()); |
4470 LookupCallback(name, &callback_result); | 4454 LookupCallback(name, &callback_result); |
4471 if (callback_result.IsProperty()) { | 4455 if (callback_result.IsProperty()) { |
4472 Object* obj = callback_result.GetCallbackObject(); | 4456 Object* obj = callback_result.GetCallbackObject(); |
4473 if (obj->IsAccessorInfo() && | 4457 if (obj->IsAccessorInfo() && |
4474 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4458 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4625 } | 4609 } |
4626 | 4610 |
4627 uint32_t index = 0; | 4611 uint32_t index = 0; |
4628 bool is_element = name->AsArrayIndex(&index); | 4612 bool is_element = name->AsArrayIndex(&index); |
4629 | 4613 |
4630 if (is_element) { | 4614 if (is_element) { |
4631 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4615 if (IsJSArray()) return isolate->heap()->undefined_value(); |
4632 | 4616 |
4633 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4617 // Accessors overwrite previous callbacks (cf. with getters/setters). |
4634 switch (GetElementsKind()) { | 4618 switch (GetElementsKind()) { |
4635 case FAST_SMI_ELEMENTS: | 4619 case FAST_SMI_ONLY_ELEMENTS: |
4636 case FAST_ELEMENTS: | 4620 case FAST_ELEMENTS: |
4637 case FAST_DOUBLE_ELEMENTS: | 4621 case FAST_DOUBLE_ELEMENTS: |
4638 case FAST_HOLEY_SMI_ELEMENTS: | |
4639 case FAST_HOLEY_ELEMENTS: | |
4640 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4641 break; | 4622 break; |
4642 case EXTERNAL_PIXEL_ELEMENTS: | 4623 case EXTERNAL_PIXEL_ELEMENTS: |
4643 case EXTERNAL_BYTE_ELEMENTS: | 4624 case EXTERNAL_BYTE_ELEMENTS: |
4644 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4625 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4645 case EXTERNAL_SHORT_ELEMENTS: | 4626 case EXTERNAL_SHORT_ELEMENTS: |
4646 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4627 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4647 case EXTERNAL_INT_ELEMENTS: | 4628 case EXTERNAL_INT_ELEMENTS: |
4648 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4629 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4649 case EXTERNAL_FLOAT_ELEMENTS: | 4630 case EXTERNAL_FLOAT_ELEMENTS: |
4650 case EXTERNAL_DOUBLE_ELEMENTS: | 4631 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8419 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 8400 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
8420 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8401 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
8421 PrintF(out, "\n"); | 8402 PrintF(out, "\n"); |
8422 } | 8403 } |
8423 #endif // ENABLE_DISASSEMBLER | 8404 #endif // ENABLE_DISASSEMBLER |
8424 | 8405 |
8425 | 8406 |
8426 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8407 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
8427 int capacity, | 8408 int capacity, |
8428 int length, | 8409 int length, |
8429 SetFastElementsCapacitySmiMode smi_mode) { | 8410 SetFastElementsCapacityMode set_capacity_mode) { |
8430 Heap* heap = GetHeap(); | 8411 Heap* heap = GetHeap(); |
8431 // We should never end in here with a pixel or external array. | 8412 // We should never end in here with a pixel or external array. |
8432 ASSERT(!HasExternalArrayElements()); | 8413 ASSERT(!HasExternalArrayElements()); |
8433 | 8414 |
8434 // Allocate a new fast elements backing store. | 8415 // Allocate a new fast elements backing store. |
8435 FixedArray* new_elements; | 8416 FixedArray* new_elements; |
8436 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 8417 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
8437 if (!maybe->To(&new_elements)) return maybe; | 8418 if (!maybe->To(&new_elements)) return maybe; |
8438 } | 8419 } |
8439 | 8420 |
| 8421 // Find the new map to use for this object if there is a map change. |
| 8422 Map* new_map = NULL; |
| 8423 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
| 8424 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces |
| 8425 // it, or if it's allowed and the old elements array contained only SMIs. |
| 8426 bool has_fast_smi_only_elements = |
| 8427 (set_capacity_mode == kForceSmiOnlyElements) || |
| 8428 ((set_capacity_mode == kAllowSmiOnlyElements) && |
| 8429 (elements()->map()->has_fast_smi_only_elements() || |
| 8430 elements() == heap->empty_fixed_array())); |
| 8431 ElementsKind elements_kind = has_fast_smi_only_elements |
| 8432 ? FAST_SMI_ONLY_ELEMENTS |
| 8433 : FAST_ELEMENTS; |
| 8434 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); |
| 8435 if (!maybe->To(&new_map)) return maybe; |
| 8436 } |
| 8437 |
| 8438 FixedArrayBase* old_elements = elements(); |
8440 ElementsKind elements_kind = GetElementsKind(); | 8439 ElementsKind elements_kind = GetElementsKind(); |
8441 ElementsKind new_elements_kind; | |
8442 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, | |
8443 // or if it's allowed and the old elements array contained only SMIs. | |
8444 bool has_fast_smi_elements = | |
8445 (smi_mode == kForceSmiElements) || | |
8446 ((smi_mode == kAllowSmiElements) && HasFastSmiElements()); | |
8447 if (has_fast_smi_elements) { | |
8448 if (IsHoleyElementsKind(elements_kind)) { | |
8449 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; | |
8450 } else { | |
8451 new_elements_kind = FAST_SMI_ELEMENTS; | |
8452 } | |
8453 } else { | |
8454 if (IsHoleyElementsKind(elements_kind)) { | |
8455 new_elements_kind = FAST_HOLEY_ELEMENTS; | |
8456 } else { | |
8457 new_elements_kind = FAST_ELEMENTS; | |
8458 } | |
8459 } | |
8460 FixedArrayBase* old_elements = elements(); | |
8461 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8440 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 8441 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) |
| 8442 ? FAST_SMI_ONLY_ELEMENTS |
| 8443 : FAST_ELEMENTS; |
8462 { MaybeObject* maybe_obj = | 8444 { MaybeObject* maybe_obj = |
8463 accessor->CopyElements(this, new_elements, new_elements_kind); | 8445 accessor->CopyElements(this, new_elements, to_kind); |
8464 if (maybe_obj->IsFailure()) return maybe_obj; | 8446 if (maybe_obj->IsFailure()) return maybe_obj; |
8465 } | 8447 } |
8466 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8448 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(); | |
8474 set_map_and_elements(new_map, new_elements); | 8449 set_map_and_elements(new_map, new_elements); |
8475 } else { | 8450 } else { |
8476 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8451 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8477 parameter_map->set(1, new_elements); | 8452 parameter_map->set(1, new_elements); |
8478 } | 8453 } |
8479 | 8454 |
8480 if (FLAG_trace_elements_transitions) { | 8455 if (FLAG_trace_elements_transitions) { |
8481 PrintElementsTransition(stdout, elements_kind, old_elements, | 8456 PrintElementsTransition(stdout, elements_kind, old_elements, |
8482 GetElementsKind(), new_elements); | 8457 GetElementsKind(), new_elements); |
8483 } | 8458 } |
8484 | 8459 |
| 8460 // Update the length if necessary. |
8485 if (IsJSArray()) { | 8461 if (IsJSArray()) { |
8486 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8462 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8487 } | 8463 } |
| 8464 |
8488 return new_elements; | 8465 return new_elements; |
8489 } | 8466 } |
8490 | 8467 |
8491 | 8468 |
8492 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8469 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
8493 int capacity, | 8470 int capacity, |
8494 int length) { | 8471 int length) { |
8495 Heap* heap = GetHeap(); | 8472 Heap* heap = GetHeap(); |
8496 // We should never end in here with a pixel or external array. | 8473 // We should never end in here with a pixel or external array. |
8497 ASSERT(!HasExternalArrayElements()); | 8474 ASSERT(!HasExternalArrayElements()); |
8498 | 8475 |
8499 FixedArrayBase* elems; | 8476 FixedArrayBase* elems; |
8500 { MaybeObject* maybe_obj = | 8477 { MaybeObject* maybe_obj = |
8501 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8478 heap->AllocateUninitializedFixedDoubleArray(capacity); |
8502 if (!maybe_obj->To(&elems)) return maybe_obj; | 8479 if (!maybe_obj->To(&elems)) return maybe_obj; |
8503 } | 8480 } |
8504 | 8481 |
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 | |
8513 Map* new_map; | 8482 Map* new_map; |
8514 { MaybeObject* maybe_obj = | 8483 { MaybeObject* maybe_obj = |
8515 GetElementsTransitionMap(heap->isolate(), new_elements_kind); | 8484 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); |
8516 if (!maybe_obj->To(&new_map)) return maybe_obj; | 8485 if (!maybe_obj->To(&new_map)) return maybe_obj; |
8517 } | 8486 } |
8518 | 8487 |
8519 FixedArrayBase* old_elements = elements(); | 8488 FixedArrayBase* old_elements = elements(); |
| 8489 ElementsKind elements_kind = GetElementsKind(); |
8520 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8490 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8521 { MaybeObject* maybe_obj = | 8491 { MaybeObject* maybe_obj = |
8522 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); | 8492 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); |
8523 if (maybe_obj->IsFailure()) return maybe_obj; | 8493 if (maybe_obj->IsFailure()) return maybe_obj; |
8524 } | 8494 } |
8525 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8495 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
8526 ValidateElements(); | |
8527 set_map_and_elements(new_map, elems); | 8496 set_map_and_elements(new_map, elems); |
8528 } else { | 8497 } else { |
8529 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8498 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8530 parameter_map->set(1, elems); | 8499 parameter_map->set(1, elems); |
8531 } | 8500 } |
8532 | 8501 |
8533 if (FLAG_trace_elements_transitions) { | 8502 if (FLAG_trace_elements_transitions) { |
8534 PrintElementsTransition(stdout, elements_kind, old_elements, | 8503 PrintElementsTransition(stdout, elements_kind, old_elements, |
8535 GetElementsKind(), elems); | 8504 FAST_DOUBLE_ELEMENTS, elems); |
8536 } | 8505 } |
8537 | 8506 |
8538 if (IsJSArray()) { | 8507 if (IsJSArray()) { |
8539 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8508 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8540 } | 8509 } |
8541 | 8510 |
8542 return this; | 8511 return this; |
8543 } | 8512 } |
8544 | 8513 |
8545 | 8514 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8805 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8774 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
8806 : UNDEFINED_ELEMENT; | 8775 : UNDEFINED_ELEMENT; |
8807 } | 8776 } |
8808 | 8777 |
8809 // Handle [] on String objects. | 8778 // Handle [] on String objects. |
8810 if (this->IsStringObjectWithCharacterAt(index)) { | 8779 if (this->IsStringObjectWithCharacterAt(index)) { |
8811 return STRING_CHARACTER_ELEMENT; | 8780 return STRING_CHARACTER_ELEMENT; |
8812 } | 8781 } |
8813 | 8782 |
8814 switch (GetElementsKind()) { | 8783 switch (GetElementsKind()) { |
8815 case FAST_SMI_ELEMENTS: | 8784 case FAST_SMI_ONLY_ELEMENTS: |
8816 case FAST_ELEMENTS: | 8785 case FAST_ELEMENTS: { |
8817 case FAST_HOLEY_SMI_ELEMENTS: | |
8818 case FAST_HOLEY_ELEMENTS: { | |
8819 uint32_t length = IsJSArray() ? | 8786 uint32_t length = IsJSArray() ? |
8820 static_cast<uint32_t> | 8787 static_cast<uint32_t> |
8821 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8788 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8822 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8789 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
8823 if ((index < length) && | 8790 if ((index < length) && |
8824 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8791 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
8825 return FAST_ELEMENT; | 8792 return FAST_ELEMENT; |
8826 } | 8793 } |
8827 break; | 8794 break; |
8828 } | 8795 } |
8829 case FAST_DOUBLE_ELEMENTS: | 8796 case FAST_DOUBLE_ELEMENTS: { |
8830 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
8831 uint32_t length = IsJSArray() ? | 8797 uint32_t length = IsJSArray() ? |
8832 static_cast<uint32_t> | 8798 static_cast<uint32_t> |
8833 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8799 (Smi::cast(JSArray::cast(this)->length())->value()) : |
8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 8800 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
8835 if ((index < length) && | 8801 if ((index < length) && |
8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | 8802 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
8837 return FAST_ELEMENT; | 8803 return FAST_ELEMENT; |
8838 } | 8804 } |
8839 break; | 8805 break; |
8840 } | 8806 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9104 } | 9070 } |
9105 | 9071 |
9106 | 9072 |
9107 // Adding n elements in fast case is O(n*n). | 9073 // Adding n elements in fast case is O(n*n). |
9108 // Note: revisit design to have dual undefined values to capture absent | 9074 // Note: revisit design to have dual undefined values to capture absent |
9109 // elements. | 9075 // elements. |
9110 MaybeObject* JSObject::SetFastElement(uint32_t index, | 9076 MaybeObject* JSObject::SetFastElement(uint32_t index, |
9111 Object* value, | 9077 Object* value, |
9112 StrictModeFlag strict_mode, | 9078 StrictModeFlag strict_mode, |
9113 bool check_prototype) { | 9079 bool check_prototype) { |
9114 ASSERT(HasFastSmiOrObjectElements() || | 9080 ASSERT(HasFastTypeElements() || |
9115 HasFastArgumentsElements()); | 9081 HasFastArgumentsElements()); |
9116 | 9082 |
9117 FixedArray* backing_store = FixedArray::cast(elements()); | 9083 FixedArray* backing_store = FixedArray::cast(elements()); |
9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9084 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
9119 backing_store = FixedArray::cast(backing_store->get(1)); | 9085 backing_store = FixedArray::cast(backing_store->get(1)); |
9120 } else { | 9086 } else { |
9121 MaybeObject* maybe = EnsureWritableFastElements(); | 9087 MaybeObject* maybe = EnsureWritableFastElements(); |
9122 if (!maybe->To(&backing_store)) return maybe; | 9088 if (!maybe->To(&backing_store)) return maybe; |
9123 } | 9089 } |
9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 9090 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
9125 | 9091 |
9126 if (check_prototype && | 9092 if (check_prototype && |
9127 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 9093 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
9128 bool found; | 9094 bool found; |
9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9095 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9130 value, | 9096 value, |
9131 &found, | 9097 &found, |
9132 strict_mode); | 9098 strict_mode); |
9133 if (found) return result; | 9099 if (found) return result; |
9134 } | 9100 } |
9135 | 9101 |
9136 uint32_t new_capacity = capacity; | 9102 uint32_t new_capacity = capacity; |
9137 // Check if the length property of this object needs to be updated. | 9103 // Check if the length property of this object needs to be updated. |
9138 uint32_t array_length = 0; | 9104 uint32_t array_length = 0; |
9139 bool must_update_array_length = false; | 9105 bool must_update_array_length = false; |
9140 bool introduces_holes = true; | |
9141 if (IsJSArray()) { | 9106 if (IsJSArray()) { |
9142 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9107 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9143 introduces_holes = index > array_length; | |
9144 if (index >= array_length) { | 9108 if (index >= array_length) { |
9145 must_update_array_length = true; | 9109 must_update_array_length = true; |
9146 array_length = index + 1; | 9110 array_length = index + 1; |
9147 } | 9111 } |
9148 } else { | |
9149 introduces_holes = index >= capacity; | |
9150 } | 9112 } |
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 | |
9163 // Check if the capacity of the backing store needs to be increased, or if | 9113 // Check if the capacity of the backing store needs to be increased, or if |
9164 // a transition to slow elements is necessary. | 9114 // a transition to slow elements is necessary. |
9165 if (index >= capacity) { | 9115 if (index >= capacity) { |
9166 bool convert_to_slow = true; | 9116 bool convert_to_slow = true; |
9167 if ((index - capacity) < kMaxGap) { | 9117 if ((index - capacity) < kMaxGap) { |
9168 new_capacity = NewElementsCapacity(index + 1); | 9118 new_capacity = NewElementsCapacity(index + 1); |
9169 ASSERT(new_capacity > index); | 9119 ASSERT(new_capacity > index); |
9170 if (!ShouldConvertToSlowElements(new_capacity)) { | 9120 if (!ShouldConvertToSlowElements(new_capacity)) { |
9171 convert_to_slow = false; | 9121 convert_to_slow = false; |
9172 } | 9122 } |
9173 } | 9123 } |
9174 if (convert_to_slow) { | 9124 if (convert_to_slow) { |
9175 MaybeObject* result = NormalizeElements(); | 9125 MaybeObject* result = NormalizeElements(); |
9176 if (result->IsFailure()) return result; | 9126 if (result->IsFailure()) return result; |
9177 return SetDictionaryElement(index, value, NONE, strict_mode, | 9127 return SetDictionaryElement(index, value, NONE, strict_mode, |
9178 check_prototype); | 9128 check_prototype); |
9179 } | 9129 } |
9180 } | 9130 } |
9181 // Convert to fast double elements if appropriate. | 9131 // Convert to fast double elements if appropriate. |
9182 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { | 9132 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { |
9183 MaybeObject* maybe = | 9133 MaybeObject* maybe = |
9184 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9134 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
9185 if (maybe->IsFailure()) return maybe; | 9135 if (maybe->IsFailure()) return maybe; |
9186 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9136 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
9187 ValidateElements(); | |
9188 return value; | 9137 return value; |
9189 } | 9138 } |
9190 // Change elements kind from Smi-only to generic FAST if necessary. | 9139 // Change elements kind from SMI_ONLY to generic FAST if necessary. |
9191 if (HasFastSmiElements() && !value->IsSmi()) { | 9140 if (HasFastSmiOnlyElements() && !value->IsSmi()) { |
9192 Map* new_map; | 9141 Map* new_map; |
9193 ElementsKind kind = HasFastHoleyElements() | 9142 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
9194 ? FAST_HOLEY_ELEMENTS | 9143 FAST_ELEMENTS); |
9195 : FAST_ELEMENTS; | 9144 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9196 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 9145 } |
9197 kind); | |
9198 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
9199 | |
9200 set_map(new_map); | 9146 set_map(new_map); |
| 9147 if (FLAG_trace_elements_transitions) { |
| 9148 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), |
| 9149 FAST_ELEMENTS, elements()); |
| 9150 } |
9201 } | 9151 } |
9202 // Increase backing store capacity if that's been decided previously. | 9152 // Increase backing store capacity if that's been decided previously. |
9203 if (new_capacity != capacity) { | 9153 if (new_capacity != capacity) { |
9204 FixedArray* new_elements; | 9154 FixedArray* new_elements; |
9205 SetFastElementsCapacitySmiMode smi_mode = | 9155 SetFastElementsCapacityMode set_capacity_mode = |
9206 value->IsSmi() && HasFastSmiElements() | 9156 value->IsSmi() && HasFastSmiOnlyElements() |
9207 ? kAllowSmiElements | 9157 ? kAllowSmiOnlyElements |
9208 : kDontAllowSmiElements; | 9158 : kDontAllowSmiOnlyElements; |
9209 { MaybeObject* maybe = | 9159 { MaybeObject* maybe = |
9210 SetFastElementsCapacityAndLength(new_capacity, | 9160 SetFastElementsCapacityAndLength(new_capacity, |
9211 array_length, | 9161 array_length, |
9212 smi_mode); | 9162 set_capacity_mode); |
9213 if (!maybe->To(&new_elements)) return maybe; | 9163 if (!maybe->To(&new_elements)) return maybe; |
9214 } | 9164 } |
9215 new_elements->set(index, value); | 9165 new_elements->set(index, value); |
9216 ValidateElements(); | |
9217 return value; | 9166 return value; |
9218 } | 9167 } |
9219 | |
9220 // Finally, set the new element and length. | 9168 // Finally, set the new element and length. |
9221 ASSERT(elements()->IsFixedArray()); | 9169 ASSERT(elements()->IsFixedArray()); |
9222 backing_store->set(index, value); | 9170 backing_store->set(index, value); |
9223 if (must_update_array_length) { | 9171 if (must_update_array_length) { |
9224 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 9172 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); |
9225 } | 9173 } |
9226 return value; | 9174 return value; |
9227 } | 9175 } |
9228 | 9176 |
9229 | 9177 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9333 } | 9281 } |
9334 | 9282 |
9335 // Attempt to put this object back in fast case. | 9283 // Attempt to put this object back in fast case. |
9336 if (ShouldConvertToFastElements()) { | 9284 if (ShouldConvertToFastElements()) { |
9337 uint32_t new_length = 0; | 9285 uint32_t new_length = 0; |
9338 if (IsJSArray()) { | 9286 if (IsJSArray()) { |
9339 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
9340 } else { | 9288 } else { |
9341 new_length = dictionary->max_number_key() + 1; | 9289 new_length = dictionary->max_number_key() + 1; |
9342 } | 9290 } |
9343 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays | 9291 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays |
9344 ? kAllowSmiElements | 9292 ? kAllowSmiOnlyElements |
9345 : kDontAllowSmiElements; | 9293 : kDontAllowSmiOnlyElements; |
9346 bool has_smi_only_elements = false; | 9294 bool has_smi_only_elements = false; |
9347 bool should_convert_to_fast_double_elements = | 9295 bool should_convert_to_fast_double_elements = |
9348 ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 9296 ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
9349 if (has_smi_only_elements) { | 9297 if (has_smi_only_elements) { |
9350 smi_mode = kForceSmiElements; | 9298 set_capacity_mode = kForceSmiOnlyElements; |
9351 } | 9299 } |
9352 MaybeObject* result = should_convert_to_fast_double_elements | 9300 MaybeObject* result = should_convert_to_fast_double_elements |
9353 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 9301 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
9354 : SetFastElementsCapacityAndLength(new_length, | 9302 : SetFastElementsCapacityAndLength(new_length, |
9355 new_length, | 9303 new_length, |
9356 smi_mode); | 9304 set_capacity_mode); |
9357 ValidateElements(); | |
9358 if (result->IsFailure()) return result; | 9305 if (result->IsFailure()) return result; |
9359 #ifdef DEBUG | 9306 #ifdef DEBUG |
9360 if (FLAG_trace_normalization) { | 9307 if (FLAG_trace_normalization) { |
9361 PrintF("Object elements are fast case again:\n"); | 9308 PrintF("Object elements are fast case again:\n"); |
9362 Print(); | 9309 Print(); |
9363 } | 9310 } |
9364 #endif | 9311 #endif |
9365 } | 9312 } |
9366 return value; | 9313 return value; |
9367 } | 9314 } |
(...skipping 18 matching lines...) Expand all Loading... |
9386 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9333 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9387 value, | 9334 value, |
9388 &found, | 9335 &found, |
9389 strict_mode); | 9336 strict_mode); |
9390 if (found) return result; | 9337 if (found) return result; |
9391 } | 9338 } |
9392 | 9339 |
9393 // If the value object is not a heap number, switch to fast elements and try | 9340 // If the value object is not a heap number, switch to fast elements and try |
9394 // again. | 9341 // again. |
9395 bool value_is_smi = value->IsSmi(); | 9342 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 | |
9405 if (!value->IsNumber()) { | 9343 if (!value->IsNumber()) { |
| 9344 Object* obj; |
| 9345 uint32_t length = elms_length; |
| 9346 if (IsJSArray()) { |
| 9347 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9348 } |
9406 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 9349 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
9407 elms_length, | 9350 elms_length, |
9408 length, | 9351 length, |
9409 kDontAllowSmiElements); | 9352 kDontAllowSmiOnlyElements); |
9410 if (maybe_obj->IsFailure()) return maybe_obj; | 9353 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
9411 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); | 9354 return SetFastElement(index, |
9412 if (maybe_obj->IsFailure()) return maybe_obj; | 9355 value, |
9413 ValidateElements(); | 9356 strict_mode, |
9414 return maybe_obj; | 9357 check_prototype); |
9415 } | 9358 } |
9416 | 9359 |
9417 double double_value = value_is_smi | 9360 double double_value = value_is_smi |
9418 ? static_cast<double>(Smi::cast(value)->value()) | 9361 ? static_cast<double>(Smi::cast(value)->value()) |
9419 : HeapNumber::cast(value)->value(); | 9362 : HeapNumber::cast(value)->value(); |
9420 | 9363 |
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 | |
9430 // Check whether there is extra space in the fixed array. | 9364 // Check whether there is extra space in the fixed array. |
9431 if (index < elms_length) { | 9365 if (index < elms_length) { |
9432 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9366 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9433 elms->set(index, double_value); | 9367 elms->set(index, double_value); |
9434 if (IsJSArray()) { | 9368 if (IsJSArray()) { |
9435 // Update the length of the array if needed. | 9369 // Update the length of the array if needed. |
9436 uint32_t array_length = 0; | 9370 uint32_t array_length = 0; |
9437 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9371 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9438 if (index >= array_length) { | 9372 if (index >= array_length) { |
9439 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 9373 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
9440 } | 9374 } |
9441 } | 9375 } |
9442 return value; | 9376 return value; |
9443 } | 9377 } |
9444 | 9378 |
9445 // Allow gap in fast case. | 9379 // Allow gap in fast case. |
9446 if ((index - elms_length) < kMaxGap) { | 9380 if ((index - elms_length) < kMaxGap) { |
9447 // Try allocating extra space. | 9381 // Try allocating extra space. |
9448 int new_capacity = NewElementsCapacity(index+1); | 9382 int new_capacity = NewElementsCapacity(index+1); |
9449 if (!ShouldConvertToSlowElements(new_capacity)) { | 9383 if (!ShouldConvertToSlowElements(new_capacity)) { |
9450 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 9384 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
9451 MaybeObject* maybe_obj = | 9385 Object* obj; |
9452 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); | 9386 { MaybeObject* maybe_obj = |
9453 if (maybe_obj->IsFailure()) return maybe_obj; | 9387 SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 9388 index + 1); |
| 9389 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9390 } |
9454 FixedDoubleArray::cast(elements())->set(index, double_value); | 9391 FixedDoubleArray::cast(elements())->set(index, double_value); |
9455 ValidateElements(); | |
9456 return value; | 9392 return value; |
9457 } | 9393 } |
9458 } | 9394 } |
9459 | 9395 |
9460 // Otherwise default to slow case. | 9396 // Otherwise default to slow case. |
9461 ASSERT(HasFastDoubleElements()); | 9397 ASSERT(HasFastDoubleElements()); |
9462 ASSERT(map()->has_fast_double_elements()); | 9398 ASSERT(map()->has_fast_double_elements()); |
9463 ASSERT(elements()->IsFixedDoubleArray()); | 9399 ASSERT(elements()->IsFixedDoubleArray()); |
9464 Object* obj; | 9400 Object* obj; |
9465 { MaybeObject* maybe_obj = NormalizeElements(); | 9401 { MaybeObject* maybe_obj = NormalizeElements(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9589 Object* value, | 9525 Object* value, |
9590 PropertyAttributes attr, | 9526 PropertyAttributes attr, |
9591 StrictModeFlag strict_mode, | 9527 StrictModeFlag strict_mode, |
9592 bool check_prototype, | 9528 bool check_prototype, |
9593 SetPropertyMode set_mode) { | 9529 SetPropertyMode set_mode) { |
9594 ASSERT(HasDictionaryElements() || | 9530 ASSERT(HasDictionaryElements() || |
9595 HasDictionaryArgumentsElements() || | 9531 HasDictionaryArgumentsElements() || |
9596 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 9532 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
9597 Isolate* isolate = GetIsolate(); | 9533 Isolate* isolate = GetIsolate(); |
9598 switch (GetElementsKind()) { | 9534 switch (GetElementsKind()) { |
9599 case FAST_SMI_ELEMENTS: | 9535 case FAST_SMI_ONLY_ELEMENTS: |
9600 case FAST_ELEMENTS: | 9536 case FAST_ELEMENTS: |
9601 case FAST_HOLEY_SMI_ELEMENTS: | |
9602 case FAST_HOLEY_ELEMENTS: | |
9603 return SetFastElement(index, value, strict_mode, check_prototype); | 9537 return SetFastElement(index, value, strict_mode, check_prototype); |
9604 case FAST_DOUBLE_ELEMENTS: | 9538 case FAST_DOUBLE_ELEMENTS: |
9605 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
9606 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 9539 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
9607 case EXTERNAL_PIXEL_ELEMENTS: { | 9540 case EXTERNAL_PIXEL_ELEMENTS: { |
9608 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9541 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
9609 return pixels->SetValue(index, value); | 9542 return pixels->SetValue(index, value); |
9610 } | 9543 } |
9611 case EXTERNAL_BYTE_ELEMENTS: { | 9544 case EXTERNAL_BYTE_ELEMENTS: { |
9612 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 9545 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
9613 return array->SetValue(index, value); | 9546 return array->SetValue(index, value); |
9614 } | 9547 } |
9615 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 9548 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9686 ElementsKind to_kind) { | 9619 ElementsKind to_kind) { |
9687 CALL_HEAP_FUNCTION(object->GetIsolate(), | 9620 CALL_HEAP_FUNCTION(object->GetIsolate(), |
9688 object->TransitionElementsKind(to_kind), | 9621 object->TransitionElementsKind(to_kind), |
9689 Object); | 9622 Object); |
9690 } | 9623 } |
9691 | 9624 |
9692 | 9625 |
9693 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 9626 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
9694 ElementsKind from_kind = map()->elements_kind(); | 9627 ElementsKind from_kind = map()->elements_kind(); |
9695 | 9628 |
9696 if (IsFastHoleyElementsKind(from_kind)) { | |
9697 to_kind = GetHoleyElementsKind(to_kind); | |
9698 } | |
9699 | |
9700 Isolate* isolate = GetIsolate(); | 9629 Isolate* isolate = GetIsolate(); |
9701 if (elements() == isolate->heap()->empty_fixed_array() || | 9630 if ((from_kind == FAST_SMI_ONLY_ELEMENTS || |
9702 (IsFastSmiOrObjectElementsKind(from_kind) && | 9631 elements() == isolate->heap()->empty_fixed_array()) && |
9703 IsFastSmiOrObjectElementsKind(to_kind)) || | 9632 to_kind == FAST_ELEMENTS) { |
9704 (from_kind == FAST_DOUBLE_ELEMENTS && | 9633 ASSERT(from_kind != FAST_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. | |
9709 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 9634 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
9710 Map* new_map; | 9635 Map* new_map; |
9711 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9636 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9712 set_map(new_map); | 9637 set_map(new_map); |
9713 if (FLAG_trace_elements_transitions) { | 9638 if (FLAG_trace_elements_transitions) { |
9714 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9639 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9715 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 9640 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
9716 } | 9641 } |
9717 return this; | 9642 return this; |
9718 } | 9643 } |
9719 | 9644 |
9720 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9645 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9721 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9646 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9722 uint32_t length = capacity; | 9647 uint32_t length = capacity; |
9723 | 9648 |
9724 if (IsJSArray()) { | 9649 if (IsJSArray()) { |
9725 Object* raw_length = JSArray::cast(this)->length(); | 9650 Object* raw_length = JSArray::cast(this)->length(); |
9726 if (raw_length->IsUndefined()) { | 9651 if (raw_length->IsUndefined()) { |
9727 // If length is undefined, then JSArray is being initialized and has no | 9652 // If length is undefined, then JSArray is being initialized and has no |
9728 // elements, assume a length of zero. | 9653 // elements, assume a length of zero. |
9729 length = 0; | 9654 length = 0; |
9730 } else { | 9655 } else { |
9731 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9656 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
9732 } | 9657 } |
9733 } | 9658 } |
9734 | 9659 |
9735 if (IsFastSmiElementsKind(from_kind) && | 9660 if (from_kind == FAST_SMI_ONLY_ELEMENTS && |
9736 IsFastDoubleElementsKind(to_kind)) { | 9661 to_kind == FAST_DOUBLE_ELEMENTS) { |
9737 MaybeObject* maybe_result = | 9662 MaybeObject* maybe_result = |
9738 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9663 SetFastDoubleElementsCapacityAndLength(capacity, length); |
9739 if (maybe_result->IsFailure()) return maybe_result; | 9664 if (maybe_result->IsFailure()) return maybe_result; |
9740 ValidateElements(); | |
9741 return this; | 9665 return this; |
9742 } | 9666 } |
9743 | 9667 |
9744 if (IsFastDoubleElementsKind(from_kind) && | 9668 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
9745 IsFastObjectElementsKind(to_kind)) { | |
9746 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9669 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
9747 capacity, length, kDontAllowSmiElements); | 9670 capacity, length, kDontAllowSmiOnlyElements); |
9748 if (maybe_result->IsFailure()) return maybe_result; | 9671 if (maybe_result->IsFailure()) return maybe_result; |
9749 ValidateElements(); | |
9750 return this; | 9672 return this; |
9751 } | 9673 } |
9752 | 9674 |
9753 // This method should never be called for any other case than the ones | 9675 // This method should never be called for any other case than the ones |
9754 // handled above. | 9676 // handled above. |
9755 UNREACHABLE(); | 9677 UNREACHABLE(); |
9756 return GetIsolate()->heap()->null_value(); | 9678 return GetIsolate()->heap()->null_value(); |
9757 } | 9679 } |
9758 | 9680 |
9759 | 9681 |
9760 // static | 9682 // static |
9761 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9683 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
9762 ElementsKind to_kind) { | 9684 ElementsKind to_kind) { |
9763 // Transitions can't go backwards. | 9685 return |
9764 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { | 9686 (from_kind == FAST_SMI_ONLY_ELEMENTS && |
9765 return false; | 9687 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || |
9766 } | 9688 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); |
9767 | |
9768 // Transitions from HOLEY -> PACKED are not allowed. | |
9769 return !IsFastHoleyElementsKind(from_kind) || | |
9770 IsFastHoleyElementsKind(to_kind); | |
9771 } | 9689 } |
9772 | 9690 |
9773 | 9691 |
9774 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 9692 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
9775 Object* value) { | 9693 Object* value) { |
9776 uint32_t old_len = 0; | 9694 uint32_t old_len = 0; |
9777 CHECK(length()->ToArrayIndex(&old_len)); | 9695 CHECK(length()->ToArrayIndex(&old_len)); |
9778 // Check to see if we need to update the length. For now, we make | 9696 // Check to see if we need to update the length. For now, we make |
9779 // sure that the length stays within 32-bits (unsigned). | 9697 // sure that the length stays within 32-bits (unsigned). |
9780 if (index >= old_len && index != 0xffffffff) { | 9698 if (index >= old_len && index != 0xffffffff) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9851 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 9769 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
9852 backing_store = FixedArray::cast(backing_store_base); | 9770 backing_store = FixedArray::cast(backing_store_base); |
9853 if (backing_store->IsDictionary()) { | 9771 if (backing_store->IsDictionary()) { |
9854 SeededNumberDictionary* dictionary = | 9772 SeededNumberDictionary* dictionary = |
9855 SeededNumberDictionary::cast(backing_store); | 9773 SeededNumberDictionary::cast(backing_store); |
9856 *capacity = dictionary->Capacity(); | 9774 *capacity = dictionary->Capacity(); |
9857 *used = dictionary->NumberOfElements(); | 9775 *used = dictionary->NumberOfElements(); |
9858 break; | 9776 break; |
9859 } | 9777 } |
9860 // Fall through. | 9778 // Fall through. |
9861 case FAST_SMI_ELEMENTS: | 9779 case FAST_SMI_ONLY_ELEMENTS: |
9862 case FAST_ELEMENTS: | 9780 case FAST_ELEMENTS: |
9863 case FAST_HOLEY_SMI_ELEMENTS: | |
9864 case FAST_HOLEY_ELEMENTS: | |
9865 backing_store = FixedArray::cast(backing_store_base); | 9781 backing_store = FixedArray::cast(backing_store_base); |
9866 *capacity = backing_store->length(); | 9782 *capacity = backing_store->length(); |
9867 for (int i = 0; i < *capacity; ++i) { | 9783 for (int i = 0; i < *capacity; ++i) { |
9868 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 9784 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
9869 } | 9785 } |
9870 break; | 9786 break; |
9871 case DICTIONARY_ELEMENTS: { | 9787 case DICTIONARY_ELEMENTS: { |
9872 SeededNumberDictionary* dictionary = | 9788 SeededNumberDictionary* dictionary = |
9873 SeededNumberDictionary::cast(FixedArray::cast(elements())); | 9789 SeededNumberDictionary::cast(FixedArray::cast(elements())); |
9874 *capacity = dictionary->Capacity(); | 9790 *capacity = dictionary->Capacity(); |
9875 *used = dictionary->NumberOfElements(); | 9791 *used = dictionary->NumberOfElements(); |
9876 break; | 9792 break; |
9877 } | 9793 } |
9878 case FAST_DOUBLE_ELEMENTS: | 9794 case FAST_DOUBLE_ELEMENTS: { |
9879 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
9880 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9795 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9881 *capacity = elms->length(); | 9796 *capacity = elms->length(); |
9882 for (int i = 0; i < *capacity; i++) { | 9797 for (int i = 0; i < *capacity; i++) { |
9883 if (!elms->is_the_hole(i)) ++(*used); | 9798 if (!elms->is_the_hole(i)) ++(*used); |
9884 } | 9799 } |
9885 break; | 9800 break; |
9886 } | 9801 } |
9887 case EXTERNAL_BYTE_ELEMENTS: | 9802 case EXTERNAL_BYTE_ELEMENTS: |
9888 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9803 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
9889 case EXTERNAL_SHORT_ELEMENTS: | 9804 case EXTERNAL_SHORT_ELEMENTS: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10139 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10054 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
10140 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 10055 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
10141 return false; | 10056 return false; |
10142 } | 10057 } |
10143 } | 10058 } |
10144 | 10059 |
10145 // Handle [] on String objects. | 10060 // Handle [] on String objects. |
10146 if (this->IsStringObjectWithCharacterAt(index)) return true; | 10061 if (this->IsStringObjectWithCharacterAt(index)) return true; |
10147 | 10062 |
10148 switch (GetElementsKind()) { | 10063 switch (GetElementsKind()) { |
10149 case FAST_SMI_ELEMENTS: | 10064 case FAST_SMI_ONLY_ELEMENTS: |
10150 case FAST_ELEMENTS: | 10065 case FAST_ELEMENTS: { |
10151 case FAST_HOLEY_SMI_ELEMENTS: | 10066 uint32_t length = IsJSArray() ? |
10152 case FAST_HOLEY_ELEMENTS: { | |
10153 uint32_t length = IsJSArray() ? | |
10154 static_cast<uint32_t>( | 10067 static_cast<uint32_t>( |
10155 Smi::cast(JSArray::cast(this)->length())->value()) : | 10068 Smi::cast(JSArray::cast(this)->length())->value()) : |
10156 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10069 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10157 return (index < length) && | 10070 return (index < length) && |
10158 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 10071 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
10159 } | 10072 } |
10160 case FAST_DOUBLE_ELEMENTS: | 10073 case FAST_DOUBLE_ELEMENTS: { |
10161 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
10162 uint32_t length = IsJSArray() ? | 10074 uint32_t length = IsJSArray() ? |
10163 static_cast<uint32_t>( | 10075 static_cast<uint32_t>( |
10164 Smi::cast(JSArray::cast(this)->length())->value()) : | 10076 Smi::cast(JSArray::cast(this)->length())->value()) : |
10165 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 10077 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
10166 return (index < length) && | 10078 return (index < length) && |
10167 !FixedDoubleArray::cast(elements())->is_the_hole(index); | 10079 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
10168 break; | 10080 break; |
10169 } | 10081 } |
10170 case EXTERNAL_PIXEL_ELEMENTS: { | 10082 case EXTERNAL_PIXEL_ELEMENTS: { |
10171 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 10083 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10351 } | 10263 } |
10352 | 10264 |
10353 | 10265 |
10354 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 10266 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
10355 return GetLocalElementKeys(NULL, filter); | 10267 return GetLocalElementKeys(NULL, filter); |
10356 } | 10268 } |
10357 | 10269 |
10358 | 10270 |
10359 int JSObject::NumberOfEnumElements() { | 10271 int JSObject::NumberOfEnumElements() { |
10360 // Fast case for objects with no elements. | 10272 // Fast case for objects with no elements. |
10361 if (!IsJSValue() && HasFastObjectElements()) { | 10273 if (!IsJSValue() && HasFastElements()) { |
10362 uint32_t length = IsJSArray() ? | 10274 uint32_t length = IsJSArray() ? |
10363 static_cast<uint32_t>( | 10275 static_cast<uint32_t>( |
10364 Smi::cast(JSArray::cast(this)->length())->value()) : | 10276 Smi::cast(JSArray::cast(this)->length())->value()) : |
10365 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10277 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10366 if (length == 0) return 0; | 10278 if (length == 0) return 0; |
10367 } | 10279 } |
10368 // Compute the number of enumerable elements. | 10280 // Compute the number of enumerable elements. |
10369 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 10281 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
10370 } | 10282 } |
10371 | 10283 |
10372 | 10284 |
10373 int JSObject::GetLocalElementKeys(FixedArray* storage, | 10285 int JSObject::GetLocalElementKeys(FixedArray* storage, |
10374 PropertyAttributes filter) { | 10286 PropertyAttributes filter) { |
10375 int counter = 0; | 10287 int counter = 0; |
10376 switch (GetElementsKind()) { | 10288 switch (GetElementsKind()) { |
10377 case FAST_SMI_ELEMENTS: | 10289 case FAST_SMI_ONLY_ELEMENTS: |
10378 case FAST_ELEMENTS: | 10290 case FAST_ELEMENTS: { |
10379 case FAST_HOLEY_SMI_ELEMENTS: | |
10380 case FAST_HOLEY_ELEMENTS: { | |
10381 int length = IsJSArray() ? | 10291 int length = IsJSArray() ? |
10382 Smi::cast(JSArray::cast(this)->length())->value() : | 10292 Smi::cast(JSArray::cast(this)->length())->value() : |
10383 FixedArray::cast(elements())->length(); | 10293 FixedArray::cast(elements())->length(); |
10384 for (int i = 0; i < length; i++) { | 10294 for (int i = 0; i < length; i++) { |
10385 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 10295 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
10386 if (storage != NULL) { | 10296 if (storage != NULL) { |
10387 storage->set(counter, Smi::FromInt(i)); | 10297 storage->set(counter, Smi::FromInt(i)); |
10388 } | 10298 } |
10389 counter++; | 10299 counter++; |
10390 } | 10300 } |
10391 } | 10301 } |
10392 ASSERT(!storage || storage->length() >= counter); | 10302 ASSERT(!storage || storage->length() >= counter); |
10393 break; | 10303 break; |
10394 } | 10304 } |
10395 case FAST_DOUBLE_ELEMENTS: | 10305 case FAST_DOUBLE_ELEMENTS: { |
10396 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
10397 int length = IsJSArray() ? | 10306 int length = IsJSArray() ? |
10398 Smi::cast(JSArray::cast(this)->length())->value() : | 10307 Smi::cast(JSArray::cast(this)->length())->value() : |
10399 FixedDoubleArray::cast(elements())->length(); | 10308 FixedDoubleArray::cast(elements())->length(); |
10400 for (int i = 0; i < length; i++) { | 10309 for (int i = 0; i < length; i++) { |
10401 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 10310 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
10402 if (storage != NULL) { | 10311 if (storage != NULL) { |
10403 storage->set(counter, Smi::FromInt(i)); | 10312 storage->set(counter, Smi::FromInt(i)); |
10404 } | 10313 } |
10405 counter++; | 10314 counter++; |
10406 } | 10315 } |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11319 // Convert to fast elements containing only the existing properties. | 11228 // Convert to fast elements containing only the existing properties. |
11320 // Ordering is irrelevant, since we are going to sort anyway. | 11229 // Ordering is irrelevant, since we are going to sort anyway. |
11321 SeededNumberDictionary* dict = element_dictionary(); | 11230 SeededNumberDictionary* dict = element_dictionary(); |
11322 if (IsJSArray() || dict->requires_slow_elements() || | 11231 if (IsJSArray() || dict->requires_slow_elements() || |
11323 dict->max_number_key() >= limit) { | 11232 dict->max_number_key() >= limit) { |
11324 return PrepareSlowElementsForSort(limit); | 11233 return PrepareSlowElementsForSort(limit); |
11325 } | 11234 } |
11326 // Convert to fast elements. | 11235 // Convert to fast elements. |
11327 | 11236 |
11328 Object* obj; | 11237 Object* obj; |
11329 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 11238 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
11330 FAST_HOLEY_ELEMENTS); | 11239 FAST_ELEMENTS); |
11331 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11240 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11241 } |
11332 Map* new_map = Map::cast(obj); | 11242 Map* new_map = Map::cast(obj); |
11333 | 11243 |
11334 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 11244 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
11335 Object* new_array; | 11245 Object* new_array; |
11336 { MaybeObject* maybe_new_array = | 11246 { MaybeObject* maybe_new_array = |
11337 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 11247 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
11338 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 11248 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
11339 } | 11249 } |
11340 FixedArray* fast_elements = FixedArray::cast(new_array); | 11250 FixedArray* fast_elements = FixedArray::cast(new_array); |
11341 dict->CopyValuesTo(fast_elements); | 11251 dict->CopyValuesTo(fast_elements); |
11342 ValidateElements(); | |
11343 | 11252 |
11344 set_map_and_elements(new_map, fast_elements); | 11253 set_map(new_map); |
| 11254 set_elements(fast_elements); |
11345 } else if (HasExternalArrayElements()) { | 11255 } else if (HasExternalArrayElements()) { |
11346 // External arrays cannot have holes or undefined elements. | 11256 // External arrays cannot have holes or undefined elements. |
11347 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 11257 return Smi::FromInt(ExternalArray::cast(elements())->length()); |
11348 } else if (!HasFastDoubleElements()) { | 11258 } else if (!HasFastDoubleElements()) { |
11349 Object* obj; | 11259 Object* obj; |
11350 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 11260 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
11351 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11261 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11352 } | 11262 } |
11353 } | 11263 } |
11354 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); | 11264 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); |
11355 | 11265 |
11356 // Collect holes at the end, undefined before that and the rest at the | 11266 // Collect holes at the end, undefined before that and the rest at the |
11357 // start, and return the number of non-hole, non-undefined values. | 11267 // start, and return the number of non-hole, non-undefined values. |
11358 | 11268 |
11359 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 11269 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
11360 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 11270 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
11361 if (limit > elements_length) { | 11271 if (limit > elements_length) { |
11362 limit = elements_length ; | 11272 limit = elements_length ; |
11363 } | 11273 } |
11364 if (limit == 0) { | 11274 if (limit == 0) { |
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13021 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13022 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13023 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13024 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13025 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13026 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13027 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13028 } | 12938 } |
13029 | 12939 |
13030 } } // namespace v8::internal | 12940 } } // namespace v8::internal |
OLD | NEW |