Chromium Code Reviews| 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 |