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 |
| 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 : | |
| 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 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2061 if (result->IsProperty()) { | 2058 if (result->IsProperty()) { |
| 2062 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; | 2059 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; |
| 2063 // Found non-callback or read-only callback, stop looking. | 2060 // Found non-callback or read-only callback, stop looking. |
| 2064 break; | 2061 break; |
| 2065 } | 2062 } |
| 2066 } | 2063 } |
| 2067 result->NotFound(); | 2064 result->NotFound(); |
| 2068 } | 2065 } |
| 2069 | 2066 |
| 2070 | 2067 |
| 2068 void JSObject::ValidateElements() { | |
| 2069 ElementsAccessor* accessor = GetElementsAccessor(); | |
| 2070 accessor->Validate(this); | |
| 2071 } | |
| 2072 | |
| 2073 | |
| 2071 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( | 2074 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( |
| 2072 uint32_t index, | 2075 uint32_t index, |
| 2073 Object* value, | 2076 Object* value, |
| 2074 bool* found, | 2077 bool* found, |
| 2075 StrictModeFlag strict_mode) { | 2078 StrictModeFlag strict_mode) { |
| 2076 Heap* heap = GetHeap(); | 2079 Heap* heap = GetHeap(); |
| 2077 for (Object* pt = GetPrototype(); | 2080 for (Object* pt = GetPrototype(); |
| 2078 pt != heap->null_value(); | 2081 pt != heap->null_value(); |
| 2079 pt = pt->GetPrototype()) { | 2082 pt = pt->GetPrototype()) { |
| 2080 if (pt->IsJSProxy()) { | 2083 if (pt->IsJSProxy()) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2192 | 2195 |
| 2193 | 2196 |
| 2194 template <class T> | 2197 template <class T> |
| 2195 static Handle<T> MaybeNull(T* p) { | 2198 static Handle<T> MaybeNull(T* p) { |
| 2196 if (p == NULL) return Handle<T>::null(); | 2199 if (p == NULL) return Handle<T>::null(); |
| 2197 return Handle<T>(p); | 2200 return Handle<T>(p); |
| 2198 } | 2201 } |
| 2199 | 2202 |
| 2200 | 2203 |
| 2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { | 2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
| 2202 ElementsKind elms_kind = elements_kind(); | 2205 ElementsKind kind = elements_kind(); |
| 2203 if (elms_kind == FAST_DOUBLE_ELEMENTS) { | 2206 Handle<Map> transitioned_map = Handle<Map>::null(); |
| 2204 bool dummy = true; | 2207 Handle<Map> current_map(this); |
| 2205 Handle<Map> fast_map = | 2208 bool packed = IsFastPackedElementsKind(kind); |
| 2206 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); | 2209 if (IsTransitionableFastElementsKind(kind)) { |
| 2207 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { | 2210 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { |
| 2208 return fast_map; | 2211 kind = GetNextMoreGeneralFastElementsKind(kind, false); |
| 2212 bool dummy = true; | |
| 2213 Handle<Map> maybe_transitioned_map = | |
| 2214 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy)); | |
| 2215 if (maybe_transitioned_map.is_null()) break; | |
| 2216 if (ContainsMap(candidates, maybe_transitioned_map) && | |
| 2217 (packed || !IsFastPackedElementsKind(kind))) { | |
| 2218 transitioned_map = maybe_transitioned_map; | |
| 2219 if (!IsFastPackedElementsKind(kind)) packed = false; | |
| 2220 } | |
| 2221 current_map = maybe_transitioned_map; | |
| 2209 } | 2222 } |
| 2210 return Handle<Map>::null(); | |
| 2211 } | 2223 } |
| 2212 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { | 2224 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 } | 2225 } |
| 2229 | 2226 |
| 2227 | |
| 2230 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | 2228 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
| 2231 ElementsKind elements_kind) { | 2229 ElementsKind elements_kind) { |
| 2232 if (descriptor_contents->IsMap()) { | 2230 if (descriptor_contents->IsMap()) { |
| 2233 Map* map = Map::cast(descriptor_contents); | 2231 Map* map = Map::cast(descriptor_contents); |
| 2234 if (map->elements_kind() == elements_kind) { | 2232 if (map->elements_kind() == elements_kind) { |
| 2235 return map; | 2233 return map; |
| 2236 } | 2234 } |
| 2237 return NULL; | 2235 return NULL; |
| 2238 } | 2236 } |
| 2239 | 2237 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2328 } else { | 2326 } else { |
| 2329 if (safe_to_add_transition != NULL) { | 2327 if (safe_to_add_transition != NULL) { |
| 2330 *safe_to_add_transition = false; | 2328 *safe_to_add_transition = false; |
| 2331 } | 2329 } |
| 2332 } | 2330 } |
| 2333 } | 2331 } |
| 2334 return NULL; | 2332 return NULL; |
| 2335 } | 2333 } |
| 2336 | 2334 |
| 2337 | 2335 |
| 2338 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, | 2336 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, |
| 2339 bool* safe_to_add_transition) { | 2337 bool* safe_to_add_transition) { |
| 2340 // Special case: indirect SMI->FAST transition (cf. comment in | 2338 ElementsKind from_kind = elements_kind(); |
| 2341 // AddElementsTransition()). | 2339 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
| 2342 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2340 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
| 2343 elements_kind == FAST_ELEMENTS) { | 2341 if (safe_to_add_transition) *safe_to_add_transition = false; |
| 2344 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, | 2342 return NULL; |
| 2345 safe_to_add_transition); | 2343 } |
| 2346 if (double_map == NULL) return double_map; | 2344 ElementsKind transitioned_from_kind = |
| 2347 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, | 2345 GetNextMoreGeneralFastElementsKind(from_kind, false); |
| 2346 | |
| 2347 | |
| 2348 // If the transition is a single step in the transition sequence, fall | |
| 2349 // through to looking it up and returning it. If it requires several steps, | |
| 2350 // divide and conquer. | |
| 2351 if (transitioned_from_kind != to_kind) { | |
| 2352 // If the transition is several steps in the lattice, divide and conquer. | |
| 2353 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind, | |
| 2354 safe_to_add_transition); | |
| 2355 if (from_map == NULL) return NULL; | |
| 2356 return from_map->LookupElementsTransitionMap(to_kind, | |
| 2348 safe_to_add_transition); | 2357 safe_to_add_transition); |
| 2358 } | |
| 2349 } | 2359 } |
| 2360 | |
| 2350 Object* descriptor_contents = GetDescriptorContents( | 2361 Object* descriptor_contents = GetDescriptorContents( |
| 2351 elements_transition_sentinel_name(), safe_to_add_transition); | 2362 elements_transition_sentinel_name(), safe_to_add_transition); |
| 2352 if (descriptor_contents != NULL) { | 2363 if (descriptor_contents != NULL) { |
| 2353 Map* maybe_transition_map = | 2364 Map* maybe_transition_map = |
| 2354 GetElementsTransitionMapFromDescriptor(descriptor_contents, | 2365 GetElementsTransitionMapFromDescriptor(descriptor_contents, |
| 2355 elements_kind); | 2366 to_kind); |
| 2356 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); | 2367 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); |
| 2357 return maybe_transition_map; | 2368 return maybe_transition_map; |
| 2358 } | 2369 } |
| 2359 return NULL; | 2370 return NULL; |
| 2360 } | 2371 } |
| 2361 | 2372 |
| 2362 | 2373 |
| 2363 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, | 2374 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, |
| 2364 Map* transitioned_map) { | 2375 Map* transitioned_map) { |
| 2365 // The map transition graph should be a tree, therefore the transition | 2376 ElementsKind from_kind = elements_kind(); |
| 2366 // from SMI to FAST elements is not done directly, but by going through | 2377 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { |
| 2367 // DOUBLE elements first. | 2378 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); |
| 2368 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && | 2379 ElementsKind transitioned_from_kind = |
| 2369 elements_kind == FAST_ELEMENTS) { | 2380 GetNextMoreGeneralFastElementsKind(from_kind, false); |
| 2370 bool safe_to_add = true; | 2381 // The map transitions graph should be a tree, therefore transitions to |
| 2371 Map* double_map = this->LookupElementsTransitionMap( | 2382 // ElementsKind that are not adjacent in the ElementsKind sequence are not |
| 2372 FAST_DOUBLE_ELEMENTS, &safe_to_add); | 2383 // done directly, but instead by going through intermediate ElementsKinds |
| 2373 // This method is only called when safe_to_add_transition has been found | 2384 // first. |
| 2374 // to be true earlier. | 2385 if (to_kind != transitioned_from_kind) { |
| 2375 ASSERT(safe_to_add); | 2386 bool safe_to_add = true; |
| 2387 Map* intermediate_map = LookupElementsTransitionMap( | |
| 2388 transitioned_from_kind, &safe_to_add); | |
| 2389 // This method is only called when safe_to_add_transition has been found | |
| 2390 // to be true earlier. | |
| 2391 ASSERT(safe_to_add); | |
| 2376 | 2392 |
| 2377 if (double_map == NULL) { | 2393 if (intermediate_map == NULL) { |
| 2378 MaybeObject* maybe_map = this->CopyDropTransitions(); | 2394 MaybeObject* maybe_map = CopyDropTransitions(); |
| 2379 if (!maybe_map->To(&double_map)) return maybe_map; | 2395 if (!maybe_map->To(&intermediate_map)) return maybe_map; |
| 2380 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); | 2396 intermediate_map->set_elements_kind(transitioned_from_kind); |
| 2381 MaybeObject* maybe_double_transition = this->AddElementsTransition( | 2397 MaybeObject* maybe_transition = AddElementsTransition( |
| 2382 FAST_DOUBLE_ELEMENTS, double_map); | 2398 transitioned_from_kind, intermediate_map); |
| 2383 if (maybe_double_transition->IsFailure()) return maybe_double_transition; | 2399 if (maybe_transition->IsFailure()) return maybe_transition; |
| 2400 } | |
| 2401 return intermediate_map->AddElementsTransition(to_kind, transitioned_map); | |
| 2384 } | 2402 } |
| 2385 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map); | |
| 2386 } | 2403 } |
| 2387 | 2404 |
| 2388 bool safe_to_add_transition = true; | 2405 bool safe_to_add_transition = true; |
| 2389 Object* descriptor_contents = GetDescriptorContents( | 2406 Object* descriptor_contents = GetDescriptorContents( |
| 2390 elements_transition_sentinel_name(), &safe_to_add_transition); | 2407 elements_transition_sentinel_name(), &safe_to_add_transition); |
| 2391 // This method is only called when safe_to_add_transition has been found | 2408 // This method is only called when safe_to_add_transition has been found |
| 2392 // to be true earlier. | 2409 // to be true earlier. |
| 2393 ASSERT(safe_to_add_transition); | 2410 ASSERT(safe_to_add_transition); |
| 2394 MaybeObject* maybe_new_contents = | 2411 MaybeObject* maybe_new_contents = |
| 2395 AddElementsTransitionMapToDescriptor(descriptor_contents, | 2412 AddElementsTransitionMapToDescriptor(descriptor_contents, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 2426 ElementsKind from_kind = current_map->elements_kind(); | 2443 ElementsKind from_kind = current_map->elements_kind(); |
| 2427 | 2444 |
| 2428 if (from_kind == to_kind) return current_map; | 2445 if (from_kind == to_kind) return current_map; |
| 2429 | 2446 |
| 2430 // Only objects with FastProperties can have DescriptorArrays and can track | 2447 // Only objects with FastProperties can have DescriptorArrays and can track |
| 2431 // element-related maps. Also don't add descriptors to maps that are shared. | 2448 // element-related maps. Also don't add descriptors to maps that are shared. |
| 2432 bool safe_to_add_transition = HasFastProperties() && | 2449 bool safe_to_add_transition = HasFastProperties() && |
| 2433 !current_map->IsUndefined() && | 2450 !current_map->IsUndefined() && |
| 2434 !current_map->is_shared(); | 2451 !current_map->is_shared(); |
| 2435 | 2452 |
| 2436 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects | 2453 // Prevent long chains of DICTIONARY -> fast object elements maps caused by |
| 2437 // with elements that switch back and forth between dictionary and fast | 2454 // objects with elements that switch back and forth between dictionary and |
| 2438 // element mode. | 2455 // fast element mode. |
| 2439 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 2456 if (from_kind == DICTIONARY_ELEMENTS && |
| 2457 IsFastObjectElementsKind(to_kind)) { | |
| 2440 safe_to_add_transition = false; | 2458 safe_to_add_transition = false; |
| 2441 } | 2459 } |
| 2442 | 2460 |
| 2443 if (safe_to_add_transition) { | 2461 if (safe_to_add_transition) { |
| 2444 // It's only safe to manipulate the descriptor array if it would be | 2462 // It's only safe to manipulate the descriptor array if it would be |
| 2445 // safe to add a transition. | 2463 // safe to add a transition. |
| 2446 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( | 2464 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( |
| 2447 to_kind, &safe_to_add_transition); | 2465 to_kind, &safe_to_add_transition); |
| 2448 if (maybe_transition_map != NULL) { | 2466 if (maybe_transition_map != NULL) { |
| 2449 return maybe_transition_map; | 2467 return maybe_transition_map; |
| (...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3465 // Find the backing store. | 3483 // Find the backing store. |
| 3466 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 3484 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 3467 Map* old_map = array->map(); | 3485 Map* old_map = array->map(); |
| 3468 bool is_arguments = | 3486 bool is_arguments = |
| 3469 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 3487 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
| 3470 if (is_arguments) { | 3488 if (is_arguments) { |
| 3471 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 3489 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 3472 } | 3490 } |
| 3473 if (array->IsDictionary()) return array; | 3491 if (array->IsDictionary()) return array; |
| 3474 | 3492 |
| 3475 ASSERT(HasFastElements() || | 3493 ASSERT(HasFastSmiOrObjectElements() || |
| 3476 HasFastSmiOnlyElements() || | |
| 3477 HasFastDoubleElements() || | 3494 HasFastDoubleElements() || |
| 3478 HasFastArgumentsElements()); | 3495 HasFastArgumentsElements()); |
| 3479 // Compute the effective length and allocate a new backing store. | 3496 // Compute the effective length and allocate a new backing store. |
| 3480 int length = IsJSArray() | 3497 int length = IsJSArray() |
| 3481 ? Smi::cast(JSArray::cast(this)->length())->value() | 3498 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3482 : array->length(); | 3499 : array->length(); |
| 3483 int old_capacity = 0; | 3500 int old_capacity = 0; |
| 3484 int used_elements = 0; | 3501 int used_elements = 0; |
| 3485 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 3502 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 3486 SeededNumberDictionary* dictionary = NULL; | 3503 SeededNumberDictionary* dictionary = NULL; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 3501 } else { | 3518 } else { |
| 3502 // Objects must be allocated in the old object space, since the | 3519 // Objects must be allocated in the old object space, since the |
| 3503 // overall number of HeapNumbers needed for the conversion might | 3520 // overall number of HeapNumbers needed for the conversion might |
| 3504 // exceed the capacity of new space, and we would fail repeatedly | 3521 // exceed the capacity of new space, and we would fail repeatedly |
| 3505 // trying to convert the FixedDoubleArray. | 3522 // trying to convert the FixedDoubleArray. |
| 3506 MaybeObject* maybe_value_object = | 3523 MaybeObject* maybe_value_object = |
| 3507 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); | 3524 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 3508 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 3525 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 3509 } | 3526 } |
| 3510 } else { | 3527 } else { |
| 3511 ASSERT(old_map->has_fast_elements() || | 3528 ASSERT(old_map->has_fast_smi_or_object_elements()); |
| 3512 old_map->has_fast_smi_only_elements()); | |
| 3513 value = FixedArray::cast(array)->get(i); | 3529 value = FixedArray::cast(array)->get(i); |
| 3514 } | 3530 } |
| 3515 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 3531 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 3516 if (!value->IsTheHole()) { | 3532 if (!value->IsTheHole()) { |
| 3517 Object* result; | 3533 Object* result; |
| 3518 MaybeObject* maybe_result = | 3534 MaybeObject* maybe_result = |
| 3519 dictionary->AddNumberEntry(i, value, details); | 3535 dictionary->AddNumberEntry(i, value, details); |
| 3520 if (!maybe_result->ToObject(&result)) return maybe_result; | 3536 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3521 dictionary = SeededNumberDictionary::cast(result); | 3537 dictionary = SeededNumberDictionary::cast(result); |
| 3522 } | 3538 } |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3989 if (IsJSProxy()) { | 4005 if (IsJSProxy()) { |
| 3990 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); | 4006 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
| 3991 } | 4007 } |
| 3992 return JSObject::cast(this)->DeleteProperty(name, mode); | 4008 return JSObject::cast(this)->DeleteProperty(name, mode); |
| 3993 } | 4009 } |
| 3994 | 4010 |
| 3995 | 4011 |
| 3996 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 4012 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 3997 ElementsKind kind, | 4013 ElementsKind kind, |
| 3998 Object* object) { | 4014 Object* object) { |
| 3999 ASSERT(kind == FAST_ELEMENTS || | 4015 ASSERT(IsFastObjectElementsKind(kind) || |
| 4000 kind == DICTIONARY_ELEMENTS); | 4016 kind == DICTIONARY_ELEMENTS); |
| 4001 if (kind == FAST_ELEMENTS) { | 4017 if (IsFastObjectElementsKind(kind)) { |
| 4002 int length = IsJSArray() | 4018 int length = IsJSArray() |
| 4003 ? Smi::cast(JSArray::cast(this)->length())->value() | 4019 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 4004 : elements->length(); | 4020 : elements->length(); |
| 4005 for (int i = 0; i < length; ++i) { | 4021 for (int i = 0; i < length; ++i) { |
| 4006 Object* element = elements->get(i); | 4022 Object* element = elements->get(i); |
| 4007 if (!element->IsTheHole() && element == object) return true; | 4023 if (!element->IsTheHole() && element == object) return true; |
| 4008 } | 4024 } |
| 4009 } else { | 4025 } else { |
| 4010 Object* key = | 4026 Object* key = |
| 4011 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); | 4027 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4043 case EXTERNAL_PIXEL_ELEMENTS: | 4059 case EXTERNAL_PIXEL_ELEMENTS: |
| 4044 case EXTERNAL_BYTE_ELEMENTS: | 4060 case EXTERNAL_BYTE_ELEMENTS: |
| 4045 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4061 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4046 case EXTERNAL_SHORT_ELEMENTS: | 4062 case EXTERNAL_SHORT_ELEMENTS: |
| 4047 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4063 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4048 case EXTERNAL_INT_ELEMENTS: | 4064 case EXTERNAL_INT_ELEMENTS: |
| 4049 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4065 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4050 case EXTERNAL_FLOAT_ELEMENTS: | 4066 case EXTERNAL_FLOAT_ELEMENTS: |
| 4051 case EXTERNAL_DOUBLE_ELEMENTS: | 4067 case EXTERNAL_DOUBLE_ELEMENTS: |
| 4052 case FAST_DOUBLE_ELEMENTS: | 4068 case FAST_DOUBLE_ELEMENTS: |
| 4069 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 4053 // Raw pixels and external arrays do not reference other | 4070 // Raw pixels and external arrays do not reference other |
| 4054 // objects. | 4071 // objects. |
| 4055 break; | 4072 break; |
| 4056 case FAST_SMI_ONLY_ELEMENTS: | 4073 case FAST_SMI_ELEMENTS: |
| 4074 case FAST_HOLEY_SMI_ELEMENTS: | |
| 4057 break; | 4075 break; |
| 4058 case FAST_ELEMENTS: | 4076 case FAST_ELEMENTS: |
| 4077 case FAST_HOLEY_ELEMENTS: | |
| 4059 case DICTIONARY_ELEMENTS: { | 4078 case DICTIONARY_ELEMENTS: { |
| 4060 FixedArray* elements = FixedArray::cast(this->elements()); | 4079 FixedArray* elements = FixedArray::cast(this->elements()); |
| 4061 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 4080 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 4062 break; | 4081 break; |
| 4063 } | 4082 } |
| 4064 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 4083 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 4065 FixedArray* parameter_map = FixedArray::cast(elements()); | 4084 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 4066 // Check the mapped parameters. | 4085 // Check the mapped parameters. |
| 4067 int length = parameter_map->length(); | 4086 int length = parameter_map->length(); |
| 4068 for (int i = 2; i < length; ++i) { | 4087 for (int i = 2; i < length; ++i) { |
| 4069 Object* value = parameter_map->get(i); | 4088 Object* value = parameter_map->get(i); |
| 4070 if (!value->IsTheHole() && value == obj) return true; | 4089 if (!value->IsTheHole() && value == obj) return true; |
| 4071 } | 4090 } |
| 4072 // Check the arguments. | 4091 // Check the arguments. |
| 4073 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 4092 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 4074 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; | 4093 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
| 4094 FAST_HOLEY_ELEMENTS; | |
| 4075 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 4095 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
| 4076 break; | 4096 break; |
| 4077 } | 4097 } |
| 4078 } | 4098 } |
| 4079 | 4099 |
| 4080 // For functions check the context. | 4100 // For functions check the context. |
| 4081 if (IsJSFunction()) { | 4101 if (IsJSFunction()) { |
| 4082 // Get the constructor function for arguments array. | 4102 // Get the constructor function for arguments array. |
| 4083 JSObject* arguments_boilerplate = | 4103 JSObject* arguments_boilerplate = |
| 4084 heap->isolate()->context()->global_context()-> | 4104 heap->isolate()->context()->global_context()-> |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4298 for (Object* current = this; | 4318 for (Object* current = this; |
| 4299 current != heap->null_value(); | 4319 current != heap->null_value(); |
| 4300 current = JSObject::cast(current)->GetPrototype()) { | 4320 current = JSObject::cast(current)->GetPrototype()) { |
| 4301 JSReceiver::cast(current)->LocalLookup(name, result); | 4321 JSReceiver::cast(current)->LocalLookup(name, result); |
| 4302 if (result->IsProperty()) return; | 4322 if (result->IsProperty()) return; |
| 4303 } | 4323 } |
| 4304 result->NotFound(); | 4324 result->NotFound(); |
| 4305 } | 4325 } |
| 4306 | 4326 |
| 4307 | 4327 |
| 4308 // Search object and it's prototype chain for callback properties. | 4328 // Search object and its prototype chain for callback properties. |
| 4309 void JSObject::LookupCallback(String* name, LookupResult* result) { | 4329 void JSObject::LookupCallback(String* name, LookupResult* result) { |
| 4310 Heap* heap = GetHeap(); | 4330 Heap* heap = GetHeap(); |
| 4311 for (Object* current = this; | 4331 for (Object* current = this; |
| 4312 current != heap->null_value() && current->IsJSObject(); | 4332 current != heap->null_value() && current->IsJSObject(); |
| 4313 current = JSObject::cast(current)->GetPrototype()) { | 4333 current = JSObject::cast(current)->GetPrototype()) { |
| 4314 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4334 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 4315 if (result->IsFound() && result->type() == CALLBACKS) return; | 4335 if (result->IsFound() && result->type() == CALLBACKS) return; |
| 4316 } | 4336 } |
| 4317 result->NotFound(); | 4337 result->NotFound(); |
| 4318 } | 4338 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 4342 } | 4362 } |
| 4343 return false; | 4363 return false; |
| 4344 } | 4364 } |
| 4345 | 4365 |
| 4346 | 4366 |
| 4347 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 4367 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, |
| 4348 Object* getter, | 4368 Object* getter, |
| 4349 Object* setter, | 4369 Object* setter, |
| 4350 PropertyAttributes attributes) { | 4370 PropertyAttributes attributes) { |
| 4351 switch (GetElementsKind()) { | 4371 switch (GetElementsKind()) { |
| 4352 case FAST_SMI_ONLY_ELEMENTS: | 4372 case FAST_SMI_ELEMENTS: |
| 4353 case FAST_ELEMENTS: | 4373 case FAST_ELEMENTS: |
| 4354 case FAST_DOUBLE_ELEMENTS: | 4374 case FAST_DOUBLE_ELEMENTS: |
| 4375 case FAST_HOLEY_SMI_ELEMENTS: | |
| 4376 case FAST_HOLEY_ELEMENTS: | |
| 4377 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 4355 break; | 4378 break; |
| 4356 case EXTERNAL_PIXEL_ELEMENTS: | 4379 case EXTERNAL_PIXEL_ELEMENTS: |
| 4357 case EXTERNAL_BYTE_ELEMENTS: | 4380 case EXTERNAL_BYTE_ELEMENTS: |
| 4358 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4381 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4359 case EXTERNAL_SHORT_ELEMENTS: | 4382 case EXTERNAL_SHORT_ELEMENTS: |
| 4360 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4383 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4361 case EXTERNAL_INT_ELEMENTS: | 4384 case EXTERNAL_INT_ELEMENTS: |
| 4362 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4385 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4363 case EXTERNAL_FLOAT_ELEMENTS: | 4386 case EXTERNAL_FLOAT_ELEMENTS: |
| 4364 case EXTERNAL_DOUBLE_ELEMENTS: | 4387 case EXTERNAL_DOUBLE_ELEMENTS: |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4434 accessors->SetComponents(getter, setter); | 4457 accessors->SetComponents(getter, setter); |
| 4435 return SetPropertyCallback(name, accessors, attributes); | 4458 return SetPropertyCallback(name, accessors, attributes); |
| 4436 } | 4459 } |
| 4437 | 4460 |
| 4438 | 4461 |
| 4439 bool JSObject::CanSetCallback(String* name) { | 4462 bool JSObject::CanSetCallback(String* name) { |
| 4440 ASSERT(!IsAccessCheckNeeded() || | 4463 ASSERT(!IsAccessCheckNeeded() || |
| 4441 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4464 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 4442 | 4465 |
| 4443 // Check if there is an API defined callback object which prohibits | 4466 // Check if there is an API defined callback object which prohibits |
| 4444 // callback overwriting in this object or it's prototype chain. | 4467 // callback overwriting in this object or its prototype chain. |
| 4445 // This mechanism is needed for instance in a browser setting, where | 4468 // This mechanism is needed for instance in a browser setting, where |
| 4446 // certain accessors such as window.location should not be allowed | 4469 // certain accessors such as window.location should not be allowed |
| 4447 // to be overwritten because allowing overwriting could potentially | 4470 // to be overwritten because allowing overwriting could potentially |
| 4448 // cause security problems. | 4471 // cause security problems. |
| 4449 LookupResult callback_result(GetIsolate()); | 4472 LookupResult callback_result(GetIsolate()); |
| 4450 LookupCallback(name, &callback_result); | 4473 LookupCallback(name, &callback_result); |
| 4451 if (callback_result.IsProperty()) { | 4474 if (callback_result.IsProperty()) { |
| 4452 Object* obj = callback_result.GetCallbackObject(); | 4475 Object* obj = callback_result.GetCallbackObject(); |
| 4453 if (obj->IsAccessorInfo() && | 4476 if (obj->IsAccessorInfo() && |
| 4454 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4477 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4605 } | 4628 } |
| 4606 | 4629 |
| 4607 uint32_t index = 0; | 4630 uint32_t index = 0; |
| 4608 bool is_element = name->AsArrayIndex(&index); | 4631 bool is_element = name->AsArrayIndex(&index); |
| 4609 | 4632 |
| 4610 if (is_element) { | 4633 if (is_element) { |
| 4611 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4634 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 4612 | 4635 |
| 4613 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4636 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 4614 switch (GetElementsKind()) { | 4637 switch (GetElementsKind()) { |
| 4615 case FAST_SMI_ONLY_ELEMENTS: | 4638 case FAST_SMI_ELEMENTS: |
| 4616 case FAST_ELEMENTS: | 4639 case FAST_ELEMENTS: |
| 4617 case FAST_DOUBLE_ELEMENTS: | 4640 case FAST_DOUBLE_ELEMENTS: |
| 4641 case FAST_HOLEY_SMI_ELEMENTS: | |
| 4642 case FAST_HOLEY_ELEMENTS: | |
| 4643 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 4618 break; | 4644 break; |
| 4619 case EXTERNAL_PIXEL_ELEMENTS: | 4645 case EXTERNAL_PIXEL_ELEMENTS: |
| 4620 case EXTERNAL_BYTE_ELEMENTS: | 4646 case EXTERNAL_BYTE_ELEMENTS: |
| 4621 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4647 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4622 case EXTERNAL_SHORT_ELEMENTS: | 4648 case EXTERNAL_SHORT_ELEMENTS: |
| 4623 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4649 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4624 case EXTERNAL_INT_ELEMENTS: | 4650 case EXTERNAL_INT_ELEMENTS: |
| 4625 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4651 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4626 case EXTERNAL_FLOAT_ELEMENTS: | 4652 case EXTERNAL_FLOAT_ELEMENTS: |
| 4627 case EXTERNAL_DOUBLE_ELEMENTS: | 4653 case EXTERNAL_DOUBLE_ELEMENTS: |
| (...skipping 3811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8439 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 8465 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
| 8440 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 8466 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
| 8441 PrintF(out, "\n"); | 8467 PrintF(out, "\n"); |
| 8442 } | 8468 } |
| 8443 #endif // ENABLE_DISASSEMBLER | 8469 #endif // ENABLE_DISASSEMBLER |
| 8444 | 8470 |
| 8445 | 8471 |
| 8446 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 8472 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 8447 int capacity, | 8473 int capacity, |
| 8448 int length, | 8474 int length, |
| 8449 SetFastElementsCapacityMode set_capacity_mode) { | 8475 SetFastElementsCapacitySmiMode smi_mode) { |
| 8450 Heap* heap = GetHeap(); | 8476 Heap* heap = GetHeap(); |
| 8451 // We should never end in here with a pixel or external array. | 8477 // We should never end in here with a pixel or external array. |
| 8452 ASSERT(!HasExternalArrayElements()); | 8478 ASSERT(!HasExternalArrayElements()); |
| 8453 | 8479 |
| 8454 // Allocate a new fast elements backing store. | 8480 // Allocate a new fast elements backing store. |
| 8455 FixedArray* new_elements; | 8481 FixedArray* new_elements; |
| 8456 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); | 8482 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); |
| 8457 if (!maybe->To(&new_elements)) return maybe; | 8483 if (!maybe->To(&new_elements)) return maybe; |
| 8458 } | 8484 } |
| 8459 | 8485 |
| 8460 // Find the new map to use for this object if there is a map change. | 8486 ElementsKind elements_kind = GetElementsKind(); |
| 8461 Map* new_map = NULL; | 8487 ElementsKind new_elements_kind; |
| 8462 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 8488 // The resized array has Smi-only elements if the capacity mode forces it, or |
| 8463 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces | 8489 // if it's allowed and the old elements array contained only SMIs. |
| 8464 // it, or if it's allowed and the old elements array contained only SMIs. | 8490 bool has_fast_smi_elements = |
| 8465 bool has_fast_smi_only_elements = | 8491 (smi_mode == kForceSmiOnlyElements) || |
| 8466 (set_capacity_mode == kForceSmiOnlyElements) || | 8492 ((smi_mode == kAllowSmiOnlyElements) && HasFastSmiElements()); |
| 8467 ((set_capacity_mode == kAllowSmiOnlyElements) && | 8493 if (has_fast_smi_elements) { |
| 8468 (elements()->map()->has_fast_smi_only_elements() || | 8494 if (IsHoleyElementsKind(elements_kind)) { |
| 8469 elements() == heap->empty_fixed_array())); | 8495 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; |
| 8470 ElementsKind elements_kind = has_fast_smi_only_elements | 8496 } else { |
| 8471 ? FAST_SMI_ONLY_ELEMENTS | 8497 new_elements_kind = FAST_SMI_ELEMENTS; |
| 8472 : FAST_ELEMENTS; | 8498 } |
| 8473 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | 8499 } else { |
| 8474 if (!maybe->To(&new_map)) return maybe; | 8500 if (IsHoleyElementsKind(elements_kind)) { |
| 8501 new_elements_kind = FAST_HOLEY_ELEMENTS; | |
| 8502 } else { | |
| 8503 new_elements_kind = FAST_ELEMENTS; | |
| 8504 } | |
| 8475 } | 8505 } |
| 8476 | |
| 8477 FixedArrayBase* old_elements = elements(); | 8506 FixedArrayBase* old_elements = elements(); |
| 8478 ElementsKind elements_kind = GetElementsKind(); | |
| 8479 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8507 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 8480 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) | 8508 accessor->CopyElements(this, new_elements, new_elements_kind); |
|
fschneider
2012/05/09 11:30:33
Missing check for failure? CopyElements has a Mayb
| |
| 8481 ? FAST_SMI_ONLY_ELEMENTS | |
| 8482 : FAST_ELEMENTS; | |
| 8483 // int copy_size = Min(old_elements_raw->length(), new_elements->length()); | |
| 8484 accessor->CopyElements(this, new_elements, to_kind); | |
| 8485 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8509 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8510 Map* new_map = map(); | |
| 8511 if (new_elements_kind != elements_kind) { | |
| 8512 MaybeObject* maybe = | |
| 8513 GetElementsTransitionMap(GetIsolate(), new_elements_kind); | |
| 8514 if (!maybe->To(&new_map)) return maybe; | |
| 8515 } | |
| 8516 #ifdef DEBUG | |
| 8517 ValidateElements(); | |
| 8518 #endif | |
| 8486 set_map_and_elements(new_map, new_elements); | 8519 set_map_and_elements(new_map, new_elements); |
| 8487 } else { | 8520 } else { |
| 8488 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8521 FixedArray* parameter_map = FixedArray::cast(old_elements); |
| 8489 parameter_map->set(1, new_elements); | 8522 parameter_map->set(1, new_elements); |
| 8490 } | 8523 } |
| 8491 | 8524 |
| 8492 if (FLAG_trace_elements_transitions) { | 8525 if (FLAG_trace_elements_transitions) { |
| 8493 PrintElementsTransition(stdout, elements_kind, old_elements, | 8526 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 8494 GetElementsKind(), new_elements); | 8527 GetElementsKind(), new_elements); |
| 8495 } | 8528 } |
| 8496 | 8529 |
| 8497 // Update the length if necessary. | |
| 8498 if (IsJSArray()) { | 8530 if (IsJSArray()) { |
| 8499 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8531 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 8500 } | 8532 } |
| 8501 | |
| 8502 return new_elements; | 8533 return new_elements; |
| 8503 } | 8534 } |
| 8504 | 8535 |
| 8505 | 8536 |
| 8506 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8537 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
| 8507 int capacity, | 8538 int capacity, |
| 8508 int length) { | 8539 int length) { |
| 8509 Heap* heap = GetHeap(); | 8540 Heap* heap = GetHeap(); |
| 8510 // We should never end in here with a pixel or external array. | 8541 // We should never end in here with a pixel or external array. |
| 8511 ASSERT(!HasExternalArrayElements()); | 8542 ASSERT(!HasExternalArrayElements()); |
| 8512 | 8543 |
| 8513 FixedDoubleArray* elems; | 8544 FixedDoubleArray* elems; |
| 8514 { MaybeObject* maybe_obj = | 8545 { MaybeObject* maybe_obj = |
| 8515 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8546 heap->AllocateUninitializedFixedDoubleArray(capacity); |
| 8516 if (!maybe_obj->To(&elems)) return maybe_obj; | 8547 if (!maybe_obj->To(&elems)) return maybe_obj; |
| 8517 } | 8548 } |
| 8518 | 8549 |
| 8550 ElementsKind elements_kind = GetElementsKind(); | |
| 8551 ElementsKind new_elements_kind = elements_kind; | |
| 8552 if (IsHoleyElementsKind(elements_kind)) { | |
| 8553 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; | |
| 8554 } else { | |
| 8555 new_elements_kind = FAST_DOUBLE_ELEMENTS; | |
| 8556 } | |
| 8557 | |
| 8519 Map* new_map; | 8558 Map* new_map; |
| 8520 { MaybeObject* maybe_obj = | 8559 { MaybeObject* maybe_obj = |
| 8521 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); | 8560 GetElementsTransitionMap(heap->isolate(), new_elements_kind); |
| 8522 if (!maybe_obj->To(&new_map)) return maybe_obj; | 8561 if (!maybe_obj->To(&new_map)) return maybe_obj; |
| 8523 } | 8562 } |
| 8524 | 8563 |
| 8525 FixedArrayBase* old_elements = elements(); | 8564 FixedArrayBase* old_elements = elements(); |
| 8526 ElementsKind elements_kind = GetElementsKind(); | |
| 8527 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 8565 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); |
| 8528 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); | 8566 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); |
| 8529 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 8567 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 8568 #ifdef DEBUG | |
| 8569 ValidateElements(); | |
| 8570 #endif | |
| 8530 set_map_and_elements(new_map, elems); | 8571 set_map_and_elements(new_map, elems); |
| 8531 } else { | 8572 } else { |
| 8532 FixedArray* parameter_map = FixedArray::cast(old_elements); | 8573 FixedArray* parameter_map = FixedArray::cast(old_elements); |
| 8533 parameter_map->set(1, elems); | 8574 parameter_map->set(1, elems); |
| 8534 } | 8575 } |
| 8535 | 8576 |
| 8536 if (FLAG_trace_elements_transitions) { | 8577 if (FLAG_trace_elements_transitions) { |
| 8537 PrintElementsTransition(stdout, elements_kind, old_elements, | 8578 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 8538 FAST_DOUBLE_ELEMENTS, elems); | 8579 GetElementsKind(), elems); |
| 8539 } | 8580 } |
| 8540 | 8581 |
| 8541 if (IsJSArray()) { | 8582 if (IsJSArray()) { |
| 8542 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8583 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 8543 } | 8584 } |
| 8544 | 8585 |
| 8545 return this; | 8586 return this; |
| 8546 } | 8587 } |
| 8547 | 8588 |
| 8548 | 8589 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8808 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 8849 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 8809 : UNDEFINED_ELEMENT; | 8850 : UNDEFINED_ELEMENT; |
| 8810 } | 8851 } |
| 8811 | 8852 |
| 8812 // Handle [] on String objects. | 8853 // Handle [] on String objects. |
| 8813 if (this->IsStringObjectWithCharacterAt(index)) { | 8854 if (this->IsStringObjectWithCharacterAt(index)) { |
| 8814 return STRING_CHARACTER_ELEMENT; | 8855 return STRING_CHARACTER_ELEMENT; |
| 8815 } | 8856 } |
| 8816 | 8857 |
| 8817 switch (GetElementsKind()) { | 8858 switch (GetElementsKind()) { |
| 8818 case FAST_SMI_ONLY_ELEMENTS: | 8859 case FAST_SMI_ELEMENTS: |
| 8819 case FAST_ELEMENTS: { | 8860 case FAST_ELEMENTS: |
| 8861 case FAST_HOLEY_SMI_ELEMENTS: | |
| 8862 case FAST_HOLEY_ELEMENTS: { | |
| 8820 uint32_t length = IsJSArray() ? | 8863 uint32_t length = IsJSArray() ? |
| 8821 static_cast<uint32_t> | 8864 static_cast<uint32_t> |
| 8822 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8865 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8823 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8866 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8824 if ((index < length) && | 8867 if ((index < length) && |
| 8825 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8868 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 8826 return FAST_ELEMENT; | 8869 return FAST_ELEMENT; |
| 8827 } | 8870 } |
| 8828 break; | 8871 break; |
| 8829 } | 8872 } |
| 8830 case FAST_DOUBLE_ELEMENTS: { | 8873 case FAST_DOUBLE_ELEMENTS: |
| 8874 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
| 8831 uint32_t length = IsJSArray() ? | 8875 uint32_t length = IsJSArray() ? |
| 8832 static_cast<uint32_t> | 8876 static_cast<uint32_t> |
| 8833 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8877 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 8878 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 8835 if ((index < length) && | 8879 if ((index < length) && |
| 8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | 8880 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
| 8837 return FAST_ELEMENT; | 8881 return FAST_ELEMENT; |
| 8838 } | 8882 } |
| 8839 break; | 8883 break; |
| 8840 } | 8884 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9104 } | 9148 } |
| 9105 | 9149 |
| 9106 | 9150 |
| 9107 // Adding n elements in fast case is O(n*n). | 9151 // Adding n elements in fast case is O(n*n). |
| 9108 // Note: revisit design to have dual undefined values to capture absent | 9152 // Note: revisit design to have dual undefined values to capture absent |
| 9109 // elements. | 9153 // elements. |
| 9110 MaybeObject* JSObject::SetFastElement(uint32_t index, | 9154 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 9111 Object* value, | 9155 Object* value, |
| 9112 StrictModeFlag strict_mode, | 9156 StrictModeFlag strict_mode, |
| 9113 bool check_prototype) { | 9157 bool check_prototype) { |
| 9114 ASSERT(HasFastTypeElements() || | 9158 ASSERT(HasFastSmiOrObjectElements() || |
| 9115 HasFastArgumentsElements()); | 9159 HasFastArgumentsElements()); |
| 9116 | 9160 |
| 9117 FixedArray* backing_store = FixedArray::cast(elements()); | 9161 FixedArray* backing_store = FixedArray::cast(elements()); |
| 9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9162 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 9119 backing_store = FixedArray::cast(backing_store->get(1)); | 9163 backing_store = FixedArray::cast(backing_store->get(1)); |
| 9120 } else { | 9164 } else { |
| 9121 MaybeObject* maybe = EnsureWritableFastElements(); | 9165 MaybeObject* maybe = EnsureWritableFastElements(); |
| 9122 if (!maybe->To(&backing_store)) return maybe; | 9166 if (!maybe->To(&backing_store)) return maybe; |
| 9123 } | 9167 } |
| 9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 9168 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 9125 | 9169 |
| 9126 if (check_prototype && | 9170 if (check_prototype && |
| 9127 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 9171 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
| 9128 bool found; | 9172 bool found; |
| 9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9173 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 9130 value, | 9174 value, |
| 9131 &found, | 9175 &found, |
| 9132 strict_mode); | 9176 strict_mode); |
| 9133 if (found) return result; | 9177 if (found) return result; |
| 9134 } | 9178 } |
| 9135 | 9179 |
| 9136 uint32_t new_capacity = capacity; | 9180 uint32_t new_capacity = capacity; |
| 9137 // Check if the length property of this object needs to be updated. | 9181 // Check if the length property of this object needs to be updated. |
| 9138 uint32_t array_length = 0; | 9182 uint32_t array_length = 0; |
| 9139 bool must_update_array_length = false; | 9183 bool must_update_array_length = false; |
| 9184 bool introduces_holes = true; | |
| 9140 if (IsJSArray()) { | 9185 if (IsJSArray()) { |
| 9141 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9186 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 9187 introduces_holes = index > array_length; | |
| 9142 if (index >= array_length) { | 9188 if (index >= array_length) { |
| 9143 must_update_array_length = true; | 9189 must_update_array_length = true; |
| 9144 array_length = index + 1; | 9190 array_length = index + 1; |
| 9145 } | 9191 } |
| 9192 } else { | |
| 9193 introduces_holes = index >= capacity; | |
| 9146 } | 9194 } |
| 9195 | |
| 9196 // If the array is growing, and it's not growth by a single element at the | |
| 9197 // end, make sure that the ElementsKind is HOLEY. | |
| 9198 ElementsKind elements_kind = GetElementsKind(); | |
| 9199 if (introduces_holes && | |
| 9200 IsFastElementsKind(elements_kind) && | |
| 9201 !IsFastHoleyElementsKind(elements_kind)) { | |
| 9202 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | |
| 9203 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | |
| 9204 if (maybe->IsFailure()) return maybe; | |
| 9205 } | |
| 9206 | |
| 9147 // Check if the capacity of the backing store needs to be increased, or if | 9207 // Check if the capacity of the backing store needs to be increased, or if |
| 9148 // a transition to slow elements is necessary. | 9208 // a transition to slow elements is necessary. |
| 9149 if (index >= capacity) { | 9209 if (index >= capacity) { |
| 9150 bool convert_to_slow = true; | 9210 bool convert_to_slow = true; |
| 9151 if ((index - capacity) < kMaxGap) { | 9211 if ((index - capacity) < kMaxGap) { |
| 9152 new_capacity = NewElementsCapacity(index + 1); | 9212 new_capacity = NewElementsCapacity(index + 1); |
| 9153 ASSERT(new_capacity > index); | 9213 ASSERT(new_capacity > index); |
| 9154 if (!ShouldConvertToSlowElements(new_capacity)) { | 9214 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 9155 convert_to_slow = false; | 9215 convert_to_slow = false; |
| 9156 } | 9216 } |
| 9157 } | 9217 } |
| 9158 if (convert_to_slow) { | 9218 if (convert_to_slow) { |
| 9159 MaybeObject* result = NormalizeElements(); | 9219 MaybeObject* result = NormalizeElements(); |
| 9160 if (result->IsFailure()) return result; | 9220 if (result->IsFailure()) return result; |
| 9161 return SetDictionaryElement(index, value, NONE, strict_mode, | 9221 return SetDictionaryElement(index, value, NONE, strict_mode, |
| 9162 check_prototype); | 9222 check_prototype); |
| 9163 } | 9223 } |
| 9164 } | 9224 } |
| 9165 // Convert to fast double elements if appropriate. | 9225 // Convert to fast double elements if appropriate. |
| 9166 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { | 9226 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
| 9167 MaybeObject* maybe = | 9227 MaybeObject* maybe = |
| 9168 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 9228 SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 9229 array_length); | |
| 9169 if (maybe->IsFailure()) return maybe; | 9230 if (maybe->IsFailure()) return maybe; |
| 9170 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9231 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 9232 #if DEBUG | |
| 9233 ValidateElements(); | |
| 9234 #endif | |
| 9171 return value; | 9235 return value; |
| 9172 } | 9236 } |
| 9173 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9237 // Change elements kind from Smi-only to generic FAST if necessary. |
| 9174 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9238 if (HasFastSmiElements() && !value->IsSmi()) { |
| 9175 Map* new_map; | 9239 Map* new_map; |
| 9176 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 9240 ElementsKind kind = HasFastHoleyElements() |
| 9177 FAST_ELEMENTS); | 9241 ? FAST_HOLEY_ELEMENTS |
| 9178 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9242 : FAST_ELEMENTS; |
| 9179 } | 9243 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
| 9244 kind); | |
| 9245 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 9246 | |
| 9180 set_map(new_map); | 9247 set_map(new_map); |
| 9181 if (FLAG_trace_elements_transitions) { | |
| 9182 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), | |
| 9183 FAST_ELEMENTS, elements()); | |
| 9184 } | |
| 9185 } | 9248 } |
| 9186 // Increase backing store capacity if that's been decided previously. | 9249 // Increase backing store capacity if that's been decided previously. |
| 9187 if (new_capacity != capacity) { | 9250 if (new_capacity != capacity) { |
| 9188 FixedArray* new_elements; | 9251 FixedArray* new_elements; |
| 9189 SetFastElementsCapacityMode set_capacity_mode = | 9252 SetFastElementsCapacitySmiMode smi_mode = |
| 9190 value->IsSmi() && HasFastSmiOnlyElements() | 9253 value->IsSmi() && HasFastSmiElements() |
| 9191 ? kAllowSmiOnlyElements | 9254 ? kAllowSmiOnlyElements |
| 9192 : kDontAllowSmiOnlyElements; | 9255 : kDontAllowSmiOnlyElements; |
| 9193 { MaybeObject* maybe = | 9256 { MaybeObject* maybe = |
| 9194 SetFastElementsCapacityAndLength(new_capacity, | 9257 SetFastElementsCapacityAndLength(new_capacity, |
| 9195 array_length, | 9258 array_length, |
| 9196 set_capacity_mode); | 9259 smi_mode); |
| 9197 if (!maybe->To(&new_elements)) return maybe; | 9260 if (!maybe->To(&new_elements)) return maybe; |
| 9198 } | 9261 } |
| 9199 new_elements->set(index, value); | 9262 new_elements->set(index, value); |
| 9263 #if DEBUG | |
| 9264 ValidateElements(); | |
| 9265 #endif | |
| 9200 return value; | 9266 return value; |
| 9201 } | 9267 } |
| 9268 | |
| 9202 // Finally, set the new element and length. | 9269 // Finally, set the new element and length. |
| 9203 ASSERT(elements()->IsFixedArray()); | 9270 ASSERT(elements()->IsFixedArray()); |
| 9204 backing_store->set(index, value); | 9271 backing_store->set(index, value); |
| 9205 if (must_update_array_length) { | 9272 if (must_update_array_length) { |
| 9206 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 9273 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); |
| 9207 } | 9274 } |
| 9208 return value; | 9275 return value; |
| 9209 } | 9276 } |
| 9210 | 9277 |
| 9211 | 9278 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9315 } | 9382 } |
| 9316 | 9383 |
| 9317 // Attempt to put this object back in fast case. | 9384 // Attempt to put this object back in fast case. |
| 9318 if (ShouldConvertToFastElements()) { | 9385 if (ShouldConvertToFastElements()) { |
| 9319 uint32_t new_length = 0; | 9386 uint32_t new_length = 0; |
| 9320 if (IsJSArray()) { | 9387 if (IsJSArray()) { |
| 9321 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 9388 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 9322 } else { | 9389 } else { |
| 9323 new_length = dictionary->max_number_key() + 1; | 9390 new_length = dictionary->max_number_key() + 1; |
| 9324 } | 9391 } |
| 9325 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays | 9392 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays |
| 9326 ? kAllowSmiOnlyElements | 9393 ? kAllowSmiOnlyElements |
| 9327 : kDontAllowSmiOnlyElements; | 9394 : kDontAllowSmiOnlyElements; |
| 9328 bool has_smi_only_elements = false; | 9395 bool has_smi_only_elements = false; |
| 9329 bool should_convert_to_fast_double_elements = | 9396 bool should_convert_to_fast_double_elements = |
| 9330 ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 9397 ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
| 9331 if (has_smi_only_elements) { | 9398 if (has_smi_only_elements) { |
| 9332 set_capacity_mode = kForceSmiOnlyElements; | 9399 smi_mode = kForceSmiOnlyElements; |
| 9333 } | 9400 } |
| 9334 MaybeObject* result = should_convert_to_fast_double_elements | 9401 MaybeObject* result = should_convert_to_fast_double_elements |
| 9335 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 9402 ? SetFastDoubleElementsCapacityAndLength(new_length, |
| 9403 new_length) | |
| 9336 : SetFastElementsCapacityAndLength(new_length, | 9404 : SetFastElementsCapacityAndLength(new_length, |
| 9337 new_length, | 9405 new_length, |
| 9338 set_capacity_mode); | 9406 smi_mode); |
| 9407 #if DEBUG | |
| 9408 ValidateElements(); | |
|
fschneider
2012/05/09 11:30:33
Maybe check result for failure before calling Vali
| |
| 9409 #endif | |
| 9339 if (result->IsFailure()) return result; | 9410 if (result->IsFailure()) return result; |
| 9340 #ifdef DEBUG | 9411 #ifdef DEBUG |
| 9341 if (FLAG_trace_normalization) { | 9412 if (FLAG_trace_normalization) { |
| 9342 PrintF("Object elements are fast case again:\n"); | 9413 PrintF("Object elements are fast case again:\n"); |
| 9343 Print(); | 9414 Print(); |
| 9344 } | 9415 } |
| 9345 #endif | 9416 #endif |
| 9346 } | 9417 } |
| 9347 return value; | 9418 return value; |
| 9348 } | 9419 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 9367 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 9438 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 9368 value, | 9439 value, |
| 9369 &found, | 9440 &found, |
| 9370 strict_mode); | 9441 strict_mode); |
| 9371 if (found) return result; | 9442 if (found) return result; |
| 9372 } | 9443 } |
| 9373 | 9444 |
| 9374 // If the value object is not a heap number, switch to fast elements and try | 9445 // If the value object is not a heap number, switch to fast elements and try |
| 9375 // again. | 9446 // again. |
| 9376 bool value_is_smi = value->IsSmi(); | 9447 bool value_is_smi = value->IsSmi(); |
| 9448 bool introduces_holes = true; | |
| 9449 uint32_t length = elms_length; | |
| 9450 if (IsJSArray()) { | |
| 9451 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
| 9452 introduces_holes = index > length; | |
| 9453 } else { | |
| 9454 introduces_holes = index >= elms_length; | |
| 9455 } | |
| 9456 | |
| 9377 if (!value->IsNumber()) { | 9457 if (!value->IsNumber()) { |
| 9378 Object* obj; | |
| 9379 uint32_t length = elms_length; | |
| 9380 if (IsJSArray()) { | |
| 9381 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | |
| 9382 } | |
| 9383 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 9458 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( |
| 9384 elms_length, | 9459 elms_length, |
| 9385 length, | 9460 length, |
| 9386 kDontAllowSmiOnlyElements); | 9461 kDontAllowSmiOnlyElements); |
| 9387 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9462 if (maybe_obj->IsFailure()) return maybe_obj; |
| 9388 return SetFastElement(index, | 9463 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); |
| 9389 value, | 9464 if (maybe_obj->IsFailure()) return maybe_obj; |
| 9390 strict_mode, | 9465 #if DEBUG |
| 9391 check_prototype); | 9466 ValidateElements(); |
| 9467 #endif | |
| 9468 return maybe_obj; | |
| 9392 } | 9469 } |
| 9393 | 9470 |
| 9394 double double_value = value_is_smi | 9471 double double_value = value_is_smi |
| 9395 ? static_cast<double>(Smi::cast(value)->value()) | 9472 ? static_cast<double>(Smi::cast(value)->value()) |
| 9396 : HeapNumber::cast(value)->value(); | 9473 : HeapNumber::cast(value)->value(); |
| 9397 | 9474 |
| 9475 // If the array is growing, and it's not growth by a single element at the | |
| 9476 // end, make sure that the ElementsKind is HOLEY. | |
| 9477 ElementsKind elements_kind = GetElementsKind(); | |
| 9478 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { | |
| 9479 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | |
| 9480 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | |
| 9481 if (maybe->IsFailure()) return maybe; | |
| 9482 } | |
| 9483 | |
| 9398 // Check whether there is extra space in the fixed array. | 9484 // Check whether there is extra space in the fixed array. |
| 9399 if (index < elms_length) { | 9485 if (index < elms_length) { |
| 9400 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9486 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 9401 elms->set(index, double_value); | 9487 elms->set(index, double_value); |
| 9402 if (IsJSArray()) { | 9488 if (IsJSArray()) { |
| 9403 // Update the length of the array if needed. | 9489 // Update the length of the array if needed. |
| 9404 uint32_t array_length = 0; | 9490 uint32_t array_length = 0; |
| 9405 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 9491 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 9406 if (index >= array_length) { | 9492 if (index >= array_length) { |
| 9407 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 9493 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 9408 } | 9494 } |
| 9409 } | 9495 } |
| 9410 return value; | 9496 return value; |
| 9411 } | 9497 } |
| 9412 | 9498 |
| 9413 // Allow gap in fast case. | 9499 // Allow gap in fast case. |
| 9414 if ((index - elms_length) < kMaxGap) { | 9500 if ((index - elms_length) < kMaxGap) { |
| 9415 // Try allocating extra space. | 9501 // Try allocating extra space. |
| 9416 int new_capacity = NewElementsCapacity(index+1); | 9502 int new_capacity = NewElementsCapacity(index+1); |
| 9417 if (!ShouldConvertToSlowElements(new_capacity)) { | 9503 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 9418 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 9504 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 9419 Object* obj; | 9505 MaybeObject* maybe_obj = |
| 9420 { MaybeObject* maybe_obj = | 9506 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); |
| 9421 SetFastDoubleElementsCapacityAndLength(new_capacity, | 9507 if (maybe_obj->IsFailure()) return maybe_obj; |
| 9422 index + 1); | |
| 9423 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 9424 } | |
| 9425 FixedDoubleArray::cast(elements())->set(index, double_value); | 9508 FixedDoubleArray::cast(elements())->set(index, double_value); |
| 9509 #if DEBUG | |
| 9510 ValidateElements(); | |
| 9511 #endif | |
| 9426 return value; | 9512 return value; |
| 9427 } | 9513 } |
| 9428 } | 9514 } |
| 9429 | 9515 |
| 9430 // Otherwise default to slow case. | 9516 // Otherwise default to slow case. |
| 9431 ASSERT(HasFastDoubleElements()); | 9517 ASSERT(HasFastDoubleElements()); |
| 9432 ASSERT(map()->has_fast_double_elements()); | 9518 ASSERT(map()->has_fast_double_elements()); |
| 9433 ASSERT(elements()->IsFixedDoubleArray()); | 9519 ASSERT(elements()->IsFixedDoubleArray()); |
| 9434 Object* obj; | 9520 Object* obj; |
| 9435 { MaybeObject* maybe_obj = NormalizeElements(); | 9521 { MaybeObject* maybe_obj = NormalizeElements(); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9559 Object* value, | 9645 Object* value, |
| 9560 PropertyAttributes attr, | 9646 PropertyAttributes attr, |
| 9561 StrictModeFlag strict_mode, | 9647 StrictModeFlag strict_mode, |
| 9562 bool check_prototype, | 9648 bool check_prototype, |
| 9563 SetPropertyMode set_mode) { | 9649 SetPropertyMode set_mode) { |
| 9564 ASSERT(HasDictionaryElements() || | 9650 ASSERT(HasDictionaryElements() || |
| 9565 HasDictionaryArgumentsElements() || | 9651 HasDictionaryArgumentsElements() || |
| 9566 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 9652 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
| 9567 Isolate* isolate = GetIsolate(); | 9653 Isolate* isolate = GetIsolate(); |
| 9568 switch (GetElementsKind()) { | 9654 switch (GetElementsKind()) { |
| 9569 case FAST_SMI_ONLY_ELEMENTS: | 9655 case FAST_SMI_ELEMENTS: |
| 9570 case FAST_ELEMENTS: | 9656 case FAST_ELEMENTS: |
| 9657 case FAST_HOLEY_SMI_ELEMENTS: | |
| 9658 case FAST_HOLEY_ELEMENTS: | |
| 9571 return SetFastElement(index, value, strict_mode, check_prototype); | 9659 return SetFastElement(index, value, strict_mode, check_prototype); |
| 9572 case FAST_DOUBLE_ELEMENTS: | 9660 case FAST_DOUBLE_ELEMENTS: |
| 9661 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 9573 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 9662 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
| 9574 case EXTERNAL_PIXEL_ELEMENTS: { | 9663 case EXTERNAL_PIXEL_ELEMENTS: { |
| 9575 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9664 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 9576 return pixels->SetValue(index, value); | 9665 return pixels->SetValue(index, value); |
| 9577 } | 9666 } |
| 9578 case EXTERNAL_BYTE_ELEMENTS: { | 9667 case EXTERNAL_BYTE_ELEMENTS: { |
| 9579 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 9668 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| 9580 return array->SetValue(index, value); | 9669 return array->SetValue(index, value); |
| 9581 } | 9670 } |
| 9582 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 9671 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9653 ElementsKind to_kind) { | 9742 ElementsKind to_kind) { |
| 9654 CALL_HEAP_FUNCTION(object->GetIsolate(), | 9743 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 9655 object->TransitionElementsKind(to_kind), | 9744 object->TransitionElementsKind(to_kind), |
| 9656 Object); | 9745 Object); |
| 9657 } | 9746 } |
| 9658 | 9747 |
| 9659 | 9748 |
| 9660 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 9749 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
| 9661 ElementsKind from_kind = map()->elements_kind(); | 9750 ElementsKind from_kind = map()->elements_kind(); |
| 9662 | 9751 |
| 9752 if (IsFastHoleyElementsKind(from_kind)) { | |
| 9753 to_kind = GetHoleyElementsKind(to_kind); | |
| 9754 } | |
| 9755 | |
| 9663 Isolate* isolate = GetIsolate(); | 9756 Isolate* isolate = GetIsolate(); |
| 9664 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9757 |
| 9665 (to_kind == FAST_ELEMENTS || | 9758 if (elements() == isolate->heap()->empty_fixed_array() || |
| 9666 elements() == isolate->heap()->empty_fixed_array())) { | 9759 (IsFastSmiOrObjectElementsKind(from_kind) && |
| 9760 IsFastSmiOrObjectElementsKind(to_kind)) || | |
| 9761 (from_kind == FAST_DOUBLE_ELEMENTS && | |
| 9762 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | |
| 9763 // No change is needed to the elements() buffer, the transition | |
| 9764 // only requires a map change. | |
| 9667 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 9765 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
| 9668 Map* new_map; | 9766 Map* new_map; |
| 9669 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 9767 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 9670 set_map(new_map); | 9768 set_map(new_map); |
| 9671 if (FLAG_trace_elements_transitions) { | 9769 if (FLAG_trace_elements_transitions) { |
| 9672 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9770 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
| 9673 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 9771 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
| 9674 } | 9772 } |
| 9675 return this; | 9773 return this; |
| 9676 } | 9774 } |
| 9677 | 9775 |
| 9678 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 9776 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
| 9679 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 9777 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
| 9680 uint32_t length = capacity; | 9778 uint32_t length = capacity; |
| 9681 | 9779 |
| 9682 if (IsJSArray()) { | 9780 if (IsJSArray()) { |
| 9683 Object* raw_length = JSArray::cast(this)->length(); | 9781 Object* raw_length = JSArray::cast(this)->length(); |
| 9684 if (raw_length->IsUndefined()) { | 9782 if (raw_length->IsUndefined()) { |
| 9685 // If length is undefined, then JSArray is being initialized and has no | 9783 // If length is undefined, then JSArray is being initialized and has no |
| 9686 // elements, assume a length of zero. | 9784 // elements, assume a length of zero. |
| 9687 length = 0; | 9785 length = 0; |
| 9688 } else { | 9786 } else { |
| 9689 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9787 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9690 } | 9788 } |
| 9691 } | 9789 } |
| 9692 | 9790 |
| 9693 if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9791 if (IsFastSmiElementsKind(from_kind) && |
| 9694 to_kind == FAST_DOUBLE_ELEMENTS) { | 9792 IsFastDoubleElementsKind(to_kind)) { |
| 9695 MaybeObject* maybe_result = | 9793 MaybeObject* maybe_result = |
| 9696 SetFastDoubleElementsCapacityAndLength(capacity, length); | 9794 SetFastDoubleElementsCapacityAndLength(capacity, length); |
| 9697 if (maybe_result->IsFailure()) return maybe_result; | 9795 if (maybe_result->IsFailure()) return maybe_result; |
| 9796 #if DEBUG | |
| 9797 ValidateElements(); | |
| 9798 #endif | |
| 9698 return this; | 9799 return this; |
| 9699 } | 9800 } |
| 9700 | 9801 |
| 9701 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 9802 if (IsFastDoubleElementsKind(from_kind) && |
| 9803 IsFastObjectElementsKind(to_kind)) { | |
| 9702 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 9804 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
| 9703 capacity, length, kDontAllowSmiOnlyElements); | 9805 capacity, length, kDontAllowSmiOnlyElements); |
| 9704 if (maybe_result->IsFailure()) return maybe_result; | 9806 if (maybe_result->IsFailure()) return maybe_result; |
| 9807 #if DEBUG | |
| 9808 ValidateElements(); | |
| 9809 #endif | |
| 9705 return this; | 9810 return this; |
| 9706 } | 9811 } |
| 9707 | 9812 |
| 9708 // This method should never be called for any other case than the ones | 9813 // This method should never be called for any other case than the ones |
| 9709 // handled above. | 9814 // handled above. |
| 9710 UNREACHABLE(); | 9815 UNREACHABLE(); |
| 9711 return GetIsolate()->heap()->null_value(); | 9816 return GetIsolate()->heap()->null_value(); |
| 9712 } | 9817 } |
| 9713 | 9818 |
| 9714 | 9819 |
| 9715 // static | 9820 // static |
| 9716 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 9821 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
| 9717 ElementsKind to_kind) { | 9822 ElementsKind to_kind) { |
| 9718 return | 9823 // Transitions can't go backwards. |
| 9719 (from_kind == FAST_SMI_ONLY_ELEMENTS && | 9824 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
| 9720 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || | 9825 return false; |
| 9721 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); | 9826 } |
| 9827 | |
| 9828 // Transitions from HOLEY -> PACKED are not allowed. | |
| 9829 return !IsFastHoleyElementsKind(from_kind) || | |
| 9830 IsFastHoleyElementsKind(to_kind); | |
| 9722 } | 9831 } |
| 9723 | 9832 |
| 9724 | 9833 |
| 9725 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 9834 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 9726 Object* value) { | 9835 Object* value) { |
| 9727 uint32_t old_len = 0; | 9836 uint32_t old_len = 0; |
| 9728 CHECK(length()->ToArrayIndex(&old_len)); | 9837 CHECK(length()->ToArrayIndex(&old_len)); |
| 9729 // Check to see if we need to update the length. For now, we make | 9838 // Check to see if we need to update the length. For now, we make |
| 9730 // sure that the length stays within 32-bits (unsigned). | 9839 // sure that the length stays within 32-bits (unsigned). |
| 9731 if (index >= old_len && index != 0xffffffff) { | 9840 if (index >= old_len && index != 0xffffffff) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9802 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 9911 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 9803 backing_store = FixedArray::cast(backing_store_base); | 9912 backing_store = FixedArray::cast(backing_store_base); |
| 9804 if (backing_store->IsDictionary()) { | 9913 if (backing_store->IsDictionary()) { |
| 9805 SeededNumberDictionary* dictionary = | 9914 SeededNumberDictionary* dictionary = |
| 9806 SeededNumberDictionary::cast(backing_store); | 9915 SeededNumberDictionary::cast(backing_store); |
| 9807 *capacity = dictionary->Capacity(); | 9916 *capacity = dictionary->Capacity(); |
| 9808 *used = dictionary->NumberOfElements(); | 9917 *used = dictionary->NumberOfElements(); |
| 9809 break; | 9918 break; |
| 9810 } | 9919 } |
| 9811 // Fall through. | 9920 // Fall through. |
| 9812 case FAST_SMI_ONLY_ELEMENTS: | 9921 case FAST_SMI_ELEMENTS: |
| 9813 case FAST_ELEMENTS: | 9922 case FAST_ELEMENTS: |
| 9923 case FAST_HOLEY_SMI_ELEMENTS: | |
| 9924 case FAST_HOLEY_ELEMENTS: | |
| 9814 backing_store = FixedArray::cast(backing_store_base); | 9925 backing_store = FixedArray::cast(backing_store_base); |
| 9815 *capacity = backing_store->length(); | 9926 *capacity = backing_store->length(); |
| 9816 for (int i = 0; i < *capacity; ++i) { | 9927 for (int i = 0; i < *capacity; ++i) { |
| 9817 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 9928 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 9818 } | 9929 } |
| 9819 break; | 9930 break; |
| 9820 case DICTIONARY_ELEMENTS: { | 9931 case DICTIONARY_ELEMENTS: { |
| 9821 SeededNumberDictionary* dictionary = | 9932 SeededNumberDictionary* dictionary = |
| 9822 SeededNumberDictionary::cast(FixedArray::cast(elements())); | 9933 SeededNumberDictionary::cast(FixedArray::cast(elements())); |
| 9823 *capacity = dictionary->Capacity(); | 9934 *capacity = dictionary->Capacity(); |
| 9824 *used = dictionary->NumberOfElements(); | 9935 *used = dictionary->NumberOfElements(); |
| 9825 break; | 9936 break; |
| 9826 } | 9937 } |
| 9827 case FAST_DOUBLE_ELEMENTS: { | 9938 case FAST_DOUBLE_ELEMENTS: |
| 9939 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
| 9828 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9940 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 9829 *capacity = elms->length(); | 9941 *capacity = elms->length(); |
| 9830 for (int i = 0; i < *capacity; i++) { | 9942 for (int i = 0; i < *capacity; i++) { |
| 9831 if (!elms->is_the_hole(i)) ++(*used); | 9943 if (!elms->is_the_hole(i)) ++(*used); |
| 9832 } | 9944 } |
| 9833 break; | 9945 break; |
| 9834 } | 9946 } |
| 9835 case EXTERNAL_BYTE_ELEMENTS: | 9947 case EXTERNAL_BYTE_ELEMENTS: |
| 9836 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9948 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 9837 case EXTERNAL_SHORT_ELEMENTS: | 9949 case EXTERNAL_SHORT_ELEMENTS: |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10087 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10199 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 10088 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 10200 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 10089 return false; | 10201 return false; |
| 10090 } | 10202 } |
| 10091 } | 10203 } |
| 10092 | 10204 |
| 10093 // Handle [] on String objects. | 10205 // Handle [] on String objects. |
| 10094 if (this->IsStringObjectWithCharacterAt(index)) return true; | 10206 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 10095 | 10207 |
| 10096 switch (GetElementsKind()) { | 10208 switch (GetElementsKind()) { |
| 10097 case FAST_SMI_ONLY_ELEMENTS: | 10209 case FAST_SMI_ELEMENTS: |
| 10098 case FAST_ELEMENTS: { | 10210 case FAST_ELEMENTS: |
| 10099 uint32_t length = IsJSArray() ? | 10211 case FAST_HOLEY_SMI_ELEMENTS: |
| 10212 case FAST_HOLEY_ELEMENTS: { | |
| 10213 uint32_t length = IsJSArray() ? | |
| 10100 static_cast<uint32_t>( | 10214 static_cast<uint32_t>( |
| 10101 Smi::cast(JSArray::cast(this)->length())->value()) : | 10215 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 10102 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10216 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 10103 return (index < length) && | 10217 return (index < length) && |
| 10104 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 10218 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 10105 } | 10219 } |
| 10106 case FAST_DOUBLE_ELEMENTS: { | 10220 case FAST_DOUBLE_ELEMENTS: |
| 10221 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
| 10107 uint32_t length = IsJSArray() ? | 10222 uint32_t length = IsJSArray() ? |
| 10108 static_cast<uint32_t>( | 10223 static_cast<uint32_t>( |
| 10109 Smi::cast(JSArray::cast(this)->length())->value()) : | 10224 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 10110 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | 10225 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 10111 return (index < length) && | 10226 return (index < length) && |
| 10112 !FixedDoubleArray::cast(elements())->is_the_hole(index); | 10227 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
| 10113 break; | 10228 break; |
| 10114 } | 10229 } |
| 10115 case EXTERNAL_PIXEL_ELEMENTS: { | 10230 case EXTERNAL_PIXEL_ELEMENTS: { |
| 10116 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 10231 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10296 } | 10411 } |
| 10297 | 10412 |
| 10298 | 10413 |
| 10299 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 10414 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
| 10300 return GetLocalElementKeys(NULL, filter); | 10415 return GetLocalElementKeys(NULL, filter); |
| 10301 } | 10416 } |
| 10302 | 10417 |
| 10303 | 10418 |
| 10304 int JSObject::NumberOfEnumElements() { | 10419 int JSObject::NumberOfEnumElements() { |
| 10305 // Fast case for objects with no elements. | 10420 // Fast case for objects with no elements. |
| 10306 if (!IsJSValue() && HasFastElements()) { | 10421 if (!IsJSValue() && HasFastObjectElements()) { |
| 10307 uint32_t length = IsJSArray() ? | 10422 uint32_t length = IsJSArray() ? |
| 10308 static_cast<uint32_t>( | 10423 static_cast<uint32_t>( |
| 10309 Smi::cast(JSArray::cast(this)->length())->value()) : | 10424 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 10310 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 10425 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 10311 if (length == 0) return 0; | 10426 if (length == 0) return 0; |
| 10312 } | 10427 } |
| 10313 // Compute the number of enumerable elements. | 10428 // Compute the number of enumerable elements. |
| 10314 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 10429 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
| 10315 } | 10430 } |
| 10316 | 10431 |
| 10317 | 10432 |
| 10318 int JSObject::GetLocalElementKeys(FixedArray* storage, | 10433 int JSObject::GetLocalElementKeys(FixedArray* storage, |
| 10319 PropertyAttributes filter) { | 10434 PropertyAttributes filter) { |
| 10320 int counter = 0; | 10435 int counter = 0; |
| 10321 switch (GetElementsKind()) { | 10436 switch (GetElementsKind()) { |
| 10322 case FAST_SMI_ONLY_ELEMENTS: | 10437 case FAST_SMI_ELEMENTS: |
| 10323 case FAST_ELEMENTS: { | 10438 case FAST_ELEMENTS: |
| 10439 case FAST_HOLEY_SMI_ELEMENTS: | |
| 10440 case FAST_HOLEY_ELEMENTS: { | |
| 10324 int length = IsJSArray() ? | 10441 int length = IsJSArray() ? |
| 10325 Smi::cast(JSArray::cast(this)->length())->value() : | 10442 Smi::cast(JSArray::cast(this)->length())->value() : |
| 10326 FixedArray::cast(elements())->length(); | 10443 FixedArray::cast(elements())->length(); |
| 10327 for (int i = 0; i < length; i++) { | 10444 for (int i = 0; i < length; i++) { |
| 10328 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 10445 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 10329 if (storage != NULL) { | 10446 if (storage != NULL) { |
| 10330 storage->set(counter, Smi::FromInt(i)); | 10447 storage->set(counter, Smi::FromInt(i)); |
| 10331 } | 10448 } |
| 10332 counter++; | 10449 counter++; |
| 10333 } | 10450 } |
| 10334 } | 10451 } |
| 10335 ASSERT(!storage || storage->length() >= counter); | 10452 ASSERT(!storage || storage->length() >= counter); |
| 10336 break; | 10453 break; |
| 10337 } | 10454 } |
| 10338 case FAST_DOUBLE_ELEMENTS: { | 10455 case FAST_DOUBLE_ELEMENTS: |
| 10456 case FAST_HOLEY_DOUBLE_ELEMENTS: { | |
| 10339 int length = IsJSArray() ? | 10457 int length = IsJSArray() ? |
| 10340 Smi::cast(JSArray::cast(this)->length())->value() : | 10458 Smi::cast(JSArray::cast(this)->length())->value() : |
| 10341 FixedDoubleArray::cast(elements())->length(); | 10459 FixedDoubleArray::cast(elements())->length(); |
| 10342 for (int i = 0; i < length; i++) { | 10460 for (int i = 0; i < length; i++) { |
| 10343 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { | 10461 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
| 10344 if (storage != NULL) { | 10462 if (storage != NULL) { |
| 10345 storage->set(counter, Smi::FromInt(i)); | 10463 storage->set(counter, Smi::FromInt(i)); |
| 10346 } | 10464 } |
| 10347 counter++; | 10465 counter++; |
| 10348 } | 10466 } |
| (...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11261 // Convert to fast elements containing only the existing properties. | 11379 // Convert to fast elements containing only the existing properties. |
| 11262 // Ordering is irrelevant, since we are going to sort anyway. | 11380 // Ordering is irrelevant, since we are going to sort anyway. |
| 11263 SeededNumberDictionary* dict = element_dictionary(); | 11381 SeededNumberDictionary* dict = element_dictionary(); |
| 11264 if (IsJSArray() || dict->requires_slow_elements() || | 11382 if (IsJSArray() || dict->requires_slow_elements() || |
| 11265 dict->max_number_key() >= limit) { | 11383 dict->max_number_key() >= limit) { |
| 11266 return PrepareSlowElementsForSort(limit); | 11384 return PrepareSlowElementsForSort(limit); |
| 11267 } | 11385 } |
| 11268 // Convert to fast elements. | 11386 // Convert to fast elements. |
| 11269 | 11387 |
| 11270 Object* obj; | 11388 Object* obj; |
| 11271 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 11389 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), |
| 11272 FAST_ELEMENTS); | 11390 FAST_HOLEY_ELEMENTS); |
| 11273 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11391 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11274 } | |
| 11275 Map* new_map = Map::cast(obj); | 11392 Map* new_map = Map::cast(obj); |
| 11276 | 11393 |
| 11277 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 11394 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
| 11278 Object* new_array; | 11395 Object* new_array; |
| 11279 { MaybeObject* maybe_new_array = | 11396 { MaybeObject* maybe_new_array = |
| 11280 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 11397 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
| 11281 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 11398 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
| 11282 } | 11399 } |
| 11283 FixedArray* fast_elements = FixedArray::cast(new_array); | 11400 FixedArray* fast_elements = FixedArray::cast(new_array); |
| 11284 dict->CopyValuesTo(fast_elements); | 11401 dict->CopyValuesTo(fast_elements); |
| 11285 | 11402 |
| 11286 set_map(new_map); | 11403 #ifdef DEBUG |
| 11287 set_elements(fast_elements); | 11404 ValidateElements(); |
| 11405 #endif | |
| 11406 set_map_and_elements(new_map, fast_elements); | |
| 11288 } else if (HasExternalArrayElements()) { | 11407 } else if (HasExternalArrayElements()) { |
| 11289 // External arrays cannot have holes or undefined elements. | 11408 // External arrays cannot have holes or undefined elements. |
| 11290 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 11409 return Smi::FromInt(ExternalArray::cast(elements())->length()); |
| 11291 } else if (!HasFastDoubleElements()) { | 11410 } else if (!HasFastDoubleElements()) { |
| 11292 Object* obj; | 11411 Object* obj; |
| 11293 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 11412 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 11294 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11413 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11295 } | 11414 } |
| 11296 } | 11415 } |
| 11297 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); | 11416 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); |
| 11298 | 11417 |
| 11299 // Collect holes at the end, undefined before that and the rest at the | 11418 // Collect holes at the end, undefined before that and the rest at the |
| 11300 // start, and return the number of non-hole, non-undefined values. | 11419 // start, and return the number of non-hole, non-undefined values. |
| 11301 | 11420 |
| 11302 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 11421 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); |
| 11303 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 11422 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 11304 if (limit > elements_length) { | 11423 if (limit > elements_length) { |
| 11305 limit = elements_length ; | 11424 limit = elements_length ; |
| 11306 } | 11425 } |
| 11307 if (limit == 0) { | 11426 if (limit == 0) { |
| (...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12964 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13083 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 12965 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13084 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 12966 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13085 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 12967 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13086 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 12968 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13087 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 12969 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13088 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 12970 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13089 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 12971 } | 13090 } |
| 12972 | 13091 |
| 12973 } } // namespace v8::internal | 13092 } } // namespace v8::internal |
| OLD | NEW |