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