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