| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 switch (map()->instance_type()) { | 999 switch (map()->instance_type()) { |
| 1000 case MAP_TYPE: | 1000 case MAP_TYPE: |
| 1001 accumulator->Add("<Map>"); | 1001 accumulator->Add("<Map>"); |
| 1002 break; | 1002 break; |
| 1003 case FIXED_ARRAY_TYPE: | 1003 case FIXED_ARRAY_TYPE: |
| 1004 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); | 1004 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); |
| 1005 break; | 1005 break; |
| 1006 case BYTE_ARRAY_TYPE: | 1006 case BYTE_ARRAY_TYPE: |
| 1007 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); | 1007 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); |
| 1008 break; | 1008 break; |
| 1009 case PIXEL_ARRAY_TYPE: |
| 1010 accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length()); |
| 1011 break; |
| 1009 case SHARED_FUNCTION_INFO_TYPE: | 1012 case SHARED_FUNCTION_INFO_TYPE: |
| 1010 accumulator->Add("<SharedFunctionInfo>"); | 1013 accumulator->Add("<SharedFunctionInfo>"); |
| 1011 break; | 1014 break; |
| 1012 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1015 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 1013 case NAME##_TYPE: \ | 1016 case NAME##_TYPE: \ |
| 1014 accumulator->Put('<'); \ | 1017 accumulator->Put('<'); \ |
| 1015 accumulator->Add(#Name); \ | 1018 accumulator->Add(#Name); \ |
| 1016 accumulator->Put('>'); \ | 1019 accumulator->Put('>'); \ |
| 1017 break; | 1020 break; |
| 1018 STRUCT_LIST(MAKE_STRUCT_CASE) | 1021 STRUCT_LIST(MAKE_STRUCT_CASE) |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 case CODE_TYPE: | 1143 case CODE_TYPE: |
| 1141 reinterpret_cast<Code*>(this)->CodeIterateBody(v); | 1144 reinterpret_cast<Code*>(this)->CodeIterateBody(v); |
| 1142 break; | 1145 break; |
| 1143 case JS_GLOBAL_PROPERTY_CELL_TYPE: | 1146 case JS_GLOBAL_PROPERTY_CELL_TYPE: |
| 1144 reinterpret_cast<JSGlobalPropertyCell*>(this) | 1147 reinterpret_cast<JSGlobalPropertyCell*>(this) |
| 1145 ->JSGlobalPropertyCellIterateBody(v); | 1148 ->JSGlobalPropertyCellIterateBody(v); |
| 1146 break; | 1149 break; |
| 1147 case HEAP_NUMBER_TYPE: | 1150 case HEAP_NUMBER_TYPE: |
| 1148 case FILLER_TYPE: | 1151 case FILLER_TYPE: |
| 1149 case BYTE_ARRAY_TYPE: | 1152 case BYTE_ARRAY_TYPE: |
| 1153 case PIXEL_ARRAY_TYPE: |
| 1150 break; | 1154 break; |
| 1151 case SHARED_FUNCTION_INFO_TYPE: { | 1155 case SHARED_FUNCTION_INFO_TYPE: { |
| 1152 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this); | 1156 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this); |
| 1153 shared->SharedFunctionInfoIterateBody(v); | 1157 shared->SharedFunctionInfoIterateBody(v); |
| 1154 break; | 1158 break; |
| 1155 } | 1159 } |
| 1156 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1160 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 1157 case NAME##_TYPE: | 1161 case NAME##_TYPE: |
| 1158 STRUCT_LIST(MAKE_STRUCT_CASE) | 1162 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 1159 #undef MAKE_STRUCT_CASE | 1163 #undef MAKE_STRUCT_CASE |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 } | 1666 } |
| 1663 } | 1667 } |
| 1664 result->NotFound(); | 1668 result->NotFound(); |
| 1665 } | 1669 } |
| 1666 | 1670 |
| 1667 | 1671 |
| 1668 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) { | 1672 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) { |
| 1669 for (Object* pt = GetPrototype(); | 1673 for (Object* pt = GetPrototype(); |
| 1670 pt != Heap::null_value(); | 1674 pt != Heap::null_value(); |
| 1671 pt = pt->GetPrototype()) { | 1675 pt = pt->GetPrototype()) { |
| 1672 if (JSObject::cast(pt)->HasFastElements()) continue; | 1676 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 1677 continue; |
| 1678 } |
| 1673 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1679 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1674 int entry = dictionary->FindEntry(index); | 1680 int entry = dictionary->FindEntry(index); |
| 1675 if (entry != NumberDictionary::kNotFound) { | 1681 if (entry != NumberDictionary::kNotFound) { |
| 1676 Object* element = dictionary->ValueAt(entry); | 1682 Object* element = dictionary->ValueAt(entry); |
| 1677 PropertyDetails details = dictionary->DetailsAt(entry); | 1683 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1678 if (details.type() == CALLBACKS) { | 1684 if (details.type() == CALLBACKS) { |
| 1679 // Only accessors allowed as elements. | 1685 // Only accessors allowed as elements. |
| 1680 return FixedArray::cast(element)->get(kSetterIndex); | 1686 return FixedArray::cast(element)->get(kSetterIndex); |
| 1681 } | 1687 } |
| 1682 } | 1688 } |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2224 | 2230 |
| 2225 Object* JSObject::TransformToFastProperties(int unused_property_fields) { | 2231 Object* JSObject::TransformToFastProperties(int unused_property_fields) { |
| 2226 if (HasFastProperties()) return this; | 2232 if (HasFastProperties()) return this; |
| 2227 ASSERT(!IsGlobalObject()); | 2233 ASSERT(!IsGlobalObject()); |
| 2228 return property_dictionary()-> | 2234 return property_dictionary()-> |
| 2229 TransformPropertiesToFastFor(this, unused_property_fields); | 2235 TransformPropertiesToFastFor(this, unused_property_fields); |
| 2230 } | 2236 } |
| 2231 | 2237 |
| 2232 | 2238 |
| 2233 Object* JSObject::NormalizeElements() { | 2239 Object* JSObject::NormalizeElements() { |
| 2234 if (!HasFastElements()) return this; | 2240 ASSERT(!HasPixelElements()); |
| 2241 if (HasDictionaryElements()) return this; |
| 2235 | 2242 |
| 2236 // Get number of entries. | 2243 // Get number of entries. |
| 2237 FixedArray* array = FixedArray::cast(elements()); | 2244 FixedArray* array = FixedArray::cast(elements()); |
| 2238 | 2245 |
| 2239 // Compute the effective length. | 2246 // Compute the effective length. |
| 2240 int length = IsJSArray() ? | 2247 int length = IsJSArray() ? |
| 2241 Smi::cast(JSArray::cast(this)->length())->value() : | 2248 Smi::cast(JSArray::cast(this)->length())->value() : |
| 2242 array->length(); | 2249 array->length(); |
| 2243 Object* obj = NumberDictionary::Allocate(length); | 2250 Object* obj = NumberDictionary::Allocate(length); |
| 2244 if (obj->IsFailure()) return obj; | 2251 if (obj->IsFailure()) return obj; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 } | 2317 } |
| 2311 Object* raw_result = | 2318 Object* raw_result = |
| 2312 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); | 2319 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); |
| 2313 RETURN_IF_SCHEDULED_EXCEPTION(); | 2320 RETURN_IF_SCHEDULED_EXCEPTION(); |
| 2314 return raw_result; | 2321 return raw_result; |
| 2315 } | 2322 } |
| 2316 | 2323 |
| 2317 | 2324 |
| 2318 Object* JSObject::DeleteElementPostInterceptor(uint32_t index, | 2325 Object* JSObject::DeleteElementPostInterceptor(uint32_t index, |
| 2319 DeleteMode mode) { | 2326 DeleteMode mode) { |
| 2320 if (HasFastElements()) { | 2327 ASSERT(!HasPixelElements()); |
| 2321 uint32_t length = IsJSArray() ? | 2328 switch (GetElementsKind()) { |
| 2329 case FAST_ELEMENTS: { |
| 2330 uint32_t length = IsJSArray() ? |
| 2322 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2331 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2323 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2332 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2324 if (index < length) { | 2333 if (index < length) { |
| 2325 FixedArray::cast(elements())->set_the_hole(index); | 2334 FixedArray::cast(elements())->set_the_hole(index); |
| 2335 } |
| 2336 break; |
| 2326 } | 2337 } |
| 2327 return Heap::true_value(); | 2338 case DICTIONARY_ELEMENTS: { |
| 2328 } | 2339 NumberDictionary* dictionary = element_dictionary(); |
| 2329 ASSERT(!HasFastElements()); | 2340 int entry = dictionary->FindEntry(index); |
| 2330 NumberDictionary* dictionary = element_dictionary(); | 2341 if (entry != NumberDictionary::kNotFound) { |
| 2331 int entry = dictionary->FindEntry(index); | 2342 return dictionary->DeleteProperty(entry, mode); |
| 2332 if (entry != NumberDictionary::kNotFound) { | 2343 } |
| 2333 return dictionary->DeleteProperty(entry, mode); | 2344 break; |
| 2345 } |
| 2346 default: |
| 2347 UNREACHABLE(); |
| 2348 break; |
| 2334 } | 2349 } |
| 2335 return Heap::true_value(); | 2350 return Heap::true_value(); |
| 2336 } | 2351 } |
| 2337 | 2352 |
| 2338 | 2353 |
| 2339 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 2354 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 2340 // Make sure that the top context does not change when doing | 2355 // Make sure that the top context does not change when doing |
| 2341 // callbacks or interceptor calls. | 2356 // callbacks or interceptor calls. |
| 2342 AssertNoContextChange ncc; | 2357 AssertNoContextChange ncc; |
| 2343 HandleScope scope; | 2358 HandleScope scope; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2385 } | 2400 } |
| 2386 | 2401 |
| 2387 if (HasIndexedInterceptor()) { | 2402 if (HasIndexedInterceptor()) { |
| 2388 // Skip interceptor if forcing deletion. | 2403 // Skip interceptor if forcing deletion. |
| 2389 if (mode == FORCE_DELETION) { | 2404 if (mode == FORCE_DELETION) { |
| 2390 return DeleteElementPostInterceptor(index, mode); | 2405 return DeleteElementPostInterceptor(index, mode); |
| 2391 } | 2406 } |
| 2392 return DeleteElementWithInterceptor(index); | 2407 return DeleteElementWithInterceptor(index); |
| 2393 } | 2408 } |
| 2394 | 2409 |
| 2395 if (HasFastElements()) { | 2410 switch (GetElementsKind()) { |
| 2396 uint32_t length = IsJSArray() ? | 2411 case FAST_ELEMENTS: { |
| 2412 uint32_t length = IsJSArray() ? |
| 2397 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2413 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2398 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2414 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2399 if (index < length) { | 2415 if (index < length) { |
| 2400 FixedArray::cast(elements())->set_the_hole(index); | 2416 FixedArray::cast(elements())->set_the_hole(index); |
| 2417 } |
| 2418 break; |
| 2401 } | 2419 } |
| 2402 return Heap::true_value(); | 2420 case PIXEL_ELEMENTS: { |
| 2403 } else { | 2421 // Pixel elements cannot be deleted. Just silently ignore here. |
| 2404 NumberDictionary* dictionary = element_dictionary(); | 2422 break; |
| 2405 int entry = dictionary->FindEntry(index); | |
| 2406 if (entry != NumberDictionary::kNotFound) { | |
| 2407 return dictionary->DeleteProperty(entry, mode); | |
| 2408 } | 2423 } |
| 2424 case DICTIONARY_ELEMENTS: { |
| 2425 NumberDictionary* dictionary = element_dictionary(); |
| 2426 int entry = dictionary->FindEntry(index); |
| 2427 if (entry != NumberDictionary::kNotFound) { |
| 2428 return dictionary->DeleteProperty(entry, mode); |
| 2429 } |
| 2430 break; |
| 2431 } |
| 2432 default: |
| 2433 UNREACHABLE(); |
| 2434 break; |
| 2409 } | 2435 } |
| 2410 return Heap::true_value(); | 2436 return Heap::true_value(); |
| 2411 } | 2437 } |
| 2412 | 2438 |
| 2413 | 2439 |
| 2414 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 2440 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 2415 // ECMA-262, 3rd, 8.6.2.5 | 2441 // ECMA-262, 3rd, 8.6.2.5 |
| 2416 ASSERT(name->IsString()); | 2442 ASSERT(name->IsString()); |
| 2417 | 2443 |
| 2418 // Check access rights if needed. | 2444 // Check access rights if needed. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2476 return true; | 2502 return true; |
| 2477 } | 2503 } |
| 2478 | 2504 |
| 2479 // Check if the object is among the named properties. | 2505 // Check if the object is among the named properties. |
| 2480 Object* key = SlowReverseLookup(obj); | 2506 Object* key = SlowReverseLookup(obj); |
| 2481 if (key != Heap::undefined_value()) { | 2507 if (key != Heap::undefined_value()) { |
| 2482 return true; | 2508 return true; |
| 2483 } | 2509 } |
| 2484 | 2510 |
| 2485 // Check if the object is among the indexed properties. | 2511 // Check if the object is among the indexed properties. |
| 2486 if (HasFastElements()) { | 2512 switch (GetElementsKind()) { |
| 2487 int length = IsJSArray() | 2513 case PIXEL_ELEMENTS: |
| 2488 ? Smi::cast(JSArray::cast(this)->length())->value() | 2514 // Raw pixels do not reference other objects. |
| 2489 : FixedArray::cast(elements())->length(); | 2515 break; |
| 2490 for (int i = 0; i < length; i++) { | 2516 case FAST_ELEMENTS: { |
| 2491 Object* element = FixedArray::cast(elements())->get(i); | 2517 int length = IsJSArray() ? |
| 2492 if (!element->IsTheHole() && element == obj) { | 2518 Smi::cast(JSArray::cast(this)->length())->value() : |
| 2519 FixedArray::cast(elements())->length(); |
| 2520 for (int i = 0; i < length; i++) { |
| 2521 Object* element = FixedArray::cast(elements())->get(i); |
| 2522 if (!element->IsTheHole() && element == obj) { |
| 2523 return true; |
| 2524 } |
| 2525 } |
| 2526 break; |
| 2527 } |
| 2528 case DICTIONARY_ELEMENTS: { |
| 2529 key = element_dictionary()->SlowReverseLookup(obj); |
| 2530 if (key != Heap::undefined_value()) { |
| 2493 return true; | 2531 return true; |
| 2494 } | 2532 } |
| 2533 break; |
| 2495 } | 2534 } |
| 2496 } else { | 2535 default: |
| 2497 key = element_dictionary()->SlowReverseLookup(obj); | 2536 UNREACHABLE(); |
| 2498 if (key != Heap::undefined_value()) { | 2537 break; |
| 2499 return true; | |
| 2500 } | |
| 2501 } | 2538 } |
| 2502 | 2539 |
| 2503 // For functions check the context. Boilerplate functions do | 2540 // For functions check the context. Boilerplate functions do |
| 2504 // not have to be traversed since they have no real context. | 2541 // not have to be traversed since they have no real context. |
| 2505 if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) { | 2542 if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) { |
| 2506 // Get the constructor function for arguments array. | 2543 // Get the constructor function for arguments array. |
| 2507 JSObject* arguments_boilerplate = | 2544 JSObject* arguments_boilerplate = |
| 2508 Top::context()->global_context()->arguments_boilerplate(); | 2545 Top::context()->global_context()->arguments_boilerplate(); |
| 2509 JSFunction* arguments_function = | 2546 JSFunction* arguments_function = |
| 2510 JSFunction::cast(arguments_boilerplate->map()->constructor()); | 2547 JSFunction::cast(arguments_boilerplate->map()->constructor()); |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2708 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 2745 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
| 2709 return Heap::undefined_value(); | 2746 return Heap::undefined_value(); |
| 2710 } | 2747 } |
| 2711 } | 2748 } |
| 2712 | 2749 |
| 2713 uint32_t index; | 2750 uint32_t index; |
| 2714 bool is_element = name->AsArrayIndex(&index); | 2751 bool is_element = name->AsArrayIndex(&index); |
| 2715 if (is_element && IsJSArray()) return Heap::undefined_value(); | 2752 if (is_element && IsJSArray()) return Heap::undefined_value(); |
| 2716 | 2753 |
| 2717 if (is_element) { | 2754 if (is_element) { |
| 2718 // Lookup the index. | 2755 switch (GetElementsKind()) { |
| 2719 if (!HasFastElements()) { | 2756 case FAST_ELEMENTS: |
| 2720 NumberDictionary* dictionary = element_dictionary(); | 2757 break; |
| 2721 int entry = dictionary->FindEntry(index); | 2758 case PIXEL_ELEMENTS: |
| 2722 if (entry != NumberDictionary::kNotFound) { | 2759 // Ignore getters and setters on pixel elements. |
| 2723 Object* result = dictionary->ValueAt(entry); | 2760 return Heap::undefined_value(); |
| 2724 PropertyDetails details = dictionary->DetailsAt(entry); | 2761 case DICTIONARY_ELEMENTS: { |
| 2725 if (details.IsReadOnly()) return Heap::undefined_value(); | 2762 // Lookup the index. |
| 2726 if (details.type() == CALLBACKS) { | 2763 NumberDictionary* dictionary = element_dictionary(); |
| 2727 // Only accessors allowed as elements. | 2764 int entry = dictionary->FindEntry(index); |
| 2728 ASSERT(result->IsFixedArray()); | 2765 if (entry != NumberDictionary::kNotFound) { |
| 2729 return result; | 2766 Object* result = dictionary->ValueAt(entry); |
| 2767 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2768 if (details.IsReadOnly()) return Heap::undefined_value(); |
| 2769 if (details.type() == CALLBACKS) { |
| 2770 // Only accessors allowed as elements. |
| 2771 ASSERT(result->IsFixedArray()); |
| 2772 return result; |
| 2773 } |
| 2730 } | 2774 } |
| 2775 break; |
| 2731 } | 2776 } |
| 2777 default: |
| 2778 UNREACHABLE(); |
| 2779 break; |
| 2732 } | 2780 } |
| 2733 } else { | 2781 } else { |
| 2734 // Lookup the name. | 2782 // Lookup the name. |
| 2735 LookupResult result; | 2783 LookupResult result; |
| 2736 LocalLookup(name, &result); | 2784 LocalLookup(name, &result); |
| 2737 if (result.IsValid()) { | 2785 if (result.IsValid()) { |
| 2738 if (result.IsReadOnly()) return Heap::undefined_value(); | 2786 if (result.IsReadOnly()) return Heap::undefined_value(); |
| 2739 if (result.type() == CALLBACKS) { | 2787 if (result.type() == CALLBACKS) { |
| 2740 Object* obj = result.GetCallbackObject(); | 2788 Object* obj = result.GetCallbackObject(); |
| 2741 if (obj->IsFixedArray()) return obj; | 2789 if (obj->IsFixedArray()) return obj; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2820 return Heap::undefined_value(); | 2868 return Heap::undefined_value(); |
| 2821 } | 2869 } |
| 2822 | 2870 |
| 2823 // Make the lookup and include prototypes. | 2871 // Make the lookup and include prototypes. |
| 2824 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; | 2872 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; |
| 2825 uint32_t index; | 2873 uint32_t index; |
| 2826 if (name->AsArrayIndex(&index)) { | 2874 if (name->AsArrayIndex(&index)) { |
| 2827 for (Object* obj = this; | 2875 for (Object* obj = this; |
| 2828 obj != Heap::null_value(); | 2876 obj != Heap::null_value(); |
| 2829 obj = JSObject::cast(obj)->GetPrototype()) { | 2877 obj = JSObject::cast(obj)->GetPrototype()) { |
| 2830 JSObject* jsObject = JSObject::cast(obj); | 2878 JSObject* js_object = JSObject::cast(obj); |
| 2831 if (!jsObject->HasFastElements()) { | 2879 if (js_object->HasDictionaryElements()) { |
| 2832 NumberDictionary* dictionary = jsObject->element_dictionary(); | 2880 NumberDictionary* dictionary = js_object->element_dictionary(); |
| 2833 int entry = dictionary->FindEntry(index); | 2881 int entry = dictionary->FindEntry(index); |
| 2834 if (entry != NumberDictionary::kNotFound) { | 2882 if (entry != NumberDictionary::kNotFound) { |
| 2835 Object* element = dictionary->ValueAt(entry); | 2883 Object* element = dictionary->ValueAt(entry); |
| 2836 PropertyDetails details = dictionary->DetailsAt(entry); | 2884 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2837 if (details.type() == CALLBACKS) { | 2885 if (details.type() == CALLBACKS) { |
| 2838 // Only accessors allowed as elements. | 2886 // Only accessors allowed as elements. |
| 2839 return FixedArray::cast(element)->get(accessor_index); | 2887 return FixedArray::cast(element)->get(accessor_index); |
| 2840 } | 2888 } |
| 2841 } | 2889 } |
| 2842 } | 2890 } |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 if (element->IsString() && | 3070 if (element->IsString() && |
| 3023 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 3071 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
| 3024 return true; | 3072 return true; |
| 3025 } | 3073 } |
| 3026 } | 3074 } |
| 3027 return false; | 3075 return false; |
| 3028 } | 3076 } |
| 3029 | 3077 |
| 3030 | 3078 |
| 3031 Object* FixedArray::AddKeysFromJSArray(JSArray* array) { | 3079 Object* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 3032 if (array->HasFastElements()) { | 3080 ASSERT(!array->HasPixelElements()); |
| 3033 return UnionOfKeys(array->elements()); | 3081 switch (array->GetElementsKind()) { |
| 3082 case JSObject::FAST_ELEMENTS: |
| 3083 return UnionOfKeys(FixedArray::cast(array->elements())); |
| 3084 case JSObject::DICTIONARY_ELEMENTS: { |
| 3085 NumberDictionary* dict = array->element_dictionary(); |
| 3086 int size = dict->NumberOfElements(); |
| 3087 |
| 3088 // Allocate a temporary fixed array. |
| 3089 Object* object = Heap::AllocateFixedArray(size); |
| 3090 if (object->IsFailure()) return object; |
| 3091 FixedArray* key_array = FixedArray::cast(object); |
| 3092 |
| 3093 int capacity = dict->Capacity(); |
| 3094 int pos = 0; |
| 3095 // Copy the elements from the JSArray to the temporary fixed array. |
| 3096 for (int i = 0; i < capacity; i++) { |
| 3097 if (dict->IsKey(dict->KeyAt(i))) { |
| 3098 key_array->set(pos++, dict->ValueAt(i)); |
| 3099 } |
| 3100 } |
| 3101 // Compute the union of this and the temporary fixed array. |
| 3102 return UnionOfKeys(key_array); |
| 3103 } |
| 3104 default: |
| 3105 UNREACHABLE(); |
| 3034 } | 3106 } |
| 3035 ASSERT(!array->HasFastElements()); | 3107 UNREACHABLE(); |
| 3036 NumberDictionary* dict = array->element_dictionary(); | 3108 return Heap::null_value(); // Failure case needs to "return" a value. |
| 3037 int size = dict->NumberOfElements(); | |
| 3038 | |
| 3039 // Allocate a temporary fixed array. | |
| 3040 Object* object = Heap::AllocateFixedArray(size); | |
| 3041 if (object->IsFailure()) return object; | |
| 3042 FixedArray* key_array = FixedArray::cast(object); | |
| 3043 | |
| 3044 int capacity = dict->Capacity(); | |
| 3045 int pos = 0; | |
| 3046 // Copy the elements from the JSArray to the temporary fixed array. | |
| 3047 for (int i = 0; i < capacity; i++) { | |
| 3048 if (dict->IsKey(dict->KeyAt(i))) { | |
| 3049 key_array->set(pos++, dict->ValueAt(i)); | |
| 3050 } | |
| 3051 } | |
| 3052 // Compute the union of this and the temporary fixed array. | |
| 3053 return UnionOfKeys(key_array); | |
| 3054 } | 3109 } |
| 3055 | 3110 |
| 3056 | 3111 |
| 3057 Object* FixedArray::UnionOfKeys(FixedArray* other) { | 3112 Object* FixedArray::UnionOfKeys(FixedArray* other) { |
| 3058 int len0 = length(); | 3113 int len0 = length(); |
| 3059 int len1 = other->length(); | 3114 int len1 = other->length(); |
| 3060 // Optimize if either is empty. | 3115 // Optimize if either is empty. |
| 3061 if (len0 == 0) return other; | 3116 if (len0 == 0) return other; |
| 3062 if (len1 == 0) return this; | 3117 if (len1 == 0) return this; |
| 3063 | 3118 |
| (...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5082 | 5137 |
| 5083 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 5138 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
| 5084 for (RelocIterator it(this); !it.done(); it.next()) | 5139 for (RelocIterator it(this); !it.done(); it.next()) |
| 5085 it.rinfo()->Print(); | 5140 it.rinfo()->Print(); |
| 5086 PrintF("\n"); | 5141 PrintF("\n"); |
| 5087 } | 5142 } |
| 5088 #endif // ENABLE_DISASSEMBLER | 5143 #endif // ENABLE_DISASSEMBLER |
| 5089 | 5144 |
| 5090 | 5145 |
| 5091 void JSObject::SetFastElements(FixedArray* elems) { | 5146 void JSObject::SetFastElements(FixedArray* elems) { |
| 5147 // We should never end in here with a pixel array. |
| 5148 ASSERT(!HasPixelElements()); |
| 5092 #ifdef DEBUG | 5149 #ifdef DEBUG |
| 5093 // Check the provided array is filled with the_hole. | 5150 // Check the provided array is filled with the_hole. |
| 5094 uint32_t len = static_cast<uint32_t>(elems->length()); | 5151 uint32_t len = static_cast<uint32_t>(elems->length()); |
| 5095 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); | 5152 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); |
| 5096 #endif | 5153 #endif |
| 5097 WriteBarrierMode mode = elems->GetWriteBarrierMode(); | 5154 WriteBarrierMode mode = elems->GetWriteBarrierMode(); |
| 5098 if (HasFastElements()) { | 5155 switch (GetElementsKind()) { |
| 5099 FixedArray* old_elements = FixedArray::cast(elements()); | 5156 case FAST_ELEMENTS: { |
| 5100 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 5157 FixedArray* old_elements = FixedArray::cast(elements()); |
| 5101 // Fill out the new array with this content and array holes. | 5158 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 5102 for (uint32_t i = 0; i < old_length; i++) { | 5159 // Fill out the new array with this content and array holes. |
| 5103 elems->set(i, old_elements->get(i), mode); | 5160 for (uint32_t i = 0; i < old_length; i++) { |
| 5161 elems->set(i, old_elements->get(i), mode); |
| 5162 } |
| 5163 break; |
| 5104 } | 5164 } |
| 5105 } else { | 5165 case DICTIONARY_ELEMENTS: { |
| 5106 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 5166 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5107 for (int i = 0; i < dictionary->Capacity(); i++) { | 5167 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 5108 Object* key = dictionary->KeyAt(i); | 5168 Object* key = dictionary->KeyAt(i); |
| 5109 if (key->IsNumber()) { | 5169 if (key->IsNumber()) { |
| 5110 uint32_t entry = static_cast<uint32_t>(key->Number()); | 5170 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 5111 elems->set(entry, dictionary->ValueAt(i), mode); | 5171 elems->set(entry, dictionary->ValueAt(i), mode); |
| 5172 } |
| 5112 } | 5173 } |
| 5174 break; |
| 5113 } | 5175 } |
| 5176 default: |
| 5177 UNREACHABLE(); |
| 5178 break; |
| 5114 } | 5179 } |
| 5115 set_elements(elems); | 5180 set_elements(elems); |
| 5116 } | 5181 } |
| 5117 | 5182 |
| 5118 | 5183 |
| 5119 Object* JSObject::SetSlowElements(Object* len) { | 5184 Object* JSObject::SetSlowElements(Object* len) { |
| 5185 // We should never end in here with a pixel array. |
| 5186 ASSERT(!HasPixelElements()); |
| 5187 |
| 5120 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 5188 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 5121 | 5189 |
| 5122 if (!HasFastElements()) { | 5190 switch (GetElementsKind()) { |
| 5123 if (IsJSArray()) { | 5191 case FAST_ELEMENTS: { |
| 5124 uint32_t old_length = | 5192 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 5125 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | 5193 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= |
| 5126 element_dictionary()->RemoveNumberEntries(new_length, old_length), | 5194 new_length); |
| 5127 JSArray::cast(this)->set_length(len); | 5195 Object* obj = NormalizeElements(); |
| 5196 if (obj->IsFailure()) return obj; |
| 5197 |
| 5198 // Update length for JSArrays. |
| 5199 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 5200 break; |
| 5128 } | 5201 } |
| 5129 return this; | 5202 case DICTIONARY_ELEMENTS: { |
| 5203 if (IsJSArray()) { |
| 5204 uint32_t old_length = |
| 5205 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
| 5206 element_dictionary()->RemoveNumberEntries(new_length, old_length), |
| 5207 JSArray::cast(this)->set_length(len); |
| 5208 } |
| 5209 break; |
| 5210 } |
| 5211 default: |
| 5212 UNREACHABLE(); |
| 5213 break; |
| 5130 } | 5214 } |
| 5131 | |
| 5132 // Make sure we never try to shrink dense arrays into sparse arrays. | |
| 5133 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= | |
| 5134 new_length); | |
| 5135 Object* obj = NormalizeElements(); | |
| 5136 if (obj->IsFailure()) return obj; | |
| 5137 | |
| 5138 // Update length for JSArrays. | |
| 5139 if (IsJSArray()) JSArray::cast(this)->set_length(len); | |
| 5140 return this; | 5215 return this; |
| 5141 } | 5216 } |
| 5142 | 5217 |
| 5143 | 5218 |
| 5144 Object* JSArray::Initialize(int capacity) { | 5219 Object* JSArray::Initialize(int capacity) { |
| 5145 ASSERT(capacity >= 0); | 5220 ASSERT(capacity >= 0); |
| 5146 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); | 5221 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); |
| 5147 FixedArray* new_elements; | 5222 FixedArray* new_elements; |
| 5148 if (capacity == 0) { | 5223 if (capacity == 0) { |
| 5149 new_elements = Heap::empty_fixed_array(); | 5224 new_elements = Heap::empty_fixed_array(); |
| 5150 } else { | 5225 } else { |
| 5151 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); | 5226 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 5152 if (obj->IsFailure()) return obj; | 5227 if (obj->IsFailure()) return obj; |
| 5153 new_elements = FixedArray::cast(obj); | 5228 new_elements = FixedArray::cast(obj); |
| 5154 } | 5229 } |
| 5155 set_elements(new_elements); | 5230 set_elements(new_elements); |
| 5156 return this; | 5231 return this; |
| 5157 } | 5232 } |
| 5158 | 5233 |
| 5159 | 5234 |
| 5160 void JSArray::Expand(int required_size) { | 5235 void JSArray::Expand(int required_size) { |
| 5161 Handle<JSArray> self(this); | 5236 Handle<JSArray> self(this); |
| 5162 Handle<FixedArray> old_backing(elements()); | 5237 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 5163 int old_size = old_backing->length(); | 5238 int old_size = old_backing->length(); |
| 5164 // Doubling in size would be overkill, but leave some slack to avoid | 5239 // Doubling in size would be overkill, but leave some slack to avoid |
| 5165 // constantly growing. | 5240 // constantly growing. |
| 5166 int new_size = required_size + (required_size >> 3); | 5241 int new_size = required_size + (required_size >> 3); |
| 5167 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); | 5242 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); |
| 5168 // Can't use this any more now because we may have had a GC! | 5243 // Can't use this any more now because we may have had a GC! |
| 5169 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 5244 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 5170 self->SetContent(*new_backing); | 5245 self->SetContent(*new_backing); |
| 5171 } | 5246 } |
| 5172 | 5247 |
| 5173 | 5248 |
| 5174 // Computes the new capacity when expanding the elements of a JSObject. | 5249 // Computes the new capacity when expanding the elements of a JSObject. |
| 5175 static int NewElementsCapacity(int old_capacity) { | 5250 static int NewElementsCapacity(int old_capacity) { |
| 5176 // (old_capacity + 50%) + 16 | 5251 // (old_capacity + 50%) + 16 |
| 5177 return old_capacity + (old_capacity >> 1) + 16; | 5252 return old_capacity + (old_capacity >> 1) + 16; |
| 5178 } | 5253 } |
| 5179 | 5254 |
| 5180 | 5255 |
| 5181 static Object* ArrayLengthRangeError() { | 5256 static Object* ArrayLengthRangeError() { |
| 5182 HandleScope scope; | 5257 HandleScope scope; |
| 5183 return Top::Throw(*Factory::NewRangeError("invalid_array_length", | 5258 return Top::Throw(*Factory::NewRangeError("invalid_array_length", |
| 5184 HandleVector<Object>(NULL, 0))); | 5259 HandleVector<Object>(NULL, 0))); |
| 5185 } | 5260 } |
| 5186 | 5261 |
| 5187 | 5262 |
| 5188 Object* JSObject::SetElementsLength(Object* len) { | 5263 Object* JSObject::SetElementsLength(Object* len) { |
| 5264 // We should never end in here with a pixel array. |
| 5265 ASSERT(!HasPixelElements()); |
| 5266 |
| 5189 Object* smi_length = len->ToSmi(); | 5267 Object* smi_length = len->ToSmi(); |
| 5190 if (smi_length->IsSmi()) { | 5268 if (smi_length->IsSmi()) { |
| 5191 int value = Smi::cast(smi_length)->value(); | 5269 int value = Smi::cast(smi_length)->value(); |
| 5192 if (value < 0) return ArrayLengthRangeError(); | 5270 if (value < 0) return ArrayLengthRangeError(); |
| 5193 if (HasFastElements()) { | 5271 switch (GetElementsKind()) { |
| 5194 int old_capacity = FixedArray::cast(elements())->length(); | 5272 case FAST_ELEMENTS: { |
| 5195 if (value <= old_capacity) { | 5273 int old_capacity = FixedArray::cast(elements())->length(); |
| 5274 if (value <= old_capacity) { |
| 5275 if (IsJSArray()) { |
| 5276 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 5277 // NOTE: We may be able to optimize this by removing the |
| 5278 // last part of the elements backing storage array and |
| 5279 // setting the capacity to the new size. |
| 5280 for (int i = value; i < old_length; i++) { |
| 5281 FixedArray::cast(elements())->set_the_hole(i); |
| 5282 } |
| 5283 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); |
| 5284 } |
| 5285 return this; |
| 5286 } |
| 5287 int min = NewElementsCapacity(old_capacity); |
| 5288 int new_capacity = value > min ? value : min; |
| 5289 if (new_capacity <= kMaxFastElementsLength || |
| 5290 !ShouldConvertToSlowElements(new_capacity)) { |
| 5291 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); |
| 5292 if (obj->IsFailure()) return obj; |
| 5293 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length, |
| 5294 SKIP_WRITE_BARRIER); |
| 5295 SetFastElements(FixedArray::cast(obj)); |
| 5296 return this; |
| 5297 } |
| 5298 break; |
| 5299 } |
| 5300 case DICTIONARY_ELEMENTS: { |
| 5196 if (IsJSArray()) { | 5301 if (IsJSArray()) { |
| 5197 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 5302 if (value == 0) { |
| 5198 // NOTE: We may be able to optimize this by removing the | 5303 // If the length of a slow array is reset to zero, we clear |
| 5199 // last part of the elements backing storage array and | 5304 // the array and flush backing storage. This has the added |
| 5200 // setting the capacity to the new size. | 5305 // benefit that the array returns to fast mode. |
| 5201 for (int i = value; i < old_length; i++) { | 5306 initialize_elements(); |
| 5202 FixedArray::cast(elements())->set_the_hole(i); | 5307 } else { |
| 5308 // Remove deleted elements. |
| 5309 uint32_t old_length = |
| 5310 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
| 5311 element_dictionary()->RemoveNumberEntries(value, old_length); |
| 5203 } | 5312 } |
| 5204 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | 5313 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); |
| 5205 } | 5314 } |
| 5206 return this; | 5315 return this; |
| 5207 } | 5316 } |
| 5208 int min = NewElementsCapacity(old_capacity); | 5317 default: |
| 5209 int new_capacity = value > min ? value : min; | 5318 UNREACHABLE(); |
| 5210 if (new_capacity <= kMaxFastElementsLength || | 5319 break; |
| 5211 !ShouldConvertToSlowElements(new_capacity)) { | |
| 5212 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); | |
| 5213 if (obj->IsFailure()) return obj; | |
| 5214 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length, | |
| 5215 SKIP_WRITE_BARRIER); | |
| 5216 SetFastElements(FixedArray::cast(obj)); | |
| 5217 return this; | |
| 5218 } | |
| 5219 } else { | |
| 5220 if (IsJSArray()) { | |
| 5221 if (value == 0) { | |
| 5222 // If the length of a slow array is reset to zero, we clear | |
| 5223 // the array and flush backing storage. This has the added | |
| 5224 // benefit that the array returns to fast mode. | |
| 5225 initialize_elements(); | |
| 5226 } else { | |
| 5227 // Remove deleted elements. | |
| 5228 uint32_t old_length = | |
| 5229 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | |
| 5230 element_dictionary()->RemoveNumberEntries(value, old_length); | |
| 5231 } | |
| 5232 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | |
| 5233 } | |
| 5234 return this; | |
| 5235 } | 5320 } |
| 5236 } | 5321 } |
| 5237 | 5322 |
| 5238 // General slow case. | 5323 // General slow case. |
| 5239 if (len->IsNumber()) { | 5324 if (len->IsNumber()) { |
| 5240 uint32_t length; | 5325 uint32_t length; |
| 5241 if (Array::IndexFromObject(len, &length)) { | 5326 if (Array::IndexFromObject(len, &length)) { |
| 5242 return SetSlowElements(len); | 5327 return SetSlowElements(len); |
| 5243 } else { | 5328 } else { |
| 5244 return ArrayLengthRangeError(); | 5329 return ArrayLengthRangeError(); |
| 5245 } | 5330 } |
| 5246 } | 5331 } |
| 5247 | 5332 |
| 5248 // len is not a number so make the array size one and | 5333 // len is not a number so make the array size one and |
| 5249 // set only element to len. | 5334 // set only element to len. |
| 5250 Object* obj = Heap::AllocateFixedArray(1); | 5335 Object* obj = Heap::AllocateFixedArray(1); |
| 5251 if (obj->IsFailure()) return obj; | 5336 if (obj->IsFailure()) return obj; |
| 5252 FixedArray::cast(obj)->set(0, len); | 5337 FixedArray::cast(obj)->set(0, len); |
| 5253 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), | 5338 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), |
| 5254 SKIP_WRITE_BARRIER); | 5339 SKIP_WRITE_BARRIER); |
| 5255 set_elements(FixedArray::cast(obj)); | 5340 set_elements(FixedArray::cast(obj)); |
| 5256 return this; | 5341 return this; |
| 5257 } | 5342 } |
| 5258 | 5343 |
| 5259 | 5344 |
| 5260 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 5345 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| 5261 if (HasFastElements()) { | 5346 switch (GetElementsKind()) { |
| 5262 uint32_t length = IsJSArray() ? | 5347 case FAST_ELEMENTS: { |
| 5263 static_cast<uint32_t>( | 5348 uint32_t length = IsJSArray() ? |
| 5264 Smi::cast(JSArray::cast(this)->length())->value()) : | 5349 static_cast<uint32_t> |
| 5265 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5350 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5266 if ((index < length) && | 5351 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5267 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 5352 if ((index < length) && |
| 5268 return true; | 5353 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 5354 return true; |
| 5355 } |
| 5356 break; |
| 5269 } | 5357 } |
| 5270 } else { | 5358 case PIXEL_ELEMENTS: { |
| 5271 if (element_dictionary()->FindEntry(index) | 5359 // TODO(iposva): Add testcase. |
| 5272 != NumberDictionary::kNotFound) { | 5360 PixelArray* pixels = PixelArray::cast(elements()); |
| 5273 return true; | 5361 if (index < static_cast<uint32_t>(pixels->length())) { |
| 5362 return true; |
| 5363 } |
| 5364 break; |
| 5274 } | 5365 } |
| 5366 case DICTIONARY_ELEMENTS: { |
| 5367 if (element_dictionary()->FindEntry(index) |
| 5368 != NumberDictionary::kNotFound) { |
| 5369 return true; |
| 5370 } |
| 5371 break; |
| 5372 } |
| 5373 default: |
| 5374 UNREACHABLE(); |
| 5375 break; |
| 5275 } | 5376 } |
| 5276 | 5377 |
| 5277 // Handle [] on String objects. | 5378 // Handle [] on String objects. |
| 5278 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5379 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5279 | 5380 |
| 5280 Object* pt = GetPrototype(); | 5381 Object* pt = GetPrototype(); |
| 5281 if (pt == Heap::null_value()) return false; | 5382 if (pt == Heap::null_value()) return false; |
| 5282 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 5383 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 5283 } | 5384 } |
| 5284 | 5385 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5331 } | 5432 } |
| 5332 | 5433 |
| 5333 // Check for lookup interceptor | 5434 // Check for lookup interceptor |
| 5334 if (HasIndexedInterceptor()) { | 5435 if (HasIndexedInterceptor()) { |
| 5335 return HasElementWithInterceptor(this, index); | 5436 return HasElementWithInterceptor(this, index); |
| 5336 } | 5437 } |
| 5337 | 5438 |
| 5338 // Handle [] on String objects. | 5439 // Handle [] on String objects. |
| 5339 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5440 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5340 | 5441 |
| 5341 if (HasFastElements()) { | 5442 switch (GetElementsKind()) { |
| 5342 uint32_t length = IsJSArray() ? | 5443 case FAST_ELEMENTS: { |
| 5343 static_cast<uint32_t>( | 5444 uint32_t length = IsJSArray() ? |
| 5344 Smi::cast(JSArray::cast(this)->length())->value()) : | 5445 static_cast<uint32_t> |
| 5345 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5446 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5346 return (index < length) && | 5447 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5347 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 5448 return (index < length) && |
| 5348 } else { | 5449 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 5349 return element_dictionary()->FindEntry(index) | 5450 } |
| 5350 != NumberDictionary::kNotFound; | 5451 case PIXEL_ELEMENTS: { |
| 5452 PixelArray* pixels = PixelArray::cast(elements()); |
| 5453 return (index < static_cast<uint32_t>(pixels->length())); |
| 5454 } |
| 5455 case DICTIONARY_ELEMENTS: { |
| 5456 return element_dictionary()->FindEntry(index) |
| 5457 != NumberDictionary::kNotFound; |
| 5458 } |
| 5459 default: |
| 5460 UNREACHABLE(); |
| 5461 break; |
| 5351 } | 5462 } |
| 5463 UNREACHABLE(); |
| 5464 return Heap::null_value(); |
| 5352 } | 5465 } |
| 5353 | 5466 |
| 5354 | 5467 |
| 5355 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 5468 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| 5356 // Check access rights if needed. | 5469 // Check access rights if needed. |
| 5357 if (IsAccessCheckNeeded() && | 5470 if (IsAccessCheckNeeded() && |
| 5358 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 5471 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 5359 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 5472 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 5360 return false; | 5473 return false; |
| 5361 } | 5474 } |
| 5362 | 5475 |
| 5363 // Check for lookup interceptor | 5476 // Check for lookup interceptor |
| 5364 if (HasIndexedInterceptor()) { | 5477 if (HasIndexedInterceptor()) { |
| 5365 return HasElementWithInterceptor(receiver, index); | 5478 return HasElementWithInterceptor(receiver, index); |
| 5366 } | 5479 } |
| 5367 | 5480 |
| 5368 if (HasFastElements()) { | 5481 switch (GetElementsKind()) { |
| 5369 uint32_t length = IsJSArray() ? | 5482 case FAST_ELEMENTS: { |
| 5370 static_cast<uint32_t>( | 5483 uint32_t length = IsJSArray() ? |
| 5371 Smi::cast(JSArray::cast(this)->length())->value()) : | 5484 static_cast<uint32_t> |
| 5372 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5485 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5373 if ((index < length) && | 5486 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5374 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 5487 if ((index < length) && |
| 5375 } else { | 5488 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 5376 if (element_dictionary()->FindEntry(index) | 5489 break; |
| 5377 != NumberDictionary::kNotFound) { | |
| 5378 return true; | |
| 5379 } | 5490 } |
| 5491 case PIXEL_ELEMENTS: { |
| 5492 PixelArray* pixels = PixelArray::cast(elements()); |
| 5493 if (index < static_cast<uint32_t>(pixels->length())) { |
| 5494 return true; |
| 5495 } |
| 5496 break; |
| 5497 } |
| 5498 case DICTIONARY_ELEMENTS: { |
| 5499 if (element_dictionary()->FindEntry(index) |
| 5500 != NumberDictionary::kNotFound) { |
| 5501 return true; |
| 5502 } |
| 5503 break; |
| 5504 } |
| 5505 default: |
| 5506 UNREACHABLE(); |
| 5507 break; |
| 5380 } | 5508 } |
| 5381 | 5509 |
| 5382 // Handle [] on String objects. | 5510 // Handle [] on String objects. |
| 5383 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5511 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5384 | 5512 |
| 5385 Object* pt = GetPrototype(); | 5513 Object* pt = GetPrototype(); |
| 5386 if (pt == Heap::null_value()) return false; | 5514 if (pt == Heap::null_value()) return false; |
| 5387 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 5515 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 5388 } | 5516 } |
| 5389 | 5517 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5465 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), | 5593 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), |
| 5466 SKIP_WRITE_BARRIER); | 5594 SKIP_WRITE_BARRIER); |
| 5467 FixedArray::cast(elements())->set(index, value); | 5595 FixedArray::cast(elements())->set(index, value); |
| 5468 return value; | 5596 return value; |
| 5469 } | 5597 } |
| 5470 } | 5598 } |
| 5471 | 5599 |
| 5472 // Otherwise default to slow case. | 5600 // Otherwise default to slow case. |
| 5473 Object* obj = NormalizeElements(); | 5601 Object* obj = NormalizeElements(); |
| 5474 if (obj->IsFailure()) return obj; | 5602 if (obj->IsFailure()) return obj; |
| 5475 ASSERT(!HasFastElements()); | 5603 ASSERT(HasDictionaryElements()); |
| 5476 return SetElement(index, value); | 5604 return SetElement(index, value); |
| 5477 } | 5605 } |
| 5478 | 5606 |
| 5479 Object* JSObject::SetElement(uint32_t index, Object* value) { | 5607 Object* JSObject::SetElement(uint32_t index, Object* value) { |
| 5480 // Check access rights if needed. | 5608 // Check access rights if needed. |
| 5481 if (IsAccessCheckNeeded() && | 5609 if (IsAccessCheckNeeded() && |
| 5482 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 5610 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 5483 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 5611 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 5484 return value; | 5612 return value; |
| 5485 } | 5613 } |
| 5486 | 5614 |
| 5487 if (IsJSGlobalProxy()) { | 5615 if (IsJSGlobalProxy()) { |
| 5488 Object* proto = GetPrototype(); | 5616 Object* proto = GetPrototype(); |
| 5489 if (proto->IsNull()) return value; | 5617 if (proto->IsNull()) return value; |
| 5490 ASSERT(proto->IsJSGlobalObject()); | 5618 ASSERT(proto->IsJSGlobalObject()); |
| 5491 return JSObject::cast(proto)->SetElement(index, value); | 5619 return JSObject::cast(proto)->SetElement(index, value); |
| 5492 } | 5620 } |
| 5493 | 5621 |
| 5494 // Check for lookup interceptor | 5622 // Check for lookup interceptor |
| 5495 if (HasIndexedInterceptor()) { | 5623 if (HasIndexedInterceptor()) { |
| 5496 return SetElementWithInterceptor(index, value); | 5624 return SetElementWithInterceptor(index, value); |
| 5497 } | 5625 } |
| 5498 | 5626 |
| 5499 return SetElementWithoutInterceptor(index, value); | 5627 return SetElementWithoutInterceptor(index, value); |
| 5500 } | 5628 } |
| 5501 | 5629 |
| 5502 | 5630 |
| 5503 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { | 5631 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { |
| 5504 // Fast case. | 5632 switch (GetElementsKind()) { |
| 5505 if (HasFastElements()) return SetFastElement(index, value); | 5633 case FAST_ELEMENTS: |
| 5634 // Fast case. |
| 5635 return SetFastElement(index, value); |
| 5636 case PIXEL_ELEMENTS: { |
| 5637 PixelArray* pixels = PixelArray::cast(elements()); |
| 5638 return pixels->SetValue(index, value); |
| 5639 } |
| 5640 case DICTIONARY_ELEMENTS: { |
| 5641 // Insert element in the dictionary. |
| 5642 FixedArray* elms = FixedArray::cast(elements()); |
| 5643 NumberDictionary* dictionary = NumberDictionary::cast(elms); |
| 5506 | 5644 |
| 5507 // Dictionary case. | 5645 int entry = dictionary->FindEntry(index); |
| 5508 ASSERT(!HasFastElements()); | 5646 if (entry != NumberDictionary::kNotFound) { |
| 5647 Object* element = dictionary->ValueAt(entry); |
| 5648 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5649 if (details.type() == CALLBACKS) { |
| 5650 // Only accessors allowed as elements. |
| 5651 FixedArray* structure = FixedArray::cast(element); |
| 5652 if (structure->get(kSetterIndex)->IsJSFunction()) { |
| 5653 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex)); |
| 5654 return SetPropertyWithDefinedSetter(setter, value); |
| 5655 } else { |
| 5656 Handle<Object> self(this); |
| 5657 Handle<Object> key(Factory::NewNumberFromUint(index)); |
| 5658 Handle<Object> args[2] = { key, self }; |
| 5659 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", |
| 5660 HandleVector(args, 2))); |
| 5661 } |
| 5662 } else { |
| 5663 dictionary->UpdateMaxNumberKey(index); |
| 5664 dictionary->ValueAtPut(entry, value); |
| 5665 } |
| 5666 } else { |
| 5667 // Index not already used. Look for an accessor in the prototype chain. |
| 5668 if (!IsJSArray()) { |
| 5669 Object* setter = LookupCallbackSetterInPrototypes(index); |
| 5670 if (setter->IsJSFunction()) { |
| 5671 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), |
| 5672 value); |
| 5673 } |
| 5674 } |
| 5675 Object* result = dictionary->AtNumberPut(index, value); |
| 5676 if (result->IsFailure()) return result; |
| 5677 if (elms != FixedArray::cast(result)) { |
| 5678 set_elements(FixedArray::cast(result)); |
| 5679 } |
| 5680 } |
| 5509 | 5681 |
| 5510 // Insert element in the dictionary. | 5682 // Update the array length if this JSObject is an array. |
| 5511 FixedArray* elms = FixedArray::cast(elements()); | 5683 if (IsJSArray()) { |
| 5512 NumberDictionary* dictionary = NumberDictionary::cast(elms); | 5684 JSArray* array = JSArray::cast(this); |
| 5685 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, |
| 5686 value); |
| 5687 if (return_value->IsFailure()) return return_value; |
| 5688 } |
| 5513 | 5689 |
| 5514 int entry = dictionary->FindEntry(index); | 5690 // Attempt to put this object back in fast case. |
| 5515 if (entry != NumberDictionary::kNotFound) { | 5691 if (ShouldConvertToFastElements()) { |
| 5516 Object* element = dictionary->ValueAt(entry); | 5692 uint32_t new_length = 0; |
| 5517 PropertyDetails details = dictionary->DetailsAt(entry); | 5693 if (IsJSArray()) { |
| 5518 if (details.type() == CALLBACKS) { | 5694 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), |
| 5519 // Only accessors allowed as elements. | 5695 &new_length)); |
| 5520 FixedArray* structure = FixedArray::cast(element); | 5696 JSArray::cast(this)->set_length(Smi::FromInt(new_length)); |
| 5521 if (structure->get(kSetterIndex)->IsJSFunction()) { | 5697 } else { |
| 5522 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex)); | 5698 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; |
| 5523 return SetPropertyWithDefinedSetter(setter, value); | 5699 } |
| 5524 } else { | 5700 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); |
| 5525 Handle<Object> self(this); | 5701 if (obj->IsFailure()) return obj; |
| 5526 Handle<Object> key(Factory::NewNumberFromUint(index)); | 5702 SetFastElements(FixedArray::cast(obj)); |
| 5527 Handle<Object> args[2] = { key, self }; | 5703 #ifdef DEBUG |
| 5528 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", | 5704 if (FLAG_trace_normalization) { |
| 5529 HandleVector(args, 2))); | 5705 PrintF("Object elements are fast case again:\n"); |
| 5706 Print(); |
| 5707 } |
| 5708 #endif |
| 5530 } | 5709 } |
| 5531 } else { | 5710 |
| 5532 dictionary->UpdateMaxNumberKey(index); | 5711 return value; |
| 5533 dictionary->ValueAtPut(entry, value); | |
| 5534 } | 5712 } |
| 5535 } else { | 5713 default: |
| 5536 // Index not already used. Look for an accessor in the prototype chain. | 5714 UNREACHABLE(); |
| 5537 if (!IsJSArray()) { | 5715 break; |
| 5538 Object* setter = LookupCallbackSetterInPrototypes(index); | |
| 5539 if (setter->IsJSFunction()) { | |
| 5540 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); | |
| 5541 } | |
| 5542 } | |
| 5543 Object* result = dictionary->AtNumberPut(index, value); | |
| 5544 if (result->IsFailure()) return result; | |
| 5545 if (elms != FixedArray::cast(result)) { | |
| 5546 set_elements(FixedArray::cast(result)); | |
| 5547 } | |
| 5548 } | 5716 } |
| 5549 | 5717 // All possible cases have been handled above. Add a return to avoid the |
| 5550 // Update the array length if this JSObject is an array. | 5718 // complaints from the compiler. |
| 5551 if (IsJSArray()) { | 5719 UNREACHABLE(); |
| 5552 JSArray* array = JSArray::cast(this); | 5720 return Heap::null_value(); |
| 5553 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value); | |
| 5554 if (return_value->IsFailure()) return return_value; | |
| 5555 } | |
| 5556 | |
| 5557 // Attempt to put this object back in fast case. | |
| 5558 if (ShouldConvertToFastElements()) { | |
| 5559 uint32_t new_length = 0; | |
| 5560 if (IsJSArray()) { | |
| 5561 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); | |
| 5562 JSArray::cast(this)->set_length(Smi::FromInt(new_length)); | |
| 5563 } else { | |
| 5564 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; | |
| 5565 } | |
| 5566 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); | |
| 5567 if (obj->IsFailure()) return obj; | |
| 5568 SetFastElements(FixedArray::cast(obj)); | |
| 5569 #ifdef DEBUG | |
| 5570 if (FLAG_trace_normalization) { | |
| 5571 PrintF("Object elements are fast case again:\n"); | |
| 5572 Print(); | |
| 5573 } | |
| 5574 #endif | |
| 5575 } | |
| 5576 | |
| 5577 return value; | |
| 5578 } | 5721 } |
| 5579 | 5722 |
| 5580 | 5723 |
| 5581 Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) { | 5724 Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) { |
| 5582 uint32_t old_len = 0; | 5725 uint32_t old_len = 0; |
| 5583 CHECK(Array::IndexFromObject(length(), &old_len)); | 5726 CHECK(Array::IndexFromObject(length(), &old_len)); |
| 5584 // Check to see if we need to update the length. For now, we make | 5727 // Check to see if we need to update the length. For now, we make |
| 5585 // sure that the length stays within 32-bits (unsigned). | 5728 // sure that the length stays within 32-bits (unsigned). |
| 5586 if (index >= old_len && index != 0xffffffff) { | 5729 if (index >= old_len && index != 0xffffffff) { |
| 5587 Object* len = | 5730 Object* len = |
| 5588 Heap::NumberFromDouble(static_cast<double>(index) + 1); | 5731 Heap::NumberFromDouble(static_cast<double>(index) + 1); |
| 5589 if (len->IsFailure()) return len; | 5732 if (len->IsFailure()) return len; |
| 5590 set_length(len); | 5733 set_length(len); |
| 5591 } | 5734 } |
| 5592 return value; | 5735 return value; |
| 5593 } | 5736 } |
| 5594 | 5737 |
| 5595 | 5738 |
| 5596 Object* JSObject::GetElementPostInterceptor(JSObject* receiver, | 5739 Object* JSObject::GetElementPostInterceptor(JSObject* receiver, |
| 5597 uint32_t index) { | 5740 uint32_t index) { |
| 5598 // Get element works for both JSObject and JSArray since | 5741 // Get element works for both JSObject and JSArray since |
| 5599 // JSArray::length cannot change. | 5742 // JSArray::length cannot change. |
| 5600 if (HasFastElements()) { | 5743 switch (GetElementsKind()) { |
| 5601 FixedArray* elms = FixedArray::cast(elements()); | 5744 case FAST_ELEMENTS: { |
| 5602 if (index < static_cast<uint32_t>(elms->length())) { | 5745 FixedArray* elms = FixedArray::cast(elements()); |
| 5603 Object* value = elms->get(index); | 5746 if (index < static_cast<uint32_t>(elms->length())) { |
| 5604 if (!value->IsTheHole()) return value; | 5747 Object* value = elms->get(index); |
| 5748 if (!value->IsTheHole()) return value; |
| 5749 } |
| 5750 break; |
| 5605 } | 5751 } |
| 5606 } else { | 5752 case PIXEL_ELEMENTS: { |
| 5607 NumberDictionary* dictionary = element_dictionary(); | 5753 // TODO(iposva): Add testcase and implement. |
| 5608 int entry = dictionary->FindEntry(index); | 5754 UNIMPLEMENTED(); |
| 5609 if (entry != NumberDictionary::kNotFound) { | 5755 break; |
| 5610 Object* element = dictionary->ValueAt(entry); | 5756 } |
| 5611 PropertyDetails details = dictionary->DetailsAt(entry); | 5757 case DICTIONARY_ELEMENTS: { |
| 5612 if (details.type() == CALLBACKS) { | 5758 NumberDictionary* dictionary = element_dictionary(); |
| 5613 // Only accessors allowed as elements. | 5759 int entry = dictionary->FindEntry(index); |
| 5614 FixedArray* structure = FixedArray::cast(element); | 5760 if (entry != NumberDictionary::kNotFound) { |
| 5615 Object* getter = structure->get(kGetterIndex); | 5761 Object* element = dictionary->ValueAt(entry); |
| 5616 if (getter->IsJSFunction()) { | 5762 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5617 return GetPropertyWithDefinedGetter(receiver, | 5763 if (details.type() == CALLBACKS) { |
| 5618 JSFunction::cast(getter)); | 5764 // Only accessors allowed as elements. |
| 5619 } else { | 5765 FixedArray* structure = FixedArray::cast(element); |
| 5620 // Getter is not a function. | 5766 Object* getter = structure->get(kGetterIndex); |
| 5621 return Heap::undefined_value(); | 5767 if (getter->IsJSFunction()) { |
| 5768 return GetPropertyWithDefinedGetter(receiver, |
| 5769 JSFunction::cast(getter)); |
| 5770 } else { |
| 5771 // Getter is not a function. |
| 5772 return Heap::undefined_value(); |
| 5773 } |
| 5622 } | 5774 } |
| 5775 return element; |
| 5623 } | 5776 } |
| 5624 return element; | 5777 break; |
| 5625 } | 5778 } |
| 5779 default: |
| 5780 UNREACHABLE(); |
| 5781 break; |
| 5626 } | 5782 } |
| 5627 | 5783 |
| 5628 // Continue searching via the prototype chain. | 5784 // Continue searching via the prototype chain. |
| 5629 Object* pt = GetPrototype(); | 5785 Object* pt = GetPrototype(); |
| 5630 if (pt == Heap::null_value()) return Heap::undefined_value(); | 5786 if (pt == Heap::null_value()) return Heap::undefined_value(); |
| 5631 return pt->GetElementWithReceiver(receiver, index); | 5787 return pt->GetElementWithReceiver(receiver, index); |
| 5632 } | 5788 } |
| 5633 | 5789 |
| 5634 | 5790 |
| 5635 Object* JSObject::GetElementWithInterceptor(JSObject* receiver, | 5791 Object* JSObject::GetElementWithInterceptor(JSObject* receiver, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5674 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 5830 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 5675 return Heap::undefined_value(); | 5831 return Heap::undefined_value(); |
| 5676 } | 5832 } |
| 5677 | 5833 |
| 5678 if (HasIndexedInterceptor()) { | 5834 if (HasIndexedInterceptor()) { |
| 5679 return GetElementWithInterceptor(receiver, index); | 5835 return GetElementWithInterceptor(receiver, index); |
| 5680 } | 5836 } |
| 5681 | 5837 |
| 5682 // Get element works for both JSObject and JSArray since | 5838 // Get element works for both JSObject and JSArray since |
| 5683 // JSArray::length cannot change. | 5839 // JSArray::length cannot change. |
| 5684 if (HasFastElements()) { | 5840 switch (GetElementsKind()) { |
| 5685 FixedArray* elms = FixedArray::cast(elements()); | 5841 case FAST_ELEMENTS: { |
| 5686 if (index < static_cast<uint32_t>(elms->length())) { | 5842 FixedArray* elms = FixedArray::cast(elements()); |
| 5687 Object* value = elms->get(index); | 5843 if (index < static_cast<uint32_t>(elms->length())) { |
| 5688 if (!value->IsTheHole()) return value; | 5844 Object* value = elms->get(index); |
| 5845 if (!value->IsTheHole()) return value; |
| 5846 } |
| 5847 break; |
| 5689 } | 5848 } |
| 5690 } else { | 5849 case PIXEL_ELEMENTS: { |
| 5691 NumberDictionary* dictionary = element_dictionary(); | 5850 PixelArray* pixels = PixelArray::cast(elements()); |
| 5692 int entry = dictionary->FindEntry(index); | 5851 if (index < static_cast<uint32_t>(pixels->length())) { |
| 5693 if (entry != NumberDictionary::kNotFound) { | 5852 uint8_t value = pixels->get(index); |
| 5694 Object* element = dictionary->ValueAt(entry); | 5853 return Smi::FromInt(value); |
| 5695 PropertyDetails details = dictionary->DetailsAt(entry); | 5854 } |
| 5696 if (details.type() == CALLBACKS) { | 5855 break; |
| 5697 // Only accessors allowed as elements. | 5856 } |
| 5698 FixedArray* structure = FixedArray::cast(element); | 5857 case DICTIONARY_ELEMENTS: { |
| 5699 Object* getter = structure->get(kGetterIndex); | 5858 NumberDictionary* dictionary = element_dictionary(); |
| 5700 if (getter->IsJSFunction()) { | 5859 int entry = dictionary->FindEntry(index); |
| 5701 return GetPropertyWithDefinedGetter(receiver, | 5860 if (entry != NumberDictionary::kNotFound) { |
| 5702 JSFunction::cast(getter)); | 5861 Object* element = dictionary->ValueAt(entry); |
| 5703 } else { | 5862 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5704 // Getter is not a function. | 5863 if (details.type() == CALLBACKS) { |
| 5705 return Heap::undefined_value(); | 5864 // Only accessors allowed as elements. |
| 5865 FixedArray* structure = FixedArray::cast(element); |
| 5866 Object* getter = structure->get(kGetterIndex); |
| 5867 if (getter->IsJSFunction()) { |
| 5868 return GetPropertyWithDefinedGetter(receiver, |
| 5869 JSFunction::cast(getter)); |
| 5870 } else { |
| 5871 // Getter is not a function. |
| 5872 return Heap::undefined_value(); |
| 5873 } |
| 5706 } | 5874 } |
| 5875 return element; |
| 5707 } | 5876 } |
| 5708 return element; | 5877 break; |
| 5709 } | 5878 } |
| 5710 } | 5879 } |
| 5711 | 5880 |
| 5712 Object* pt = GetPrototype(); | 5881 Object* pt = GetPrototype(); |
| 5713 if (pt == Heap::null_value()) return Heap::undefined_value(); | 5882 if (pt == Heap::null_value()) return Heap::undefined_value(); |
| 5714 return pt->GetElementWithReceiver(receiver, index); | 5883 return pt->GetElementWithReceiver(receiver, index); |
| 5715 } | 5884 } |
| 5716 | 5885 |
| 5717 | 5886 |
| 5718 bool JSObject::HasDenseElements() { | 5887 bool JSObject::HasDenseElements() { |
| 5719 int capacity = 0; | 5888 int capacity = 0; |
| 5720 int number_of_elements = 0; | 5889 int number_of_elements = 0; |
| 5721 | 5890 |
| 5722 if (HasFastElements()) { | 5891 switch (GetElementsKind()) { |
| 5723 FixedArray* elms = FixedArray::cast(elements()); | 5892 case FAST_ELEMENTS: { |
| 5724 capacity = elms->length(); | 5893 FixedArray* elms = FixedArray::cast(elements()); |
| 5725 for (int i = 0; i < capacity; i++) { | 5894 capacity = elms->length(); |
| 5726 if (!elms->get(i)->IsTheHole()) number_of_elements++; | 5895 for (int i = 0; i < capacity; i++) { |
| 5896 if (!elms->get(i)->IsTheHole()) number_of_elements++; |
| 5897 } |
| 5898 break; |
| 5727 } | 5899 } |
| 5728 } else { | 5900 case PIXEL_ELEMENTS: { |
| 5729 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 5901 return true; |
| 5730 capacity = dictionary->Capacity(); | 5902 } |
| 5731 number_of_elements = dictionary->NumberOfElements(); | 5903 case DICTIONARY_ELEMENTS: { |
| 5904 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5905 capacity = dictionary->Capacity(); |
| 5906 number_of_elements = dictionary->NumberOfElements(); |
| 5907 break; |
| 5908 } |
| 5909 default: |
| 5910 UNREACHABLE(); |
| 5911 break; |
| 5732 } | 5912 } |
| 5733 | 5913 |
| 5734 if (capacity == 0) return true; | 5914 if (capacity == 0) return true; |
| 5735 return (number_of_elements > (capacity / 2)); | 5915 return (number_of_elements > (capacity / 2)); |
| 5736 } | 5916 } |
| 5737 | 5917 |
| 5738 | 5918 |
| 5739 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 5919 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 5740 ASSERT(HasFastElements()); | 5920 ASSERT(HasFastElements()); |
| 5741 // Keep the array in fast case if the current backing storage is | 5921 // Keep the array in fast case if the current backing storage is |
| 5742 // almost filled and if the new capacity is no more than twice the | 5922 // almost filled and if the new capacity is no more than twice the |
| 5743 // old capacity. | 5923 // old capacity. |
| 5744 int elements_length = FixedArray::cast(elements())->length(); | 5924 int elements_length = FixedArray::cast(elements())->length(); |
| 5745 return !HasDenseElements() || ((new_capacity / 2) > elements_length); | 5925 return !HasDenseElements() || ((new_capacity / 2) > elements_length); |
| 5746 } | 5926 } |
| 5747 | 5927 |
| 5748 | 5928 |
| 5749 bool JSObject::ShouldConvertToFastElements() { | 5929 bool JSObject::ShouldConvertToFastElements() { |
| 5750 ASSERT(!HasFastElements()); | 5930 ASSERT(HasDictionaryElements()); |
| 5751 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 5931 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5752 // If the elements are sparse, we should not go back to fast case. | 5932 // If the elements are sparse, we should not go back to fast case. |
| 5753 if (!HasDenseElements()) return false; | 5933 if (!HasDenseElements()) return false; |
| 5754 // If an element has been added at a very high index in the elements | 5934 // If an element has been added at a very high index in the elements |
| 5755 // dictionary, we cannot go back to fast case. | 5935 // dictionary, we cannot go back to fast case. |
| 5756 if (dictionary->requires_slow_elements()) return false; | 5936 if (dictionary->requires_slow_elements()) return false; |
| 5757 // An object requiring access checks is never allowed to have fast | 5937 // An object requiring access checks is never allowed to have fast |
| 5758 // elements. If it had fast elements we would skip security checks. | 5938 // elements. If it had fast elements we would skip security checks. |
| 5759 if (IsAccessCheckNeeded()) return false; | 5939 if (IsAccessCheckNeeded()) return false; |
| 5760 // If the dictionary backing storage takes up roughly half as much | 5940 // If the dictionary backing storage takes up roughly half as much |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5994 // Check access rights if needed. | 6174 // Check access rights if needed. |
| 5995 if (IsAccessCheckNeeded() && | 6175 if (IsAccessCheckNeeded() && |
| 5996 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6176 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 5997 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6177 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 5998 return false; | 6178 return false; |
| 5999 } | 6179 } |
| 6000 | 6180 |
| 6001 // Handle [] on String objects. | 6181 // Handle [] on String objects. |
| 6002 if (this->IsStringObjectWithCharacterAt(index)) return true; | 6182 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6003 | 6183 |
| 6004 if (HasFastElements()) { | 6184 switch (GetElementsKind()) { |
| 6005 uint32_t length = IsJSArray() ? | 6185 case FAST_ELEMENTS: { |
| 6006 static_cast<uint32_t>( | 6186 uint32_t length = IsJSArray() ? |
| 6007 Smi::cast(JSArray::cast(this)->length())->value()) : | 6187 static_cast<uint32_t>( |
| 6008 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 6188 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 6009 return (index < length) && | 6189 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 6010 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 6190 return (index < length) && |
| 6191 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 6192 } |
| 6193 case PIXEL_ELEMENTS: { |
| 6194 PixelArray* pixels = PixelArray::cast(elements()); |
| 6195 return index < static_cast<uint32_t>(pixels->length()); |
| 6196 } |
| 6197 case DICTIONARY_ELEMENTS: { |
| 6198 return element_dictionary()->FindEntry(index) |
| 6199 != NumberDictionary::kNotFound; |
| 6200 } |
| 6201 default: |
| 6202 UNREACHABLE(); |
| 6203 break; |
| 6011 } | 6204 } |
| 6012 return element_dictionary()->FindEntry(index) | 6205 // All possibilities have been handled above already. |
| 6013 != NumberDictionary::kNotFound; | 6206 UNREACHABLE(); |
| 6207 return Heap::null_value(); |
| 6014 } | 6208 } |
| 6015 | 6209 |
| 6016 | 6210 |
| 6017 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 6211 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 6018 // Check access rights if needed. | 6212 // Check access rights if needed. |
| 6019 if (IsAccessCheckNeeded() && | 6213 if (IsAccessCheckNeeded() && |
| 6020 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 6214 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 6021 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6215 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6022 return false; | 6216 return false; |
| 6023 } | 6217 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6186 | 6380 |
| 6187 | 6381 |
| 6188 int JSObject::NumberOfEnumElements() { | 6382 int JSObject::NumberOfEnumElements() { |
| 6189 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); | 6383 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); |
| 6190 } | 6384 } |
| 6191 | 6385 |
| 6192 | 6386 |
| 6193 int JSObject::GetLocalElementKeys(FixedArray* storage, | 6387 int JSObject::GetLocalElementKeys(FixedArray* storage, |
| 6194 PropertyAttributes filter) { | 6388 PropertyAttributes filter) { |
| 6195 int counter = 0; | 6389 int counter = 0; |
| 6196 if (HasFastElements()) { | 6390 switch (GetElementsKind()) { |
| 6197 int length = IsJSArray() | 6391 case FAST_ELEMENTS: { |
| 6198 ? Smi::cast(JSArray::cast(this)->length())->value() | 6392 int length = IsJSArray() ? |
| 6199 : FixedArray::cast(elements())->length(); | 6393 Smi::cast(JSArray::cast(this)->length())->value() : |
| 6200 for (int i = 0; i < length; i++) { | 6394 FixedArray::cast(elements())->length(); |
| 6201 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 6395 for (int i = 0; i < length; i++) { |
| 6202 if (storage) { | 6396 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 6203 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6397 if (storage != NULL) { |
| 6398 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
| 6399 } |
| 6400 counter++; |
| 6401 } |
| 6402 } |
| 6403 ASSERT(!storage || storage->length() >= counter); |
| 6404 break; |
| 6405 } |
| 6406 case PIXEL_ELEMENTS: { |
| 6407 int length = PixelArray::cast(elements())->length(); |
| 6408 while (counter < length) { |
| 6409 if (storage != NULL) { |
| 6410 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); |
| 6204 } | 6411 } |
| 6205 counter++; | 6412 counter++; |
| 6206 } | 6413 } |
| 6414 ASSERT(!storage || storage->length() >= counter); |
| 6415 break; |
| 6207 } | 6416 } |
| 6208 ASSERT(!storage || storage->length() >= counter); | 6417 case DICTIONARY_ELEMENTS: { |
| 6209 } else { | 6418 if (storage != NULL) { |
| 6210 if (storage) { | 6419 element_dictionary()->CopyKeysTo(storage, filter); |
| 6211 element_dictionary()->CopyKeysTo(storage, filter); | 6420 } |
| 6421 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 6422 break; |
| 6212 } | 6423 } |
| 6213 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); | 6424 default: |
| 6425 UNREACHABLE(); |
| 6426 break; |
| 6214 } | 6427 } |
| 6215 | 6428 |
| 6216 if (this->IsJSValue()) { | 6429 if (this->IsJSValue()) { |
| 6217 Object* val = JSValue::cast(this)->value(); | 6430 Object* val = JSValue::cast(this)->value(); |
| 6218 if (val->IsString()) { | 6431 if (val->IsString()) { |
| 6219 String* str = String::cast(val); | 6432 String* str = String::cast(val); |
| 6220 if (storage) { | 6433 if (storage) { |
| 6221 for (int i = 0; i < str->length(); i++) { | 6434 for (int i = 0; i < str->length(); i++) { |
| 6222 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6435 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
| 6223 } | 6436 } |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6662 | 6875 |
| 6663 template | 6876 template |
| 6664 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); | 6877 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
| 6665 | 6878 |
| 6666 template | 6879 template |
| 6667 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); | 6880 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); |
| 6668 | 6881 |
| 6669 // Collates undefined and unexisting elements below limit from position | 6882 // Collates undefined and unexisting elements below limit from position |
| 6670 // zero of the elements. The object stays in Dictionary mode. | 6883 // zero of the elements. The object stays in Dictionary mode. |
| 6671 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 6884 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 6672 ASSERT(!HasFastElements()); | 6885 ASSERT(HasDictionaryElements()); |
| 6673 // Must stay in dictionary mode, either because of requires_slow_elements, | 6886 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 6674 // or because we are not going to sort (and therefore compact) all of the | 6887 // or because we are not going to sort (and therefore compact) all of the |
| 6675 // elements. | 6888 // elements. |
| 6676 NumberDictionary* dict = element_dictionary(); | 6889 NumberDictionary* dict = element_dictionary(); |
| 6677 HeapNumber* result_double = NULL; | 6890 HeapNumber* result_double = NULL; |
| 6678 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 6891 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 6679 // Allocate space for result before we start mutating the object. | 6892 // Allocate space for result before we start mutating the object. |
| 6680 Object* new_double = Heap::AllocateHeapNumber(0.0); | 6893 Object* new_double = Heap::AllocateHeapNumber(0.0); |
| 6681 if (new_double->IsFailure()) return new_double; | 6894 if (new_double->IsFailure()) return new_double; |
| 6682 result_double = HeapNumber::cast(new_double); | 6895 result_double = HeapNumber::cast(new_double); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6736 result_double->set_value(static_cast<double>(result)); | 6949 result_double->set_value(static_cast<double>(result)); |
| 6737 return result_double; | 6950 return result_double; |
| 6738 } | 6951 } |
| 6739 | 6952 |
| 6740 | 6953 |
| 6741 // Collects all defined (non-hole) and non-undefined (array) elements at | 6954 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 6742 // the start of the elements array. | 6955 // the start of the elements array. |
| 6743 // If the object is in dictionary mode, it is converted to fast elements | 6956 // If the object is in dictionary mode, it is converted to fast elements |
| 6744 // mode. | 6957 // mode. |
| 6745 Object* JSObject::PrepareElementsForSort(uint32_t limit) { | 6958 Object* JSObject::PrepareElementsForSort(uint32_t limit) { |
| 6746 if (!HasFastElements()) { | 6959 ASSERT(!HasPixelElements()); |
| 6960 |
| 6961 if (HasDictionaryElements()) { |
| 6747 // Convert to fast elements containing only the existing properties. | 6962 // Convert to fast elements containing only the existing properties. |
| 6748 // Ordering is irrelevant, since we are going to sort anyway. | 6963 // Ordering is irrelevant, since we are going to sort anyway. |
| 6749 NumberDictionary* dict = element_dictionary(); | 6964 NumberDictionary* dict = element_dictionary(); |
| 6750 if (IsJSArray() || dict->requires_slow_elements() || | 6965 if (IsJSArray() || dict->requires_slow_elements() || |
| 6751 dict->max_number_key() >= limit) { | 6966 dict->max_number_key() >= limit) { |
| 6752 return PrepareSlowElementsForSort(limit); | 6967 return PrepareSlowElementsForSort(limit); |
| 6753 } | 6968 } |
| 6754 // Convert to fast elements. | 6969 // Convert to fast elements. |
| 6755 | 6970 |
| 6756 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; | 6971 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; |
| 6757 Object* new_array = | 6972 Object* new_array = |
| 6758 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); | 6973 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); |
| 6759 if (new_array->IsFailure()) { | 6974 if (new_array->IsFailure()) { |
| 6760 return new_array; | 6975 return new_array; |
| 6761 } | 6976 } |
| 6762 FixedArray* fast_elements = FixedArray::cast(new_array); | 6977 FixedArray* fast_elements = FixedArray::cast(new_array); |
| 6763 dict->CopyValuesTo(fast_elements); | 6978 dict->CopyValuesTo(fast_elements); |
| 6764 set_elements(fast_elements); | 6979 set_elements(fast_elements); |
| 6765 } | 6980 } |
| 6766 ASSERT(HasFastElements()); | 6981 ASSERT(HasFastElements()); |
| 6767 | 6982 |
| 6768 // Collect holes at the end, undefined before that and the rest at the | 6983 // Collect holes at the end, undefined before that and the rest at the |
| 6769 // start, and return the number of non-hole, non-undefined values. | 6984 // start, and return the number of non-hole, non-undefined values. |
| 6770 | 6985 |
| 6771 FixedArray* elements = this->elements(); | 6986 FixedArray* elements = FixedArray::cast(this->elements()); |
| 6772 uint32_t elements_length = static_cast<uint32_t>(elements->length()); | 6987 uint32_t elements_length = static_cast<uint32_t>(elements->length()); |
| 6773 if (limit > elements_length) { | 6988 if (limit > elements_length) { |
| 6774 limit = elements_length ; | 6989 limit = elements_length ; |
| 6775 } | 6990 } |
| 6776 if (limit == 0) { | 6991 if (limit == 0) { |
| 6777 return Smi::FromInt(0); | 6992 return Smi::FromInt(0); |
| 6778 } | 6993 } |
| 6779 | 6994 |
| 6780 HeapNumber* result_double = NULL; | 6995 HeapNumber* result_double = NULL; |
| 6781 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 6996 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6831 | 7046 |
| 6832 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 7047 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 6833 return Smi::FromInt(static_cast<int>(result)); | 7048 return Smi::FromInt(static_cast<int>(result)); |
| 6834 } | 7049 } |
| 6835 ASSERT_NE(NULL, result_double); | 7050 ASSERT_NE(NULL, result_double); |
| 6836 result_double->set_value(static_cast<double>(result)); | 7051 result_double->set_value(static_cast<double>(result)); |
| 6837 return result_double; | 7052 return result_double; |
| 6838 } | 7053 } |
| 6839 | 7054 |
| 6840 | 7055 |
| 7056 Object* PixelArray::SetValue(uint32_t index, Object* value) { |
| 7057 uint8_t clamped_value = 0; |
| 7058 if (index < static_cast<uint32_t>(length())) { |
| 7059 int int_value = 0; |
| 7060 if (value->IsSmi()) { |
| 7061 int_value = Smi::cast(value)->value(); |
| 7062 } else if (value->IsHeapNumber()) { |
| 7063 static const DoubleRepresentation nan(OS::nan_value()); |
| 7064 DoubleRepresentation double_value = HeapNumber::cast(value)->value(); |
| 7065 if (nan.bits != double_value.bits) { |
| 7066 int_value = static_cast<int>(double_value.value + 0.5); |
| 7067 } else { |
| 7068 // NaN clamps to zero. |
| 7069 int_value = 0; |
| 7070 } |
| 7071 } else if (value->IsUndefined()) { |
| 7072 int_value = 0; |
| 7073 } else { |
| 7074 // All other types have been converted to a number type further up in the |
| 7075 // call chain. |
| 7076 UNREACHABLE(); |
| 7077 } |
| 7078 if (int_value < 0) { |
| 7079 clamped_value = 0; |
| 7080 } else if (int_value > 255) { |
| 7081 clamped_value = 255; |
| 7082 } else { |
| 7083 clamped_value = static_cast<uint8_t>(int_value); |
| 7084 } |
| 7085 set(index, clamped_value); |
| 7086 } |
| 7087 return Smi::FromInt(clamped_value); |
| 7088 } |
| 7089 |
| 7090 |
| 6841 Object* GlobalObject::GetPropertyCell(LookupResult* result) { | 7091 Object* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 6842 ASSERT(!HasFastProperties()); | 7092 ASSERT(!HasFastProperties()); |
| 6843 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 7093 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 6844 ASSERT(value->IsJSGlobalPropertyCell()); | 7094 ASSERT(value->IsJSGlobalPropertyCell()); |
| 6845 return value; | 7095 return value; |
| 6846 } | 7096 } |
| 6847 | 7097 |
| 6848 | 7098 |
| 6849 Object* GlobalObject::EnsurePropertyCell(String* name) { | 7099 Object* GlobalObject::EnsurePropertyCell(String* name) { |
| 6850 ASSERT(!HasFastProperties()); | 7100 ASSERT(!HasFastProperties()); |
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7747 if (break_point_objects()->IsUndefined()) return 0; | 7997 if (break_point_objects()->IsUndefined()) return 0; |
| 7748 // Single beak point. | 7998 // Single beak point. |
| 7749 if (!break_point_objects()->IsFixedArray()) return 1; | 7999 if (!break_point_objects()->IsFixedArray()) return 1; |
| 7750 // Multiple break points. | 8000 // Multiple break points. |
| 7751 return FixedArray::cast(break_point_objects())->length(); | 8001 return FixedArray::cast(break_point_objects())->length(); |
| 7752 } | 8002 } |
| 7753 #endif | 8003 #endif |
| 7754 | 8004 |
| 7755 | 8005 |
| 7756 } } // namespace v8::internal | 8006 } } // namespace v8::internal |
| OLD | NEW |