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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
895 cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER); | 890 cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER); |
896 return result; | 891 return result; |
897 } | 892 } |
898 default: | 893 default: |
899 return this; | 894 return this; |
900 } | 895 } |
901 } | 896 } |
902 | 897 |
903 | 898 |
904 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 899 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
905 // Externalizing twice leaks the external resource, so it's | 900 // Externalizing twice leaks the external resource, so its prohibited by the |
Jakob Kummerow
2012/05/13 21:55:27
Why this change? Original version was correct.
danno
2012/05/22 11:05:21
Done.
| |
906 // prohibited by the API. | 901 // API. |
907 ASSERT(!this->IsExternalString()); | 902 ASSERT(!this->IsExternalString()); |
908 #ifdef DEBUG | 903 #ifdef DEBUG |
909 if (FLAG_enable_slow_asserts) { | 904 if (FLAG_enable_slow_asserts) { |
910 // Assert that the resource and the string are equivalent. | 905 // Assert that the resource and the string are equivalent. |
911 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 906 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
912 ScopedVector<uc16> smart_chars(this->length()); | 907 ScopedVector<uc16> smart_chars(this->length()); |
913 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 908 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
914 ASSERT(memcmp(smart_chars.start(), | 909 ASSERT(memcmp(smart_chars.start(), |
915 resource->data(), | 910 resource->data(), |
916 resource->length() * sizeof(smart_chars[0])) == 0); | 911 resource->length() * sizeof(smart_chars[0])) == 0); |
(...skipping 143 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 : | |
Jakob Kummerow
2012/05/13 21:55:27
nit: I'd put the colon on the next line, directly
danno
2012/05/22 11:05:21
Done.
| |
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 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2192 | 2189 |
2193 | 2190 |
2194 template <class T> | 2191 template <class T> |
2195 static Handle<T> MaybeNull(T* p) { | 2192 static Handle<T> MaybeNull(T* p) { |
2196 if (p == NULL) return Handle<T>::null(); | 2193 if (p == NULL) return Handle<T>::null(); |
2197 return Handle<T>(p); | 2194 return Handle<T>(p); |
2198 } | 2195 } |
2199 | 2196 |
2200 | 2197 |
2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { | 2198 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
2202 ElementsKind elms_kind = elements_kind(); | 2199 ElementsKind kind = elements_kind(); |
2203 if (elms_kind == FAST_DOUBLE_ELEMENTS) { | 2200 Handle<Map> transitioned_map = Handle<Map>::null(); |
2204 bool dummy = true; | 2201 Handle<Map> current_map(this); |
2205 Handle<Map> fast_map = | 2202 bool packed = IsFastPackedElementsKind(kind); |
2206 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); | 2203 if (IsTransitionableFastElementsKind(kind)) { |
2207 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { | 2204 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { |
2208 return fast_map; | 2205 kind = GetNextMoreGeneralFastElementsKind(kind, false); |
2206 bool dummy = true; | |
2207 Handle<Map> maybe_transitioned_map = | |
2208 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy)); | |
2209 if (maybe_transitioned_map.is_null()) break; | |
2210 if (ContainsMap(candidates, maybe_transitioned_map) && | |
2211 (packed || !IsFastPackedElementsKind(kind))) { | |
2212 transitioned_map = maybe_transitioned_map; | |
2213 if (!IsFastPackedElementsKind(kind)) packed = false; | |
2214 } | |
2215 current_map = maybe_transitioned_map; | |
2209 } | 2216 } |
2210 return Handle<Map>::null(); | |
2211 } | 2217 } |
2212 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { | 2218 return transitioned_map; |
2213 bool dummy = true; | |
2214 Handle<Map> double_map = | |
2215 MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy)); | |
2216 // In the current implementation, if the DOUBLE map doesn't exist, the | |
2217 // FAST map can't exist either. | |
2218 if (double_map.is_null()) return Handle<Map>::null(); | |
2219 Handle<Map> fast_map = | |
2220 MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS, | |
2221 &dummy)); | |
2222 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { | |
2223 return fast_map; | |
2224 } | |
2225 if (ContainsMap(candidates, double_map)) return double_map; | |
2226 } | |
2227 return Handle<Map>::null(); | |
2228 } | 2219 } |
2229 | 2220 |
2221 | |
2230 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | 2222 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
2231 ElementsKind elements_kind) { | 2223 ElementsKind elements_kind) { |
2232 if (descriptor_contents->IsMap()) { | 2224 if (descriptor_contents->IsMap()) { |
2233 Map* map = Map::cast(descriptor_contents); | 2225 Map* map = Map::cast(descriptor_contents); |
2234 if (map->elements_kind() == elements_kind) { | 2226 if (map->elements_kind() == elements_kind) { |
2235 return map; | 2227 return map; |
2236 } | 2228 } |
2237 return NULL; | 2229 return NULL; |
2238 } | 2230 } |
2239 | 2231 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2328 } else { | 2320 } else { |
2329 if (safe_to_add_transition != NULL) { | 2321 if (safe_to_add_transition != NULL) { |
2330 *safe_to_add_transition = false; | 2322 *safe_to_add_transition = false; |
2331 } | 2323 } |
2332 } | 2324 } |
2333 } | 2325 } |
2334 return NULL; | 2326 return NULL; |
2335 } | 2327 } |
2336 | 2328 |
2337 | 2329 |
2338 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, | 2330 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, |
2339 bool* safe_to_add_transition) { | 2331 bool* safe_to_add_transition) { |
2340 // Special case: indirect SMI->FAST transition (cf. comment in | 2332 ElementsKind from_kind = elements_kind(); |
2341 // AddElementsTransition()). | 2333 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
2342 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2334 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
2343 elements_kind == FAST_ELEMENTS) { | 2335 if (safe_to_add_transition) *safe_to_add_transition = false; |
2344 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, | 2336 return NULL; |
2345 safe_to_add_transition); | 2337 } |
2346 if (double_map == NULL) return double_map; | 2338 ElementsKind transitioned_from_kind = |
2347 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, | 2339 GetNextMoreGeneralFastElementsKind(from_kind, false); |
2340 | |
2341 | |
2342 // If the transition is a single step in the transition sequence, fall | |
2343 // through to looking it up and returning it. If it requires several steps, | |
2344 // divide and conquer. | |
2345 if (transitioned_from_kind != to_kind) { | |
2346 // If the transition is several steps in the lattice, divide and conquer. | |
2347 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind, | |
2348 safe_to_add_transition); | |
2349 if (from_map == NULL) return NULL; | |
2350 return from_map->LookupElementsTransitionMap(to_kind, | |
2348 safe_to_add_transition); | 2351 safe_to_add_transition); |
2352 } | |
2349 } | 2353 } |
2350 Object* descriptor_contents = GetDescriptorContents( | 2354 Object* descriptor_contents = GetDescriptorContents( |
2351 elements_transition_sentinel_name(), safe_to_add_transition); | 2355 elements_transition_sentinel_name(), safe_to_add_transition); |
2352 if (descriptor_contents != NULL) { | 2356 if (descriptor_contents != NULL) { |
2353 Map* maybe_transition_map = | 2357 Map* maybe_transition_map = |
2354 GetElementsTransitionMapFromDescriptor(descriptor_contents, | 2358 GetElementsTransitionMapFromDescriptor(descriptor_contents, |
2355 elements_kind); | 2359 to_kind); |
2356 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); | 2360 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); |
2357 return maybe_transition_map; | 2361 return maybe_transition_map; |
2358 } | 2362 } |
2359 return NULL; | 2363 return NULL; |
2360 } | 2364 } |
2361 | 2365 |
2362 | 2366 |
2363 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, | 2367 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, |
2364 Map* transitioned_map) { | 2368 Map* transitioned_map) { |
2365 // The map transition graph should be a tree, therefore the transition | 2369 ElementsKind from_kind = elements_kind(); |
2366 // from SMI to FAST elements is not done directly, but by going through | 2370 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
2367 // DOUBLE elements first. | 2371 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); |
2368 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2372 ElementsKind transitioned_from_kind = |
2369 elements_kind == FAST_ELEMENTS) { | 2373 GetNextMoreGeneralFastElementsKind(from_kind, false); |
2370 bool safe_to_add = true; | 2374 // The map transitions graph should be a tree, therefore transitions to |
2371 Map* double_map = this->LookupElementsTransitionMap( | 2375 // ElementsKind that are not adjacent in the ElementsKind sequence are not |
2372 FAST_DOUBLE_ELEMENTS, &safe_to_add); | 2376 // done directly, but instead by going through intermediate ElementsKinds |
2373 // This method is only called when safe_to_add_transition has been found | 2377 // first. |
2374 // to be true earlier. | 2378 if (to_kind != transitioned_from_kind) { |
2375 ASSERT(safe_to_add); | 2379 bool safe_to_add = true; |
2380 Map* intermediate_map = LookupElementsTransitionMap( | |
2381 transitioned_from_kind, &safe_to_add); | |
2382 // This method is only called when safe_to_add_transition has been found | |
Jakob Kummerow
2012/05/13 21:55:27
nit: s/safe_to_add_transition/safe_to_add/
danno
2012/05/22 11:05:21
Done.
| |
2383 // to be true earlier. | |
2384 ASSERT(safe_to_add); | |
2376 | 2385 |
2377 if (double_map == NULL) { | 2386 if (intermediate_map == NULL) { |
2378 MaybeObject* maybe_map = this->CopyDropTransitions(); | 2387 MaybeObject* maybe_map = CopyDropTransitions(); |
2379 if (!maybe_map->To(&double_map)) return maybe_map; | 2388 if (!maybe_map->To(&intermediate_map)) return maybe_map; |
2380 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); | 2389 intermediate_map->set_elements_kind(transitioned_from_kind); |
2381 MaybeObject* maybe_double_transition = this->AddElementsTransition( | 2390 MaybeObject* maybe_transition = AddElementsTransition( |
2382 FAST_DOUBLE_ELEMENTS, double_map); | 2391 transitioned_from_kind, intermediate_map); |
2383 if (maybe_double_transition->IsFailure()) return maybe_double_transition; | 2392 if (maybe_transition->IsFailure()) return maybe_transition; |
2393 } | |
2394 return intermediate_map->AddElementsTransition(to_kind, transitioned_map); | |
2384 } | 2395 } |
2385 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map); | |
2386 } | 2396 } |
2387 | 2397 |
2388 bool safe_to_add_transition = true; | 2398 bool safe_to_add_transition = true; |
2389 Object* descriptor_contents = GetDescriptorContents( | 2399 Object* descriptor_contents = GetDescriptorContents( |
2390 elements_transition_sentinel_name(), &safe_to_add_transition); | 2400 elements_transition_sentinel_name(), &safe_to_add_transition); |
2391 // This method is only called when safe_to_add_transition has been found | 2401 // This method is only called when safe_to_add_transition has been found |
2392 // to be true earlier. | 2402 // to be true earlier. |
2393 ASSERT(safe_to_add_transition); | 2403 ASSERT(safe_to_add_transition); |
2394 MaybeObject* maybe_new_contents = | 2404 MaybeObject* maybe_new_contents = |
2395 AddElementsTransitionMapToDescriptor(descriptor_contents, | 2405 AddElementsTransitionMapToDescriptor(descriptor_contents, |
(...skipping 30 matching lines...) Expand all Loading... | |
2426 ElementsKind from_kind = current_map->elements_kind(); | 2436 ElementsKind from_kind = current_map->elements_kind(); |
2427 | 2437 |
2428 if (from_kind == to_kind) return current_map; | 2438 if (from_kind == to_kind) return current_map; |
2429 | 2439 |
2430 // Only objects with FastProperties can have DescriptorArrays and can track | 2440 // Only objects with FastProperties can have DescriptorArrays and can track |
2431 // element-related maps. Also don't add descriptors to maps that are shared. | 2441 // element-related maps. Also don't add descriptors to maps that are shared. |
2432 bool safe_to_add_transition = HasFastProperties() && | 2442 bool safe_to_add_transition = HasFastProperties() && |
2433 !current_map->IsUndefined() && | 2443 !current_map->IsUndefined() && |
2434 !current_map->is_shared(); | 2444 !current_map->is_shared(); |
2435 | 2445 |
2436 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects | 2446 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects |
2437 // with elements that switch back and forth between dictionary and fast | 2447 // with elements that switch back and forth between dictionary and fast |
2438 // element mode. | 2448 // element modes. |
2439 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 2449 if (from_kind == DICTIONARY_ELEMENTS && |
2450 IsFastObjectElementsKind(to_kind)) { | |
Jakob Kummerow
2012/05/13 21:55:27
Wouldn't it make sense to check for any FAST kind
danno
2012/05/22 11:05:21
Done.
| |
2440 safe_to_add_transition = false; | 2451 safe_to_add_transition = false; |
2441 } | 2452 } |
2442 | 2453 |
2443 if (safe_to_add_transition) { | 2454 if (safe_to_add_transition) { |
2444 // It's only safe to manipulate the descriptor array if it would be | 2455 // It's only safe to manipulate the descriptor array if it would be |
2445 // safe to add a transition. | 2456 // safe to add a transition. |
2446 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( | 2457 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( |
2447 to_kind, &safe_to_add_transition); | 2458 to_kind, &safe_to_add_transition); |
2448 if (maybe_transition_map != NULL) { | 2459 if (maybe_transition_map != NULL) { |
2449 return maybe_transition_map; | 2460 return maybe_transition_map; |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3465 // Find the backing store. | 3476 // Find the backing store. |
3466 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 3477 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
3467 Map* old_map = array->map(); | 3478 Map* old_map = array->map(); |
3468 bool is_arguments = | 3479 bool is_arguments = |
3469 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 3480 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
3470 if (is_arguments) { | 3481 if (is_arguments) { |
3471 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 3482 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
3472 } | 3483 } |
3473 if (array->IsDictionary()) return array; | 3484 if (array->IsDictionary()) return array; |
3474 | 3485 |
3475 ASSERT(HasFastElements() || | 3486 ASSERT(HasFastSmiOrObjectElements() || |
3476 HasFastSmiOnlyElements() || | |
3477 HasFastDoubleElements() || | 3487 HasFastDoubleElements() || |
3478 HasFastArgumentsElements()); | 3488 HasFastArgumentsElements()); |
3479 // Compute the effective length and allocate a new backing store. | 3489 // Compute the effective length and allocate a new backing store. |
3480 int length = IsJSArray() | 3490 int length = IsJSArray() |
3481 ? Smi::cast(JSArray::cast(this)->length())->value() | 3491 ? Smi::cast(JSArray::cast(this)->length())->value() |
3482 : array->length(); | 3492 : array->length(); |
3483 int old_capacity = 0; | 3493 int old_capacity = 0; |
3484 int used_elements = 0; | 3494 int used_elements = 0; |
3485 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 3495 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
3486 SeededNumberDictionary* dictionary = NULL; | 3496 SeededNumberDictionary* dictionary = NULL; |
(...skipping 14 matching lines...) Expand all Loading... | |
3501 } else { | 3511 } else { |
3502 // Objects must be allocated in the old object space, since the | 3512 // Objects must be allocated in the old object space, since the |
3503 // overall number of HeapNumbers needed for the conversion might | 3513 // overall number of HeapNumbers needed for the conversion might |
3504 // exceed the capacity of new space, and we would fail repeatedly | 3514 // exceed the capacity of new space, and we would fail repeatedly |
3505 // trying to convert the FixedDoubleArray. | 3515 // trying to convert the FixedDoubleArray. |
3506 MaybeObject* maybe_value_object = | 3516 MaybeObject* maybe_value_object = |
3507 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 3517 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
3508 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 3518 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
3509 } | 3519 } |
3510 } else { | 3520 } else { |
3511 ASSERT(old_map->has_fast_elements() || | 3521 ASSERT(old_map->has_fast_smi_or_object_elements()); |
3512 old_map->has_fast_smi_only_elements()); | |
3513 value = FixedArray::cast(array)->get(i); | 3522 value = FixedArray::cast(array)->get(i); |
3514 } | 3523 } |
3515 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 3524 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
3516 if (!value->IsTheHole()) { | 3525 if (!value->IsTheHole()) { |
3517 Object* result; | 3526 Object* result; |
3518 MaybeObject* maybe_result = | 3527 MaybeObject* maybe_result = |
3519 dictionary->AddNumberEntry(i, value, details); | 3528 dictionary->AddNumberEntry(i, value, details); |
3520 if (!maybe_result->ToObject(&result)) return maybe_result; | 3529 if (!maybe_result->ToObject(&result)) return maybe_result; |
3521 dictionary = SeededNumberDictionary::cast(result); | 3530 dictionary = SeededNumberDictionary::cast(result); |
3522 } | 3531 } |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3989 if (IsJSProxy()) { | 3998 if (IsJSProxy()) { |
3990 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); | 3999 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
3991 } | 4000 } |
3992 return JSObject::cast(this)->DeleteProperty(name, mode); | 4001 return JSObject::cast(this)->DeleteProperty(name, mode); |
3993 } | 4002 } |
3994 | 4003 |
3995 | 4004 |
3996 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 4005 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
3997 ElementsKind kind, | 4006 ElementsKind kind, |
3998 Object* object) { | 4007 Object* object) { |
3999 ASSERT(kind == FAST_ELEMENTS || | 4008 ASSERT(IsFastObjectElementsKind(kind) || |
4000 kind == DICTIONARY_ELEMENTS); | 4009 kind == DICTIONARY_ELEMENTS); |
4001 if (kind == FAST_ELEMENTS) { | 4010 if (IsFastObjectElementsKind(kind)) { |
4002 int length = IsJSArray() | 4011 int length = IsJSArray() |
4003 ? Smi::cast(JSArray::cast(this)->length())->value() | 4012 ? Smi::cast(JSArray::cast(this)->length())->value() |
4004 : elements->length(); | 4013 : elements->length(); |
4005 for (int i = 0; i < length; ++i) { | 4014 for (int i = 0; i < length; ++i) { |
4006 Object* element = elements->get(i); | 4015 Object* element = elements->get(i); |
4007 if (!element->IsTheHole() && element == object) return true; | 4016 if (!element->IsTheHole() && element == object) return true; |
4008 } | 4017 } |
4009 } else { | 4018 } else { |
4010 Object* key = | 4019 Object* key = |
4011 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); | 4020 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4043 case EXTERNAL_PIXEL_ELEMENTS: | 4052 case EXTERNAL_PIXEL_ELEMENTS: |
4044 case EXTERNAL_BYTE_ELEMENTS: | 4053 case EXTERNAL_BYTE_ELEMENTS: |
4045 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4054 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4046 case EXTERNAL_SHORT_ELEMENTS: | 4055 case EXTERNAL_SHORT_ELEMENTS: |
4047 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4056 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4048 case EXTERNAL_INT_ELEMENTS: | 4057 case EXTERNAL_INT_ELEMENTS: |
4049 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4058 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4050 case EXTERNAL_FLOAT_ELEMENTS: | 4059 case EXTERNAL_FLOAT_ELEMENTS: |
4051 case EXTERNAL_DOUBLE_ELEMENTS: | 4060 case EXTERNAL_DOUBLE_ELEMENTS: |
4052 case FAST_DOUBLE_ELEMENTS: | 4061 case FAST_DOUBLE_ELEMENTS: |
4062 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4053 // Raw pixels and external arrays do not reference other | 4063 // Raw pixels and external arrays do not reference other |
4054 // objects. | 4064 // objects. |
4055 break; | 4065 break; |
4056 case FAST_SMI_ONLY_ELEMENTS: | 4066 case FAST_SMI_ELEMENTS: |
4067 case FAST_HOLEY_SMI_ELEMENTS: | |
4057 break; | 4068 break; |
4058 case FAST_ELEMENTS: | 4069 case FAST_ELEMENTS: |
4070 case FAST_HOLEY_ELEMENTS: | |
4059 case DICTIONARY_ELEMENTS: { | 4071 case DICTIONARY_ELEMENTS: { |
4060 FixedArray* elements = FixedArray::cast(this->elements()); | 4072 FixedArray* elements = FixedArray::cast(this->elements()); |
4061 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 4073 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
4062 break; | 4074 break; |
4063 } | 4075 } |
4064 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 4076 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
4065 FixedArray* parameter_map = FixedArray::cast(elements()); | 4077 FixedArray* parameter_map = FixedArray::cast(elements()); |
4066 // Check the mapped parameters. | 4078 // Check the mapped parameters. |
4067 int length = parameter_map->length(); | 4079 int length = parameter_map->length(); |
4068 for (int i = 2; i < length; ++i) { | 4080 for (int i = 2; i < length; ++i) { |
4069 Object* value = parameter_map->get(i); | 4081 Object* value = parameter_map->get(i); |
4070 if (!value->IsTheHole() && value == obj) return true; | 4082 if (!value->IsTheHole() && value == obj) return true; |
4071 } | 4083 } |
4072 // Check the arguments. | 4084 // Check the arguments. |
4073 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 4085 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
4074 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; | 4086 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
4087 FAST_HOLEY_ELEMENTS; | |
4075 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 4088 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
4076 break; | 4089 break; |
4077 } | 4090 } |
4078 } | 4091 } |
4079 | 4092 |
4080 // For functions check the context. | 4093 // For functions check the context. |
4081 if (IsJSFunction()) { | 4094 if (IsJSFunction()) { |
4082 // Get the constructor function for arguments array. | 4095 // Get the constructor function for arguments array. |
4083 JSObject* arguments_boilerplate = | 4096 JSObject* arguments_boilerplate = |
4084 heap->isolate()->context()->global_context()-> | 4097 heap->isolate()->context()->global_context()-> |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4298 for (Object* current = this; | 4311 for (Object* current = this; |
4299 current != heap->null_value(); | 4312 current != heap->null_value(); |
4300 current = JSObject::cast(current)->GetPrototype()) { | 4313 current = JSObject::cast(current)->GetPrototype()) { |
4301 JSReceiver::cast(current)->LocalLookup(name, result); | 4314 JSReceiver::cast(current)->LocalLookup(name, result); |
4302 if (result->IsProperty()) return; | 4315 if (result->IsProperty()) return; |
4303 } | 4316 } |
4304 result->NotFound(); | 4317 result->NotFound(); |
4305 } | 4318 } |
4306 | 4319 |
4307 | 4320 |
4308 // Search object and it's prototype chain for callback properties. | 4321 // Search object and its prototype chain for callback properties. |
4309 void JSObject::LookupCallback(String* name, LookupResult* result) { | 4322 void JSObject::LookupCallback(String* name, LookupResult* result) { |
4310 Heap* heap = GetHeap(); | 4323 Heap* heap = GetHeap(); |
4311 for (Object* current = this; | 4324 for (Object* current = this; |
4312 current != heap->null_value() && current->IsJSObject(); | 4325 current != heap->null_value() && current->IsJSObject(); |
4313 current = JSObject::cast(current)->GetPrototype()) { | 4326 current = JSObject::cast(current)->GetPrototype()) { |
4314 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4327 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
4315 if (result->IsFound() && result->type() == CALLBACKS) return; | 4328 if (result->IsFound() && result->type() == CALLBACKS) return; |
4316 } | 4329 } |
4317 result->NotFound(); | 4330 result->NotFound(); |
4318 } | 4331 } |
(...skipping 23 matching lines...) Expand all Loading... | |
4342 } | 4355 } |
4343 return false; | 4356 return false; |
4344 } | 4357 } |
4345 | 4358 |
4346 | 4359 |
4347 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 4360 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, |
4348 Object* getter, | 4361 Object* getter, |
4349 Object* setter, | 4362 Object* setter, |
4350 PropertyAttributes attributes) { | 4363 PropertyAttributes attributes) { |
4351 switch (GetElementsKind()) { | 4364 switch (GetElementsKind()) { |
4352 case FAST_SMI_ONLY_ELEMENTS: | 4365 case FAST_SMI_ELEMENTS: |
4353 case FAST_ELEMENTS: | 4366 case FAST_ELEMENTS: |
4354 case FAST_DOUBLE_ELEMENTS: | 4367 case FAST_DOUBLE_ELEMENTS: |
4368 case FAST_HOLEY_SMI_ELEMENTS: | |
4369 case FAST_HOLEY_ELEMENTS: | |
4370 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4355 break; | 4371 break; |
4356 case EXTERNAL_PIXEL_ELEMENTS: | 4372 case EXTERNAL_PIXEL_ELEMENTS: |
4357 case EXTERNAL_BYTE_ELEMENTS: | 4373 case EXTERNAL_BYTE_ELEMENTS: |
4358 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4374 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4359 case EXTERNAL_SHORT_ELEMENTS: | 4375 case EXTERNAL_SHORT_ELEMENTS: |
4360 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4376 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4361 case EXTERNAL_INT_ELEMENTS: | 4377 case EXTERNAL_INT_ELEMENTS: |
4362 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4378 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4363 case EXTERNAL_FLOAT_ELEMENTS: | 4379 case EXTERNAL_FLOAT_ELEMENTS: |
4364 case EXTERNAL_DOUBLE_ELEMENTS: | 4380 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4461 accessors->SetComponents(getter, setter); | 4477 accessors->SetComponents(getter, setter); |
4462 return SetPropertyCallback(name, accessors, attributes); | 4478 return SetPropertyCallback(name, accessors, attributes); |
4463 } | 4479 } |
4464 | 4480 |
4465 | 4481 |
4466 bool JSObject::CanSetCallback(String* name) { | 4482 bool JSObject::CanSetCallback(String* name) { |
4467 ASSERT(!IsAccessCheckNeeded() || | 4483 ASSERT(!IsAccessCheckNeeded() || |
4468 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4484 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
4469 | 4485 |
4470 // Check if there is an API defined callback object which prohibits | 4486 // Check if there is an API defined callback object which prohibits |
4471 // callback overwriting in this object or it's prototype chain. | 4487 // callback overwriting in this object or its prototype chain. |
4472 // This mechanism is needed for instance in a browser setting, where | 4488 // This mechanism is needed for instance in a browser setting, where |
4473 // certain accessors such as window.location should not be allowed | 4489 // certain accessors such as window.location should not be allowed |
4474 // to be overwritten because allowing overwriting could potentially | 4490 // to be overwritten because allowing overwriting could potentially |
4475 // cause security problems. | 4491 // cause security problems. |
4476 LookupResult callback_result(GetIsolate()); | 4492 LookupResult callback_result(GetIsolate()); |
4477 LookupCallback(name, &callback_result); | 4493 LookupCallback(name, &callback_result); |
4478 if (callback_result.IsProperty()) { | 4494 if (callback_result.IsProperty()) { |
4479 Object* obj = callback_result.GetCallbackObject(); | 4495 Object* obj = callback_result.GetCallbackObject(); |
4480 if (obj->IsAccessorInfo() && | 4496 if (obj->IsAccessorInfo() && |
4481 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4497 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4783 } | 4799 } |
4784 | 4800 |
4785 uint32_t index = 0; | 4801 uint32_t index = 0; |
4786 bool is_element = name->AsArrayIndex(&index); | 4802 bool is_element = name->AsArrayIndex(&index); |
4787 | 4803 |
4788 if (is_element) { | 4804 if (is_element) { |
4789 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4805 if (IsJSArray()) return isolate->heap()->undefined_value(); |
4790 | 4806 |
4791 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4807 // Accessors overwrite previous callbacks (cf. with getters/setters). |
4792 switch (GetElementsKind()) { | 4808 switch (GetElementsKind()) { |
4793 case FAST_SMI_ONLY_ELEMENTS: | 4809 case FAST_SMI_ELEMENTS: |
4794 case FAST_ELEMENTS: | 4810 case FAST_ELEMENTS: |
4795 case FAST_DOUBLE_ELEMENTS: | 4811 case FAST_DOUBLE_ELEMENTS: |
4812 case FAST_HOLEY_SMI_ELEMENTS: | |
4813 case FAST_HOLEY_ELEMENTS: | |
4814 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
4796 break; | 4815 break; |
4797 case EXTERNAL_PIXEL_ELEMENTS: | 4816 case EXTERNAL_PIXEL_ELEMENTS: |
4798 case EXTERNAL_BYTE_ELEMENTS: | 4817 case EXTERNAL_BYTE_ELEMENTS: |
4799 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4818 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4800 case EXTERNAL_SHORT_ELEMENTS: | 4819 case EXTERNAL_SHORT_ELEMENTS: |
4801 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4820 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4802 case EXTERNAL_INT_ELEMENTS: | 4821 case EXTERNAL_INT_ELEMENTS: |
4803 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4822 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4804 case EXTERNAL_FLOAT_ELEMENTS: | 4823 case EXTERNAL_FLOAT_ELEMENTS: |
4805 case EXTERNAL_DOUBLE_ELEMENTS: | 4824 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 3832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8638 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 8657 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
8639 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8658 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
8640 PrintF(out, "\n"); | 8659 PrintF(out, "\n"); |
8641 } | 8660 } |
8642 #endif // ENABLE_DISASSEMBLER | 8661 #endif // ENABLE_DISASSEMBLER |
8643 | 8662 |
8644 | 8663 |
8645 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8664 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
8646 int capacity, | 8665 int capacity, |
8647 int length, | 8666 int length, |
8648 SetFastElementsCapacityMode set_capacity_mode) { | 8667 SetFastElementsCapacitySmiMode smi_mode) { |
8649 Heap* heap = GetHeap(); | 8668 Heap* heap = GetHeap(); |
8650 // We should never end in here with a pixel or external array. | 8669 // We should never end in here with a pixel or external array. |
8651 ASSERT(!HasExternalArrayElements()); | 8670 ASSERT(!HasExternalArrayElements()); |
8652 | 8671 |
8653 // Allocate a new fast elements backing store. | 8672 // Allocate a new fast elements backing store. |
8654 FixedArray* new_elements; | 8673 FixedArray* new_elements; |
8655 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 8674 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
8656 if (!maybe->To(&new_elements)) return maybe; | 8675 if (!maybe->To(&new_elements)) return maybe; |
8657 } | 8676 } |
8658 | 8677 |
8659 // Find the new map to use for this object if there is a map change. | 8678 ElementsKind elements_kind = GetElementsKind(); |
8660 Map* new_map = NULL; | 8679 ElementsKind new_elements_kind; |
8661 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 8680 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
8662 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces | 8681 // or if it's allowed and the old elements array contained only SMIs. |
8663 // it, or if it's allowed and the old elements array contained only SMIs. | 8682 bool has_fast_smi_elements = |
8664 bool has_fast_smi_only_elements = | 8683 (smi_mode == kForceSmiOnlyElements) || |
8665 (set_capacity_mode == kForceSmiOnlyElements) || | 8684 ((smi_mode == kAllowSmiOnlyElements) && HasFastSmiElements()); |
8666 ((set_capacity_mode == kAllowSmiOnlyElements) && | 8685 if (has_fast_smi_elements) { |
8667 (elements()->map()->has_fast_smi_only_elements() || | 8686 if (IsHoleyElementsKind(elements_kind)) { |
8668 elements() == heap->empty_fixed_array())); | 8687 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; |
8669 ElementsKind elements_kind = has_fast_smi_only_elements | 8688 } else { |
8670 ? FAST_SMI_ONLY_ELEMENTS | 8689 new_elements_kind = FAST_SMI_ELEMENTS; |
8671 : FAST_ELEMENTS; | 8690 } |
8672 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | 8691 } else { |
8673 if (!maybe->To(&new_map)) return maybe; | 8692 if (IsHoleyElementsKind(elements_kind)) { |
8693 new_elements_kind = FAST_HOLEY_ELEMENTS; | |
8694 } else { | |
8695 new_elements_kind = FAST_ELEMENTS; | |
8696 } | |
8674 } | 8697 } |
8675 | |
8676 FixedArrayBase* old_elements = elements(); | 8698 FixedArrayBase* old_elements = elements(); |
8677 ElementsKind elements_kind = GetElementsKind(); | |
8678 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8699 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8679 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) | 8700 accessor->CopyElements(this, new_elements, new_elements_kind); |
8680 ? FAST_SMI_ONLY_ELEMENTS | |
8681 : FAST_ELEMENTS; | |
8682 // int copy_size = Min(old_elements_raw->length(), new_elements->length()); | |
8683 accessor->CopyElements(this, new_elements, to_kind); | |
8684 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8701 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
8702 Map* new_map = map(); | |
8703 if (new_elements_kind != elements_kind) { | |
8704 MaybeObject* maybe = | |
8705 GetElementsTransitionMap(GetIsolate(), new_elements_kind); | |
8706 if (!maybe->To(&new_map)) return maybe; | |
8707 } | |
8708 ValidateElements(); | |
8685 set_map_and_elements(new_map, new_elements); | 8709 set_map_and_elements(new_map, new_elements); |
8686 } else { | 8710 } else { |
8687 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8711 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8688 parameter_map->set(1, new_elements); | 8712 parameter_map->set(1, new_elements); |
8689 } | 8713 } |
8690 | 8714 |
8691 if (FLAG_trace_elements_transitions) { | 8715 if (FLAG_trace_elements_transitions) { |
8692 PrintElementsTransition(stdout, elements_kind, old_elements, | 8716 PrintElementsTransition(stdout, elements_kind, old_elements, |
8693 GetElementsKind(), new_elements); | 8717 GetElementsKind(), new_elements); |
8694 } | 8718 } |
8695 | 8719 |
8696 // Update the length if necessary. | |
8697 if (IsJSArray()) { | 8720 if (IsJSArray()) { |
8698 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8721 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8699 } | 8722 } |
8700 | |
8701 return new_elements; | 8723 return new_elements; |
8702 } | 8724 } |
8703 | 8725 |
8704 | 8726 |
8705 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8727 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
8706 int capacity, | 8728 int capacity, |
8707 int length) { | 8729 int length) { |
8708 Heap* heap = GetHeap(); | 8730 Heap* heap = GetHeap(); |
8709 // We should never end in here with a pixel or external array. | 8731 // We should never end in here with a pixel or external array. |
8710 ASSERT(!HasExternalArrayElements()); | 8732 ASSERT(!HasExternalArrayElements()); |
8711 | 8733 |
8712 FixedDoubleArray* elems; | 8734 FixedDoubleArray* elems; |
8713 { MaybeObject* maybe_obj = | 8735 { MaybeObject* maybe_obj = |
8714 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8736 heap->AllocateUninitializedFixedDoubleArray(capacity); |
8715 if (!maybe_obj->To(&elems)) return maybe_obj; | 8737 if (!maybe_obj->To(&elems)) return maybe_obj; |
8716 } | 8738 } |
8717 | 8739 |
8740 ElementsKind elements_kind = GetElementsKind(); | |
8741 ElementsKind new_elements_kind = elements_kind; | |
8742 if (IsHoleyElementsKind(elements_kind)) { | |
8743 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; | |
8744 } else { | |
8745 new_elements_kind = FAST_DOUBLE_ELEMENTS; | |
8746 } | |
8747 | |
8718 Map* new_map; | 8748 Map* new_map; |
8719 { MaybeObject* maybe_obj = | 8749 { MaybeObject* maybe_obj = |
8720 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); | 8750 GetElementsTransitionMap(heap->isolate(), new_elements_kind); |
8721 if (!maybe_obj->To(&new_map)) return maybe_obj; | 8751 if (!maybe_obj->To(&new_map)) return maybe_obj; |
8722 } | 8752 } |
8723 | 8753 |
8724 FixedArrayBase* old_elements = elements(); | 8754 FixedArrayBase* old_elements = elements(); |
8725 ElementsKind elements_kind = GetElementsKind(); | |
8726 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8755 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
8727 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); | 8756 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); |
8728 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8757 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
8758 ValidateElements(); | |
8729 set_map_and_elements(new_map, elems); | 8759 set_map_and_elements(new_map, elems); |
8730 } else { | 8760 } else { |
8731 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8761 FixedArray* parameter_map = FixedArray::cast(old_elements); |
8732 parameter_map->set(1, elems); | 8762 parameter_map->set(1, elems); |
8733 } | 8763 } |
8734 | 8764 |
8735 if (FLAG_trace_elements_transitions) { | 8765 if (FLAG_trace_elements_transitions) { |
8736 PrintElementsTransition(stdout, elements_kind, old_elements, | 8766 PrintElementsTransition(stdout, elements_kind, old_elements, |
8737 FAST_DOUBLE_ELEMENTS, elems); | 8767 GetElementsKind(), elems); |
8738 } | 8768 } |
8739 | 8769 |
8740 if (IsJSArray()) { | 8770 if (IsJSArray()) { |
8741 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8771 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
8742 } | 8772 } |
8743 | 8773 |
8744 return this; | 8774 return this; |
8745 } | 8775 } |
8746 | 8776 |
8747 | 8777 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9007 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 9037 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
9008 : UNDEFINED_ELEMENT; | 9038 : UNDEFINED_ELEMENT; |
9009 } | 9039 } |
9010 | 9040 |
9011 // Handle [] on String objects. | 9041 // Handle [] on String objects. |
9012 if (this->IsStringObjectWithCharacterAt(index)) { | 9042 if (this->IsStringObjectWithCharacterAt(index)) { |
9013 return STRING_CHARACTER_ELEMENT; | 9043 return STRING_CHARACTER_ELEMENT; |
9014 } | 9044 } |
9015 | 9045 |
9016 switch (GetElementsKind()) { | 9046 switch (GetElementsKind()) { |
9017 case FAST_SMI_ONLY_ELEMENTS: | 9047 case FAST_SMI_ELEMENTS: |
9018 case FAST_ELEMENTS: { | 9048 case FAST_ELEMENTS: |
9049 case FAST_HOLEY_SMI_ELEMENTS: | |
9050 case FAST_HOLEY_ELEMENTS: { | |
9019 uint32_t length = IsJSArray() ? | 9051 uint32_t length = IsJSArray() ? |
9020 static_cast<uint32_t> | 9052 static_cast<uint32_t> |
9021 (Smi::cast(JSArray::cast(this)->length())->value()) : | 9053 (Smi::cast(JSArray::cast(this)->length())->value()) : |
9022 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9054 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
9023 if ((index < length) && | 9055 if ((index < length) && |
9024 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 9056 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
9025 return FAST_ELEMENT; | 9057 return FAST_ELEMENT; |
9026 } | 9058 } |
9027 break; | 9059 break; |
9028 } | 9060 } |
9029 case FAST_DOUBLE_ELEMENTS: { | 9061 case FAST_DOUBLE_ELEMENTS: |
9062 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
9030 uint32_t length = IsJSArray() ? | 9063 uint32_t length = IsJSArray() ? |
9031 static_cast<uint32_t> | 9064 static_cast<uint32_t> |
9032 (Smi::cast(JSArray::cast(this)->length())->value()) : | 9065 (Smi::cast(JSArray::cast(this)->length())->value()) : |
9033 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 9066 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
9034 if ((index < length) && | 9067 if ((index < length) && |
9035 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | 9068 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
9036 return FAST_ELEMENT; | 9069 return FAST_ELEMENT; |
9037 } | 9070 } |
9038 break; | 9071 break; |
9039 } | 9072 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9303 } | 9336 } |
9304 | 9337 |
9305 | 9338 |
9306 // Adding n elements in fast case is O(n*n). | 9339 // Adding n elements in fast case is O(n*n). |
9307 // Note: revisit design to have dual undefined values to capture absent | 9340 // Note: revisit design to have dual undefined values to capture absent |
9308 // elements. | 9341 // elements. |
9309 MaybeObject* JSObject::SetFastElement(uint32_t index, | 9342 MaybeObject* JSObject::SetFastElement(uint32_t index, |
9310 Object* value, | 9343 Object* value, |
9311 StrictModeFlag strict_mode, | 9344 StrictModeFlag strict_mode, |
9312 bool check_prototype) { | 9345 bool check_prototype) { |
9313 ASSERT(HasFastTypeElements() || | 9346 ASSERT(HasFastSmiOrObjectElements() || |
9314 HasFastArgumentsElements()); | 9347 HasFastArgumentsElements()); |
9315 | 9348 |
9316 FixedArray* backing_store = FixedArray::cast(elements()); | 9349 FixedArray* backing_store = FixedArray::cast(elements()); |
9317 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9350 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
9318 backing_store = FixedArray::cast(backing_store->get(1)); | 9351 backing_store = FixedArray::cast(backing_store->get(1)); |
9319 } else { | 9352 } else { |
9320 MaybeObject* maybe = EnsureWritableFastElements(); | 9353 MaybeObject* maybe = EnsureWritableFastElements(); |
9321 if (!maybe->To(&backing_store)) return maybe; | 9354 if (!maybe->To(&backing_store)) return maybe; |
9322 } | 9355 } |
9323 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 9356 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
9324 | 9357 |
9325 if (check_prototype && | 9358 if (check_prototype && |
9326 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 9359 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
9327 bool found; | 9360 bool found; |
9328 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9361 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9329 value, | 9362 value, |
9330 &found, | 9363 &found, |
9331 strict_mode); | 9364 strict_mode); |
9332 if (found) return result; | 9365 if (found) return result; |
9333 } | 9366 } |
9334 | 9367 |
9335 uint32_t new_capacity = capacity; | 9368 uint32_t new_capacity = capacity; |
9336 // Check if the length property of this object needs to be updated. | 9369 // Check if the length property of this object needs to be updated. |
9337 uint32_t array_length = 0; | 9370 uint32_t array_length = 0; |
9338 bool must_update_array_length = false; | 9371 bool must_update_array_length = false; |
9372 bool introduces_holes = true; | |
9339 if (IsJSArray()) { | 9373 if (IsJSArray()) { |
9340 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9374 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9375 introduces_holes = index > array_length; | |
9341 if (index >= array_length) { | 9376 if (index >= array_length) { |
9342 must_update_array_length = true; | 9377 must_update_array_length = true; |
9343 array_length = index + 1; | 9378 array_length = index + 1; |
9344 } | 9379 } |
9380 } else { | |
9381 introduces_holes = index >= capacity; | |
9345 } | 9382 } |
9383 | |
9384 // If the array is growing, and it's not growth by a single element at the | |
9385 // end, make sure that the ElementsKind is HOLEY. | |
9386 ElementsKind elements_kind = GetElementsKind(); | |
9387 if (introduces_holes && | |
9388 IsFastElementsKind(elements_kind) && | |
9389 !IsFastHoleyElementsKind(elements_kind)) { | |
9390 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | |
9391 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | |
9392 if (maybe->IsFailure()) return maybe; | |
9393 } | |
9394 | |
9346 // Check if the capacity of the backing store needs to be increased, or if | 9395 // Check if the capacity of the backing store needs to be increased, or if |
9347 // a transition to slow elements is necessary. | 9396 // a transition to slow elements is necessary. |
9348 if (index >= capacity) { | 9397 if (index >= capacity) { |
9349 bool convert_to_slow = true; | 9398 bool convert_to_slow = true; |
9350 if ((index - capacity) < kMaxGap) { | 9399 if ((index - capacity) < kMaxGap) { |
9351 new_capacity = NewElementsCapacity(index + 1); | 9400 new_capacity = NewElementsCapacity(index + 1); |
9352 ASSERT(new_capacity > index); | 9401 ASSERT(new_capacity > index); |
9353 if (!ShouldConvertToSlowElements(new_capacity)) { | 9402 if (!ShouldConvertToSlowElements(new_capacity)) { |
9354 convert_to_slow = false; | 9403 convert_to_slow = false; |
9355 } | 9404 } |
9356 } | 9405 } |
9357 if (convert_to_slow) { | 9406 if (convert_to_slow) { |
9358 MaybeObject* result = NormalizeElements(); | 9407 MaybeObject* result = NormalizeElements(); |
9359 if (result->IsFailure()) return result; | 9408 if (result->IsFailure()) return result; |
9360 return SetDictionaryElement(index, value, NONE, strict_mode, | 9409 return SetDictionaryElement(index, value, NONE, strict_mode, |
9361 check_prototype); | 9410 check_prototype); |
9362 } | 9411 } |
9363 } | 9412 } |
9364 // Convert to fast double elements if appropriate. | 9413 // Convert to fast double elements if appropriate. |
9365 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { | 9414 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
9366 MaybeObject* maybe = | 9415 MaybeObject* maybe = |
9367 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9416 SetFastDoubleElementsCapacityAndLength(new_capacity, |
9417 array_length); | |
Jakob Kummerow
2012/05/13 21:55:27
nit: why the line break?
danno
2012/05/22 11:05:21
Done.
| |
9368 if (maybe->IsFailure()) return maybe; | 9418 if (maybe->IsFailure()) return maybe; |
9369 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9419 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
9420 ValidateElements(); | |
9370 return value; | 9421 return value; |
9371 } | 9422 } |
9372 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9423 // Change elements kind from Smi-only to generic FAST if necessary. |
9373 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9424 if (HasFastSmiElements() && !value->IsSmi()) { |
9374 Map* new_map; | 9425 Map* new_map; |
9375 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 9426 ElementsKind kind = HasFastHoleyElements() |
9376 FAST_ELEMENTS); | 9427 ? FAST_HOLEY_ELEMENTS |
9377 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9428 : FAST_ELEMENTS; |
9378 } | 9429 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
9430 kind); | |
9431 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
9432 | |
9379 set_map(new_map); | 9433 set_map(new_map); |
9380 if (FLAG_trace_elements_transitions) { | |
Jakob Kummerow
2012/05/13 21:55:27
I don't see why you would remove this.
danno
2012/05/22 11:05:21
Because it's a dupe of the transition printing don
| |
9381 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), | |
9382 FAST_ELEMENTS, elements()); | |
9383 } | |
9384 } | 9434 } |
9385 // Increase backing store capacity if that's been decided previously. | 9435 // Increase backing store capacity if that's been decided previously. |
9386 if (new_capacity != capacity) { | 9436 if (new_capacity != capacity) { |
9387 FixedArray* new_elements; | 9437 FixedArray* new_elements; |
9388 SetFastElementsCapacityMode set_capacity_mode = | 9438 SetFastElementsCapacitySmiMode smi_mode = |
9389 value->IsSmi() && HasFastSmiOnlyElements() | 9439 value->IsSmi() && HasFastSmiElements() |
9390 ? kAllowSmiOnlyElements | 9440 ? kAllowSmiOnlyElements |
9391 : kDontAllowSmiOnlyElements; | 9441 : kDontAllowSmiOnlyElements; |
9392 { MaybeObject* maybe = | 9442 { MaybeObject* maybe = |
9393 SetFastElementsCapacityAndLength(new_capacity, | 9443 SetFastElementsCapacityAndLength(new_capacity, |
9394 array_length, | 9444 array_length, |
9395 set_capacity_mode); | 9445 smi_mode); |
9396 if (!maybe->To(&new_elements)) return maybe; | 9446 if (!maybe->To(&new_elements)) return maybe; |
9397 } | 9447 } |
9398 new_elements->set(index, value); | 9448 new_elements->set(index, value); |
9449 #if DEBUG | |
9450 ValidateElements(); | |
Jakob Kummerow
2012/05/13 21:55:27
Calls to ValidateElements() aren't wrapped in an #
danno
2012/05/22 11:05:21
Done.
| |
9451 #endif | |
9399 return value; | 9452 return value; |
9400 } | 9453 } |
9454 | |
9401 // Finally, set the new element and length. | 9455 // Finally, set the new element and length. |
9402 ASSERT(elements()->IsFixedArray()); | 9456 ASSERT(elements()->IsFixedArray()); |
9403 backing_store->set(index, value); | 9457 backing_store->set(index, value); |
9404 if (must_update_array_length) { | 9458 if (must_update_array_length) { |
9405 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 9459 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); |
9406 } | 9460 } |
9407 return value; | 9461 return value; |
9408 } | 9462 } |
9409 | 9463 |
9410 | 9464 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9514 } | 9568 } |
9515 | 9569 |
9516 // Attempt to put this object back in fast case. | 9570 // Attempt to put this object back in fast case. |
9517 if (ShouldConvertToFastElements()) { | 9571 if (ShouldConvertToFastElements()) { |
9518 uint32_t new_length = 0; | 9572 uint32_t new_length = 0; |
9519 if (IsJSArray()) { | 9573 if (IsJSArray()) { |
9520 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 9574 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
9521 } else { | 9575 } else { |
9522 new_length = dictionary->max_number_key() + 1; | 9576 new_length = dictionary->max_number_key() + 1; |
9523 } | 9577 } |
9524 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays | 9578 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays |
9525 ? kAllowSmiOnlyElements | 9579 ? kAllowSmiOnlyElements |
9526 : kDontAllowSmiOnlyElements; | 9580 : kDontAllowSmiOnlyElements; |
9527 bool has_smi_only_elements = false; | 9581 bool has_smi_only_elements = false; |
9528 bool should_convert_to_fast_double_elements = | 9582 bool should_convert_to_fast_double_elements = |
9529 ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 9583 ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
9530 if (has_smi_only_elements) { | 9584 if (has_smi_only_elements) { |
9531 set_capacity_mode = kForceSmiOnlyElements; | 9585 smi_mode = kForceSmiOnlyElements; |
9532 } | 9586 } |
9533 MaybeObject* result = should_convert_to_fast_double_elements | 9587 MaybeObject* result = should_convert_to_fast_double_elements |
9534 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 9588 ? SetFastDoubleElementsCapacityAndLength(new_length, |
Jakob Kummerow
2012/05/13 21:55:27
nit: why the line break?
danno
2012/05/22 11:05:21
Done.
| |
9589 new_length) | |
9535 : SetFastElementsCapacityAndLength(new_length, | 9590 : SetFastElementsCapacityAndLength(new_length, |
9536 new_length, | 9591 new_length, |
9537 set_capacity_mode); | 9592 smi_mode); |
9593 ValidateElements(); | |
9538 if (result->IsFailure()) return result; | 9594 if (result->IsFailure()) return result; |
9539 #ifdef DEBUG | 9595 #ifdef DEBUG |
9540 if (FLAG_trace_normalization) { | 9596 if (FLAG_trace_normalization) { |
9541 PrintF("Object elements are fast case again:\n"); | 9597 PrintF("Object elements are fast case again:\n"); |
9542 Print(); | 9598 Print(); |
9543 } | 9599 } |
9544 #endif | 9600 #endif |
9545 } | 9601 } |
9546 return value; | 9602 return value; |
9547 } | 9603 } |
(...skipping 18 matching lines...) Expand all Loading... | |
9566 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9622 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
9567 value, | 9623 value, |
9568 &found, | 9624 &found, |
9569 strict_mode); | 9625 strict_mode); |
9570 if (found) return result; | 9626 if (found) return result; |
9571 } | 9627 } |
9572 | 9628 |
9573 // If the value object is not a heap number, switch to fast elements and try | 9629 // If the value object is not a heap number, switch to fast elements and try |
9574 // again. | 9630 // again. |
9575 bool value_is_smi = value->IsSmi(); | 9631 bool value_is_smi = value->IsSmi(); |
9632 bool introduces_holes = true; | |
9633 uint32_t length = elms_length; | |
9634 if (IsJSArray()) { | |
9635 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
9636 introduces_holes = index > length; | |
9637 } else { | |
9638 introduces_holes = index >= elms_length; | |
9639 } | |
9640 | |
9576 if (!value->IsNumber()) { | 9641 if (!value->IsNumber()) { |
9577 Object* obj; | |
9578 uint32_t length = elms_length; | |
9579 if (IsJSArray()) { | |
9580 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
9581 } | |
9582 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 9642 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
9583 elms_length, | 9643 elms_length, |
9584 length, | 9644 length, |
9585 kDontAllowSmiOnlyElements); | 9645 kDontAllowSmiOnlyElements); |
9586 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9646 if (maybe_obj->IsFailure()) return maybe_obj; |
9587 return SetFastElement(index, | 9647 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); |
9588 value, | 9648 if (maybe_obj->IsFailure()) return maybe_obj; |
9589 strict_mode, | 9649 ValidateElements(); |
9590 check_prototype); | 9650 return maybe_obj; |
9591 } | 9651 } |
9592 | 9652 |
9593 double double_value = value_is_smi | 9653 double double_value = value_is_smi |
9594 ? static_cast<double>(Smi::cast(value)->value()) | 9654 ? static_cast<double>(Smi::cast(value)->value()) |
9595 : HeapNumber::cast(value)->value(); | 9655 : HeapNumber::cast(value)->value(); |
9596 | 9656 |
9657 // If the array is growing, and it's not growth by a single element at the | |
9658 // end, make sure that the ElementsKind is HOLEY. | |
9659 ElementsKind elements_kind = GetElementsKind(); | |
9660 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { | |
9661 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | |
9662 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | |
9663 if (maybe->IsFailure()) return maybe; | |
9664 } | |
9665 | |
9597 // Check whether there is extra space in the fixed array. | 9666 // Check whether there is extra space in the fixed array. |
9598 if (index < elms_length) { | 9667 if (index < elms_length) { |
9599 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9668 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
9600 elms->set(index, double_value); | 9669 elms->set(index, double_value); |
9601 if (IsJSArray()) { | 9670 if (IsJSArray()) { |
9602 // Update the length of the array if needed. | 9671 // Update the length of the array if needed. |
9603 uint32_t array_length = 0; | 9672 uint32_t array_length = 0; |
9604 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9673 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
9605 if (index >= array_length) { | 9674 if (index >= array_length) { |
9606 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 9675 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
9607 } | 9676 } |
9608 } | 9677 } |
9609 return value; | 9678 return value; |
9610 } | 9679 } |
9611 | 9680 |
9612 // Allow gap in fast case. | 9681 // Allow gap in fast case. |
9613 if ((index - elms_length) < kMaxGap) { | 9682 if ((index - elms_length) < kMaxGap) { |
9614 // Try allocating extra space. | 9683 // Try allocating extra space. |
9615 int new_capacity = NewElementsCapacity(index+1); | 9684 int new_capacity = NewElementsCapacity(index+1); |
9616 if (!ShouldConvertToSlowElements(new_capacity)) { | 9685 if (!ShouldConvertToSlowElements(new_capacity)) { |
9617 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 9686 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
9618 Object* obj; | 9687 MaybeObject* maybe_obj = |
9619 { MaybeObject* maybe_obj = | 9688 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); |
9620 SetFastDoubleElementsCapacityAndLength(new_capacity, | 9689 if (maybe_obj->IsFailure()) return maybe_obj; |
9621 index + 1); | |
9622 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
9623 } | |
9624 FixedDoubleArray::cast(elements())->set(index, double_value); | 9690 FixedDoubleArray::cast(elements())->set(index, double_value); |
9691 ValidateElements(); | |
9625 return value; | 9692 return value; |
9626 } | 9693 } |
9627 } | 9694 } |
9628 | 9695 |
9629 // Otherwise default to slow case. | 9696 // Otherwise default to slow case. |
9630 ASSERT(HasFastDoubleElements()); | 9697 ASSERT(HasFastDoubleElements()); |
9631 ASSERT(map()->has_fast_double_elements()); | 9698 ASSERT(map()->has_fast_double_elements()); |
9632 ASSERT(elements()->IsFixedDoubleArray()); | 9699 ASSERT(elements()->IsFixedDoubleArray()); |
9633 Object* obj; | 9700 Object* obj; |
9634 { MaybeObject* maybe_obj = NormalizeElements(); | 9701 { MaybeObject* maybe_obj = NormalizeElements(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9758 Object* value, | 9825 Object* value, |
9759 PropertyAttributes attr, | 9826 PropertyAttributes attr, |
9760 StrictModeFlag strict_mode, | 9827 StrictModeFlag strict_mode, |
9761 bool check_prototype, | 9828 bool check_prototype, |
9762 SetPropertyMode set_mode) { | 9829 SetPropertyMode set_mode) { |
9763 ASSERT(HasDictionaryElements() || | 9830 ASSERT(HasDictionaryElements() || |
9764 HasDictionaryArgumentsElements() || | 9831 HasDictionaryArgumentsElements() || |
9765 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 9832 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
9766 Isolate* isolate = GetIsolate(); | 9833 Isolate* isolate = GetIsolate(); |
9767 switch (GetElementsKind()) { | 9834 switch (GetElementsKind()) { |
9768 case FAST_SMI_ONLY_ELEMENTS: | 9835 case FAST_SMI_ELEMENTS: |
9769 case FAST_ELEMENTS: | 9836 case FAST_ELEMENTS: |
9837 case FAST_HOLEY_SMI_ELEMENTS: | |
9838 case FAST_HOLEY_ELEMENTS: | |
9770 return SetFastElement(index, value, strict_mode, check_prototype); | 9839 return SetFastElement(index, value, strict_mode, check_prototype); |
9771 case FAST_DOUBLE_ELEMENTS: | 9840 case FAST_DOUBLE_ELEMENTS: |
9841 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
9772 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 9842 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
9773 case EXTERNAL_PIXEL_ELEMENTS: { | 9843 case EXTERNAL_PIXEL_ELEMENTS: { |
9774 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9844 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
9775 return pixels->SetValue(index, value); | 9845 return pixels->SetValue(index, value); |
9776 } | 9846 } |
9777 case EXTERNAL_BYTE_ELEMENTS: { | 9847 case EXTERNAL_BYTE_ELEMENTS: { |
9778 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 9848 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
9779 return array->SetValue(index, value); | 9849 return array->SetValue(index, value); |
9780 } | 9850 } |
9781 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 9851 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9852 ElementsKind to_kind) { | 9922 ElementsKind to_kind) { |
9853 CALL_HEAP_FUNCTION(object->GetIsolate(), | 9923 CALL_HEAP_FUNCTION(object->GetIsolate(), |
9854 object->TransitionElementsKind(to_kind), | 9924 object->TransitionElementsKind(to_kind), |
9855 Object); | 9925 Object); |
9856 } | 9926 } |
9857 | 9927 |
9858 | 9928 |
9859 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 9929 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
9860 ElementsKind from_kind = map()->elements_kind(); | 9930 ElementsKind from_kind = map()->elements_kind(); |
9861 | 9931 |
9932 if (IsFastHoleyElementsKind(from_kind)) { | |
9933 to_kind = GetHoleyElementsKind(to_kind); | |
9934 } | |
9935 | |
9862 Isolate* isolate = GetIsolate(); | 9936 Isolate* isolate = GetIsolate(); |
9863 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9937 |
9864 (to_kind == FAST_ELEMENTS || | 9938 if (elements() == isolate->heap()->empty_fixed_array() || |
9865 elements() == isolate->heap()->empty_fixed_array())) { | 9939 (IsFastSmiOrObjectElementsKind(from_kind) && |
9940 IsFastSmiOrObjectElementsKind(to_kind)) || | |
9941 (from_kind == FAST_DOUBLE_ELEMENTS && | |
9942 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | |
9943 // No change is needed to the elements() buffer, the transition | |
9944 // only requires a map change. | |
9866 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 9945 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
9867 Map* new_map; | 9946 Map* new_map; |
9868 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9947 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
9869 set_map(new_map); | 9948 set_map(new_map); |
9870 if (FLAG_trace_elements_transitions) { | 9949 if (FLAG_trace_elements_transitions) { |
9871 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9950 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9872 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 9951 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
9873 } | 9952 } |
9874 return this; | 9953 return this; |
9875 } | 9954 } |
9876 | 9955 |
9877 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9956 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
9878 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9957 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
9879 uint32_t length = capacity; | 9958 uint32_t length = capacity; |
9880 | 9959 |
9881 if (IsJSArray()) { | 9960 if (IsJSArray()) { |
9882 Object* raw_length = JSArray::cast(this)->length(); | 9961 Object* raw_length = JSArray::cast(this)->length(); |
9883 if (raw_length->IsUndefined()) { | 9962 if (raw_length->IsUndefined()) { |
9884 // If length is undefined, then JSArray is being initialized and has no | 9963 // If length is undefined, then JSArray is being initialized and has no |
9885 // elements, assume a length of zero. | 9964 // elements, assume a length of zero. |
9886 length = 0; | 9965 length = 0; |
9887 } else { | 9966 } else { |
9888 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9967 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
9889 } | 9968 } |
9890 } | 9969 } |
9891 | 9970 |
9892 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9971 if (IsFastSmiElementsKind(from_kind) && |
9893 to_kind == FAST_DOUBLE_ELEMENTS) { | 9972 IsFastDoubleElementsKind(to_kind)) { |
9894 MaybeObject* maybe_result = | 9973 MaybeObject* maybe_result = |
9895 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9974 SetFastDoubleElementsCapacityAndLength(capacity, length); |
9896 if (maybe_result->IsFailure()) return maybe_result; | 9975 if (maybe_result->IsFailure()) return maybe_result; |
9976 ValidateElements(); | |
9897 return this; | 9977 return this; |
9898 } | 9978 } |
9899 | 9979 |
9900 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 9980 if (IsFastDoubleElementsKind(from_kind) && |
9981 IsFastObjectElementsKind(to_kind)) { | |
9901 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9982 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
9902 capacity, length, kDontAllowSmiOnlyElements); | 9983 capacity, length, kDontAllowSmiOnlyElements); |
9903 if (maybe_result->IsFailure()) return maybe_result; | 9984 if (maybe_result->IsFailure()) return maybe_result; |
9985 ValidateElements(); | |
9904 return this; | 9986 return this; |
9905 } | 9987 } |
9906 | 9988 |
9907 // This method should never be called for any other case than the ones | 9989 // This method should never be called for any other case than the ones |
9908 // handled above. | 9990 // handled above. |
9909 UNREACHABLE(); | 9991 UNREACHABLE(); |
9910 return GetIsolate()->heap()->null_value(); | 9992 return GetIsolate()->heap()->null_value(); |
9911 } | 9993 } |
9912 | 9994 |
9913 | 9995 |
9914 // static | 9996 // static |
9915 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9997 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
9916 ElementsKind to_kind) { | 9998 ElementsKind to_kind) { |
9917 return | 9999 // Transitions can't go backwards. |
9918 (from_kind == FAST_SMI_ONLY_ELEMENTS && | 10000 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
9919 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || | 10001 return false; |
9920 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); | 10002 } |
10003 | |
10004 // Transitions from HOLEY -> PACKED are not allowed. | |
10005 return !IsFastHoleyElementsKind(from_kind) || | |
10006 IsFastHoleyElementsKind(to_kind); | |
9921 } | 10007 } |
9922 | 10008 |
9923 | 10009 |
9924 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 10010 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
9925 Object* value) { | 10011 Object* value) { |
9926 uint32_t old_len = 0; | 10012 uint32_t old_len = 0; |
9927 CHECK(length()->ToArrayIndex(&old_len)); | 10013 CHECK(length()->ToArrayIndex(&old_len)); |
9928 // Check to see if we need to update the length. For now, we make | 10014 // Check to see if we need to update the length. For now, we make |
9929 // sure that the length stays within 32-bits (unsigned). | 10015 // sure that the length stays within 32-bits (unsigned). |
9930 if (index >= old_len && index != 0xffffffff) { | 10016 if (index >= old_len && index != 0xffffffff) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10001 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 10087 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
10002 backing_store = FixedArray::cast(backing_store_base); | 10088 backing_store = FixedArray::cast(backing_store_base); |
10003 if (backing_store->IsDictionary()) { | 10089 if (backing_store->IsDictionary()) { |
10004 SeededNumberDictionary* dictionary = | 10090 SeededNumberDictionary* dictionary = |
10005 SeededNumberDictionary::cast(backing_store); | 10091 SeededNumberDictionary::cast(backing_store); |
10006 *capacity = dictionary->Capacity(); | 10092 *capacity = dictionary->Capacity(); |
10007 *used = dictionary->NumberOfElements(); | 10093 *used = dictionary->NumberOfElements(); |
10008 break; | 10094 break; |
10009 } | 10095 } |
10010 // Fall through. | 10096 // Fall through. |
10011 case FAST_SMI_ONLY_ELEMENTS: | 10097 case FAST_SMI_ELEMENTS: |
10012 case FAST_ELEMENTS: | 10098 case FAST_ELEMENTS: |
10099 case FAST_HOLEY_SMI_ELEMENTS: | |
10100 case FAST_HOLEY_ELEMENTS: | |
10013 backing_store = FixedArray::cast(backing_store_base); | 10101 backing_store = FixedArray::cast(backing_store_base); |
10014 *capacity = backing_store->length(); | 10102 *capacity = backing_store->length(); |
10015 for (int i = 0; i < *capacity; ++i) { | 10103 for (int i = 0; i < *capacity; ++i) { |
10016 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 10104 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
10017 } | 10105 } |
10018 break; | 10106 break; |
10019 case DICTIONARY_ELEMENTS: { | 10107 case DICTIONARY_ELEMENTS: { |
10020 SeededNumberDictionary* dictionary = | 10108 SeededNumberDictionary* dictionary = |
10021 SeededNumberDictionary::cast(FixedArray::cast(elements())); | 10109 SeededNumberDictionary::cast(FixedArray::cast(elements())); |
10022 *capacity = dictionary->Capacity(); | 10110 *capacity = dictionary->Capacity(); |
10023 *used = dictionary->NumberOfElements(); | 10111 *used = dictionary->NumberOfElements(); |
10024 break; | 10112 break; |
10025 } | 10113 } |
10026 case FAST_DOUBLE_ELEMENTS: { | 10114 case FAST_DOUBLE_ELEMENTS: |
10115 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
10027 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 10116 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
10028 *capacity = elms->length(); | 10117 *capacity = elms->length(); |
10029 for (int i = 0; i < *capacity; i++) { | 10118 for (int i = 0; i < *capacity; i++) { |
10030 if (!elms->is_the_hole(i)) ++(*used); | 10119 if (!elms->is_the_hole(i)) ++(*used); |
10031 } | 10120 } |
10032 break; | 10121 break; |
10033 } | 10122 } |
10034 case EXTERNAL_BYTE_ELEMENTS: | 10123 case EXTERNAL_BYTE_ELEMENTS: |
10035 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 10124 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
10036 case EXTERNAL_SHORT_ELEMENTS: | 10125 case EXTERNAL_SHORT_ELEMENTS: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10286 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10375 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
10287 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 10376 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
10288 return false; | 10377 return false; |
10289 } | 10378 } |
10290 } | 10379 } |
10291 | 10380 |
10292 // Handle [] on String objects. | 10381 // Handle [] on String objects. |
10293 if (this->IsStringObjectWithCharacterAt(index)) return true; | 10382 if (this->IsStringObjectWithCharacterAt(index)) return true; |
10294 | 10383 |
10295 switch (GetElementsKind()) { | 10384 switch (GetElementsKind()) { |
10296 case FAST_SMI_ONLY_ELEMENTS: | 10385 case FAST_SMI_ELEMENTS: |
10297 case FAST_ELEMENTS: { | 10386 case FAST_ELEMENTS: |
10298 uint32_t length = IsJSArray() ? | 10387 case FAST_HOLEY_SMI_ELEMENTS: |
10388 case FAST_HOLEY_ELEMENTS: { | |
10389 uint32_t length = IsJSArray() ? | |
10299 static_cast<uint32_t>( | 10390 static_cast<uint32_t>( |
10300 Smi::cast(JSArray::cast(this)->length())->value()) : | 10391 Smi::cast(JSArray::cast(this)->length())->value()) : |
10301 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10392 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10302 return (index < length) && | 10393 return (index < length) && |
10303 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 10394 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
10304 } | 10395 } |
10305 case FAST_DOUBLE_ELEMENTS: { | 10396 case FAST_DOUBLE_ELEMENTS: |
10397 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
10306 uint32_t length = IsJSArray() ? | 10398 uint32_t length = IsJSArray() ? |
10307 static_cast<uint32_t>( | 10399 static_cast<uint32_t>( |
10308 Smi::cast(JSArray::cast(this)->length())->value()) : | 10400 Smi::cast(JSArray::cast(this)->length())->value()) : |
10309 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 10401 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
10310 return (index < length) && | 10402 return (index < length) && |
10311 !FixedDoubleArray::cast(elements())->is_the_hole(index); | 10403 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
10312 break; | 10404 break; |
10313 } | 10405 } |
10314 case EXTERNAL_PIXEL_ELEMENTS: { | 10406 case EXTERNAL_PIXEL_ELEMENTS: { |
10315 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 10407 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10495 } | 10587 } |
10496 | 10588 |
10497 | 10589 |
10498 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 10590 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
10499 return GetLocalElementKeys(NULL, filter); | 10591 return GetLocalElementKeys(NULL, filter); |
10500 } | 10592 } |
10501 | 10593 |
10502 | 10594 |
10503 int JSObject::NumberOfEnumElements() { | 10595 int JSObject::NumberOfEnumElements() { |
10504 // Fast case for objects with no elements. | 10596 // Fast case for objects with no elements. |
10505 if (!IsJSValue() && HasFastElements()) { | 10597 if (!IsJSValue() && HasFastObjectElements()) { |
10506 uint32_t length = IsJSArray() ? | 10598 uint32_t length = IsJSArray() ? |
10507 static_cast<uint32_t>( | 10599 static_cast<uint32_t>( |
10508 Smi::cast(JSArray::cast(this)->length())->value()) : | 10600 Smi::cast(JSArray::cast(this)->length())->value()) : |
10509 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10601 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
10510 if (length == 0) return 0; | 10602 if (length == 0) return 0; |
10511 } | 10603 } |
10512 // Compute the number of enumerable elements. | 10604 // Compute the number of enumerable elements. |
10513 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 10605 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
10514 } | 10606 } |
10515 | 10607 |
10516 | 10608 |
10517 int JSObject::GetLocalElementKeys(FixedArray* storage, | 10609 int JSObject::GetLocalElementKeys(FixedArray* storage, |
10518 PropertyAttributes filter) { | 10610 PropertyAttributes filter) { |
10519 int counter = 0; | 10611 int counter = 0; |
10520 switch (GetElementsKind()) { | 10612 switch (GetElementsKind()) { |
10521 case FAST_SMI_ONLY_ELEMENTS: | 10613 case FAST_SMI_ELEMENTS: |
10522 case FAST_ELEMENTS: { | 10614 case FAST_ELEMENTS: |
10615 case FAST_HOLEY_SMI_ELEMENTS: | |
10616 case FAST_HOLEY_ELEMENTS: { | |
10523 int length = IsJSArray() ? | 10617 int length = IsJSArray() ? |
10524 Smi::cast(JSArray::cast(this)->length())->value() : | 10618 Smi::cast(JSArray::cast(this)->length())->value() : |
10525 FixedArray::cast(elements())->length(); | 10619 FixedArray::cast(elements())->length(); |
10526 for (int i = 0; i < length; i++) { | 10620 for (int i = 0; i < length; i++) { |
10527 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 10621 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
10528 if (storage != NULL) { | 10622 if (storage != NULL) { |
10529 storage->set(counter, Smi::FromInt(i)); | 10623 storage->set(counter, Smi::FromInt(i)); |
10530 } | 10624 } |
10531 counter++; | 10625 counter++; |
10532 } | 10626 } |
10533 } | 10627 } |
10534 ASSERT(!storage || storage->length() >= counter); | 10628 ASSERT(!storage || storage->length() >= counter); |
10535 break; | 10629 break; |
10536 } | 10630 } |
10537 case FAST_DOUBLE_ELEMENTS: { | 10631 case FAST_DOUBLE_ELEMENTS: |
10632 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
10538 int length = IsJSArray() ? | 10633 int length = IsJSArray() ? |
10539 Smi::cast(JSArray::cast(this)->length())->value() : | 10634 Smi::cast(JSArray::cast(this)->length())->value() : |
10540 FixedDoubleArray::cast(elements())->length(); | 10635 FixedDoubleArray::cast(elements())->length(); |
10541 for (int i = 0; i < length; i++) { | 10636 for (int i = 0; i < length; i++) { |
10542 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 10637 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
10543 if (storage != NULL) { | 10638 if (storage != NULL) { |
10544 storage->set(counter, Smi::FromInt(i)); | 10639 storage->set(counter, Smi::FromInt(i)); |
10545 } | 10640 } |
10546 counter++; | 10641 counter++; |
10547 } | 10642 } |
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11460 // Convert to fast elements containing only the existing properties. | 11555 // Convert to fast elements containing only the existing properties. |
11461 // Ordering is irrelevant, since we are going to sort anyway. | 11556 // Ordering is irrelevant, since we are going to sort anyway. |
11462 SeededNumberDictionary* dict = element_dictionary(); | 11557 SeededNumberDictionary* dict = element_dictionary(); |
11463 if (IsJSArray() || dict->requires_slow_elements() || | 11558 if (IsJSArray() || dict->requires_slow_elements() || |
11464 dict->max_number_key() >= limit) { | 11559 dict->max_number_key() >= limit) { |
11465 return PrepareSlowElementsForSort(limit); | 11560 return PrepareSlowElementsForSort(limit); |
11466 } | 11561 } |
11467 // Convert to fast elements. | 11562 // Convert to fast elements. |
11468 | 11563 |
11469 Object* obj; | 11564 Object* obj; |
11470 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 11565 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
11471 FAST_ELEMENTS); | 11566 FAST_HOLEY_ELEMENTS); |
11472 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11567 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11473 } | |
11474 Map* new_map = Map::cast(obj); | 11568 Map* new_map = Map::cast(obj); |
11475 | 11569 |
11476 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 11570 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
11477 Object* new_array; | 11571 Object* new_array; |
11478 { MaybeObject* maybe_new_array = | 11572 { MaybeObject* maybe_new_array = |
11479 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 11573 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
11480 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 11574 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
11481 } | 11575 } |
11482 FixedArray* fast_elements = FixedArray::cast(new_array); | 11576 FixedArray* fast_elements = FixedArray::cast(new_array); |
11483 dict->CopyValuesTo(fast_elements); | 11577 dict->CopyValuesTo(fast_elements); |
11578 ValidateElements(); | |
11484 | 11579 |
11485 set_map(new_map); | 11580 set_map_and_elements(new_map, fast_elements); |
11486 set_elements(fast_elements); | |
11487 } else if (HasExternalArrayElements()) { | 11581 } else if (HasExternalArrayElements()) { |
11488 // External arrays cannot have holes or undefined elements. | 11582 // External arrays cannot have holes or undefined elements. |
11489 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 11583 return Smi::FromInt(ExternalArray::cast(elements())->length()); |
11490 } else if (!HasFastDoubleElements()) { | 11584 } else if (!HasFastDoubleElements()) { |
11491 Object* obj; | 11585 Object* obj; |
11492 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 11586 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
11493 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11587 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
11494 } | 11588 } |
11495 } | 11589 } |
11496 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); | 11590 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); |
11497 | 11591 |
11498 // Collect holes at the end, undefined before that and the rest at the | 11592 // Collect holes at the end, undefined before that and the rest at the |
11499 // start, and return the number of non-hole, non-undefined values. | 11593 // start, and return the number of non-hole, non-undefined values. |
11500 | 11594 |
11501 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 11595 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
11502 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 11596 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
11503 if (limit > elements_length) { | 11597 if (limit > elements_length) { |
11504 limit = elements_length ; | 11598 limit = elements_length ; |
11505 } | 11599 } |
11506 if (limit == 0) { | 11600 if (limit == 0) { |
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13163 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13257 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13164 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13258 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13165 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13259 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13166 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13260 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13167 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13261 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13168 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13262 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13169 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13263 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13170 } | 13264 } |
13171 | 13265 |
13172 } } // namespace v8::internal | 13266 } } // namespace v8::internal |
OLD | NEW |