Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2565 if (HasFastProperties()) return this; | 2565 if (HasFastProperties()) return this; |
| 2566 ASSERT(!IsGlobalObject()); | 2566 ASSERT(!IsGlobalObject()); |
| 2567 return property_dictionary()-> | 2567 return property_dictionary()-> |
| 2568 TransformPropertiesToFastFor(this, unused_property_fields); | 2568 TransformPropertiesToFastFor(this, unused_property_fields); |
| 2569 } | 2569 } |
| 2570 | 2570 |
| 2571 | 2571 |
| 2572 MaybeObject* JSObject::NormalizeElements() { | 2572 MaybeObject* JSObject::NormalizeElements() { |
| 2573 ASSERT(!HasExternalArrayElements()); | 2573 ASSERT(!HasExternalArrayElements()); |
| 2574 // Find the backing store. | 2574 // Find the backing store. |
| 2575 FixedArray* elements = FixedArray::cast(this->elements()); | 2575 FixedArray* original = FixedArray::cast(elements()); |
| 2576 bool is_arguments = | 2576 bool is_arguments = |
| 2577 (elements->map() == GetHeap()->non_strict_arguments_elements_map()); | 2577 (original->map() == GetHeap()->non_strict_arguments_elements_map()); |
| 2578 if (is_arguments) { | 2578 if (is_arguments) { |
| 2579 elements = FixedArray::cast(elements->get(1)); | 2579 original = FixedArray::cast(original->get(1)); |
| 2580 } | 2580 } |
| 2581 if (elements->IsDictionary()) return elements; | 2581 if (original->IsDictionary()) return original; |
| 2582 | 2582 |
| 2583 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 2583 ASSERT(HasFastElements() || HasFastArgumentsElements()); |
| 2584 // Compute the effective length and allocate a new backing store. | 2584 // Compute the effective length and allocate a new backing store. |
| 2585 int length = IsJSArray() | 2585 int length = IsJSArray() |
| 2586 ? Smi::cast(JSArray::cast(this)->length())->value() | 2586 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2587 : elements->length(); | 2587 : original->length(); |
| 2588 NumberDictionary* dictionary = NULL; | 2588 NumberDictionary* dictionary = NULL; |
| 2589 { Object* object; | 2589 { Object* object; |
| 2590 MaybeObject* maybe = NumberDictionary::Allocate(length); | 2590 MaybeObject* maybe = NumberDictionary::Allocate(length); |
| 2591 if (!maybe->ToObject(&object)) return maybe; | 2591 if (!maybe->ToObject(&object)) return maybe; |
| 2592 dictionary = NumberDictionary::cast(object); | 2592 dictionary = NumberDictionary::cast(object); |
| 2593 } | 2593 } |
| 2594 | 2594 |
| 2595 // Copy the elements to the new backing store. | 2595 // Copy the elements to the new backing store. |
| 2596 for (int i = 0; i < length; i++) { | 2596 for (int i = 0; i < length; i++) { |
| 2597 Object* value = elements->get(i); | 2597 Object* value = original->get(i); |
| 2598 if (!value->IsTheHole()) { | 2598 if (!value->IsTheHole()) { |
| 2599 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2599 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2600 Object* new_dictionary; | 2600 Object* new_dictionary; |
| 2601 MaybeObject* maybe = | 2601 MaybeObject* maybe = dictionary->AddNumberEntry(i, value, details); |
| 2602 dictionary->AddNumberEntry(i, elements->get(i), details); | |
| 2603 if (!maybe->ToObject(&new_dictionary)) return maybe; | 2602 if (!maybe->ToObject(&new_dictionary)) return maybe; |
| 2604 dictionary = NumberDictionary::cast(new_dictionary); | 2603 dictionary = NumberDictionary::cast(new_dictionary); |
| 2605 } | 2604 } |
| 2606 } | 2605 } |
| 2607 | 2606 |
| 2608 // Switch to using the dictionary as the backing storage for elements. | 2607 // Switch to using the dictionary as the backing storage for elements. |
| 2609 if (is_arguments) { | 2608 if (is_arguments) { |
| 2610 FixedArray::cast(this->elements())->set(1, dictionary); | 2609 FixedArray::cast(elements())->set(1, dictionary); |
| 2611 } else { | 2610 } else { |
| 2612 // Set the new map first to satify the elements type assert in | 2611 // Set the new map first to satify the elements type assert in |
| 2613 // set_elements(). | 2612 // set_elements(). |
| 2614 Object* new_map; | 2613 Object* new_map; |
| 2615 MaybeObject* maybe = map()->GetSlowElementsMap(); | 2614 MaybeObject* maybe = map()->GetSlowElementsMap(); |
| 2616 if (!maybe->ToObject(&new_map)) return maybe; | 2615 if (!maybe->ToObject(&new_map)) return maybe; |
| 2617 set_map(Map::cast(new_map)); | 2616 set_map(Map::cast(new_map)); |
| 2618 set_elements(dictionary); | 2617 set_elements(dictionary); |
| 2619 } | 2618 } |
| 2620 | 2619 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2749 MaybeObject* raw_result = | 2748 MaybeObject* raw_result = |
| 2750 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); | 2749 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); |
| 2751 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2750 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2752 return raw_result; | 2751 return raw_result; |
| 2753 } | 2752 } |
| 2754 | 2753 |
| 2755 | 2754 |
| 2756 MaybeObject* JSObject::DeleteFastElement(uint32_t index) { | 2755 MaybeObject* JSObject::DeleteFastElement(uint32_t index) { |
| 2757 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 2756 ASSERT(HasFastElements() || HasFastArgumentsElements()); |
| 2758 Heap* heap = GetHeap(); | 2757 Heap* heap = GetHeap(); |
| 2759 FixedArray* elements = FixedArray::cast(this->elements()); | 2758 FixedArray* backing_store = FixedArray::cast(elements()); |
| 2760 if (elements->map() == heap->non_strict_arguments_elements_map()) { | 2759 if (backing_streo->map() == heap->non_strict_arguments_elements_map()) { |
|
Kevin Millikin (Chromium)
2011/03/30 12:02:45
I'll commit the version that actually compiles.
| |
| 2761 elements = FixedArray::cast(elements->get(1)); | 2760 backing_store = FixedArray::cast(backing_store->get(1)); |
| 2762 } else { | 2761 } else { |
| 2763 Object* object; | 2762 Object* writable; |
| 2764 MaybeObject* maybe = EnsureWritableFastElements(); | 2763 MaybeObject* maybe = EnsureWritableFastElements(); |
| 2765 if (!maybe->ToObject(&object)) return maybe; | 2764 if (!maybe->ToObject(&writable)) return maybe; |
| 2766 elements = FixedArray::cast(object); | 2765 backing_store = FixedArray::cast(writable); |
| 2767 } | 2766 } |
| 2768 int length = IsJSArray() | 2767 int length = IsJSArray() |
| 2769 ? Smi::cast(JSArray::cast(this)->length())->value() | 2768 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2770 : elements->length(); | 2769 : backing_store->length(); |
| 2771 if (index < static_cast<uint32_t>(length)) { | 2770 if (index < static_cast<uint32_t>(length)) { |
| 2772 elements->set_the_hole(index); | 2771 backing_store->set_the_hole(index); |
| 2773 } | 2772 } |
| 2774 return heap->true_value(); | 2773 return heap->true_value(); |
| 2775 } | 2774 } |
| 2776 | 2775 |
| 2777 | 2776 |
| 2778 MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index, | 2777 MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index, |
| 2779 DeleteMode mode) { | 2778 DeleteMode mode) { |
| 2780 Isolate* isolate = GetIsolate(); | 2779 Isolate* isolate = GetIsolate(); |
| 2781 Heap* heap = isolate->heap(); | 2780 Heap* heap = isolate->heap(); |
| 2782 FixedArray* elements = FixedArray::cast(this->elements()); | 2781 FixedArray* backing_store = FixedArray::cast(elements()); |
| 2783 if (elements->map() == heap->non_strict_arguments_elements_map()) { | 2782 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
| 2784 elements = FixedArray::cast(elements->get(1)); | 2783 backing_store = FixedArray::cast(backing_store->get(1)); |
| 2785 } | 2784 } |
| 2786 NumberDictionary* dictionary = NumberDictionary::cast(elements); | 2785 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 2787 int entry = dictionary->FindEntry(index); | 2786 int entry = dictionary->FindEntry(index); |
| 2788 if (entry != NumberDictionary::kNotFound) { | 2787 if (entry != NumberDictionary::kNotFound) { |
| 2789 Object* result = dictionary->DeleteProperty(entry, mode); | 2788 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2790 if (mode == STRICT_DELETION && result == heap->false_value()) { | 2789 if (mode == STRICT_DELETION && result == heap->false_value()) { |
| 2791 // In strict mode, attempting to delete a non-configurable property | 2790 // In strict mode, attempting to delete a non-configurable property |
| 2792 // throws an exception. | 2791 // throws an exception. |
| 2793 HandleScope scope(isolate); | 2792 HandleScope scope(isolate); |
| 2794 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); | 2793 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); |
| 2795 Handle<Object> args[2] = { name, Handle<Object>(this) }; | 2794 Handle<Object> args[2] = { name, Handle<Object>(this) }; |
| 2796 Handle<Object> error = | 2795 Handle<Object> error = |
| (...skipping 4696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7493 | 7492 |
| 7494 // Adding n elements in fast case is O(n*n). | 7493 // Adding n elements in fast case is O(n*n). |
| 7495 // Note: revisit design to have dual undefined values to capture absent | 7494 // Note: revisit design to have dual undefined values to capture absent |
| 7496 // elements. | 7495 // elements. |
| 7497 MaybeObject* JSObject::SetFastElement(uint32_t index, | 7496 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 7498 Object* value, | 7497 Object* value, |
| 7499 StrictModeFlag strict_mode, | 7498 StrictModeFlag strict_mode, |
| 7500 bool check_prototype) { | 7499 bool check_prototype) { |
| 7501 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 7500 ASSERT(HasFastElements() || HasFastArgumentsElements()); |
| 7502 | 7501 |
| 7503 FixedArray* elements = FixedArray::cast(this->elements()); | 7502 FixedArray* backing_store = FixedArray::cast(elements()); |
| 7504 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { | 7503 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 7505 elements = FixedArray::cast(elements->get(1)); | 7504 backing_store = FixedArray::cast(backing_store->get(1)); |
| 7506 } else { | 7505 } else { |
| 7507 Object* object; | 7506 Object* writable; |
| 7508 MaybeObject* maybe = EnsureWritableFastElements(); | 7507 MaybeObject* maybe = EnsureWritableFastElements(); |
| 7509 if (!maybe->ToObject(&object)) return maybe; | 7508 if (!maybe->ToObject(&writable)) return maybe; |
| 7510 elements = FixedArray::cast(object); | 7509 backing_store = FixedArray::cast(writable); |
| 7511 } | 7510 } |
| 7512 uint32_t length = static_cast<uint32_t>(elements->length()); | 7511 uint32_t length = static_cast<uint32_t>(backing_store->length()); |
| 7513 | 7512 |
| 7514 if (check_prototype && | 7513 if (check_prototype && |
| 7515 (index >= length || elements->get(index)->IsTheHole())) { | 7514 (index >= length || backing_store->get(index)->IsTheHole())) { |
| 7516 bool found; | 7515 bool found; |
| 7517 MaybeObject* result = | 7516 MaybeObject* result = |
| 7518 SetElementWithCallbackSetterInPrototypes(index, value, &found); | 7517 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7519 if (found) return result; | 7518 if (found) return result; |
| 7520 } | 7519 } |
| 7521 | 7520 |
| 7522 // Check whether there is extra space in fixed array.. | 7521 // Check whether there is extra space in fixed array.. |
| 7523 if (index < length) { | 7522 if (index < length) { |
| 7524 elements->set(index, value); | 7523 backing_store->set(index, value); |
| 7525 if (IsJSArray()) { | 7524 if (IsJSArray()) { |
| 7526 // Update the length of the array if needed. | 7525 // Update the length of the array if needed. |
| 7527 uint32_t array_length = 0; | 7526 uint32_t array_length = 0; |
| 7528 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 7527 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 7529 if (index >= array_length) { | 7528 if (index >= array_length) { |
| 7530 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 7529 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 7531 } | 7530 } |
| 7532 } | 7531 } |
| 7533 return value; | 7532 return value; |
| 7534 } | 7533 } |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8056 break; | 8055 break; |
| 8057 } | 8056 } |
| 8058 return GetHeap()->undefined_value(); | 8057 return GetHeap()->undefined_value(); |
| 8059 } | 8058 } |
| 8060 | 8059 |
| 8061 | 8060 |
| 8062 bool JSObject::HasDenseElements() { | 8061 bool JSObject::HasDenseElements() { |
| 8063 int capacity = 0; | 8062 int capacity = 0; |
| 8064 int number_of_elements = 0; | 8063 int number_of_elements = 0; |
| 8065 | 8064 |
| 8066 FixedArray* elements = FixedArray::cast(this->elements()); | 8065 FixedArray* backing_store = FixedArray::cast(elements()); |
| 8067 switch (GetElementsKind()) { | 8066 switch (GetElementsKind()) { |
| 8068 case NON_STRICT_ARGUMENTS_ELEMENTS: | 8067 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 8069 elements = FixedArray::cast(elements->get(1)); | 8068 backing_store = FixedArray::cast(backing_store->get(1)); |
| 8070 if (elements->IsDictionary()) { | 8069 if (backing_store->IsDictionary()) { |
| 8071 NumberDictionary* dictionary = NumberDictionary::cast(elements); | 8070 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8072 capacity = dictionary->Capacity(); | 8071 capacity = dictionary->Capacity(); |
| 8073 number_of_elements = dictionary->NumberOfElements(); | 8072 number_of_elements = dictionary->NumberOfElements(); |
| 8074 break; | 8073 break; |
| 8075 } | 8074 } |
| 8076 // Fall through. | 8075 // Fall through. |
| 8077 case FAST_ELEMENTS: | 8076 case FAST_ELEMENTS: |
| 8078 capacity = elements->length(); | 8077 capacity = backing_store->length(); |
| 8079 for (int i = 0; i < capacity; ++i) { | 8078 for (int i = 0; i < capacity; ++i) { |
| 8080 if (!elements->get(i)->IsTheHole()) ++number_of_elements; | 8079 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements; |
| 8081 } | 8080 } |
| 8082 break; | 8081 break; |
| 8083 case DICTIONARY_ELEMENTS: { | 8082 case DICTIONARY_ELEMENTS: { |
| 8084 NumberDictionary* dictionary = NumberDictionary::cast(elements); | 8083 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8085 capacity = dictionary->Capacity(); | 8084 capacity = dictionary->Capacity(); |
| 8086 number_of_elements = dictionary->NumberOfElements(); | 8085 number_of_elements = dictionary->NumberOfElements(); |
| 8087 break; | 8086 break; |
| 8088 } | 8087 } |
| 8089 case EXTERNAL_PIXEL_ELEMENTS: | 8088 case EXTERNAL_PIXEL_ELEMENTS: |
| 8090 case EXTERNAL_BYTE_ELEMENTS: | 8089 case EXTERNAL_BYTE_ELEMENTS: |
| 8091 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8090 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 8092 case EXTERNAL_SHORT_ELEMENTS: | 8091 case EXTERNAL_SHORT_ELEMENTS: |
| 8093 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8092 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8094 case EXTERNAL_INT_ELEMENTS: | 8093 case EXTERNAL_INT_ELEMENTS: |
| 8095 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8094 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8096 case EXTERNAL_FLOAT_ELEMENTS: | 8095 case EXTERNAL_FLOAT_ELEMENTS: |
| 8097 return true; | 8096 return true; |
| 8098 } | 8097 } |
| 8099 | 8098 |
| 8100 return (capacity == 0) || (number_of_elements > (capacity / 2)); | 8099 return (capacity == 0) || (number_of_elements > (capacity / 2)); |
| 8101 } | 8100 } |
| 8102 | 8101 |
| 8103 | 8102 |
| 8104 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 8103 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 8105 ASSERT(HasFastElements()); | 8104 ASSERT(HasFastElements()); |
| 8106 // Keep the array in fast case if the current backing storage is | 8105 // Keep the array in fast case if the current backing storage is |
| 8107 // almost filled and if the new capacity is no more than twice the | 8106 // almost filled and if the new capacity is no more than twice the |
| 8108 // old capacity. | 8107 // old capacity. |
| 8109 FixedArray* elements = FixedArray::cast(this->elements()); | 8108 FixedArray* backing_store = FixedArray::cast(elements()); |
| 8110 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { | 8109 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 8111 elements = FixedArray::cast(elements->get(1)); | 8110 backing_store = FixedArray::cast(backing_store->get(1)); |
| 8112 } | 8111 } |
| 8113 return !HasDenseElements() || ((new_capacity / 2) > elements->length()); | 8112 return !HasDenseElements() || ((new_capacity / 2) > backing_store->length()); |
| 8114 } | 8113 } |
| 8115 | 8114 |
| 8116 | 8115 |
| 8117 bool JSObject::ShouldConvertToFastElements() { | 8116 bool JSObject::ShouldConvertToFastElements() { |
| 8118 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 8117 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 8119 // If the elements are sparse, we should not go back to fast case. | 8118 // If the elements are sparse, we should not go back to fast case. |
| 8120 if (!HasDenseElements()) return false; | 8119 if (!HasDenseElements()) return false; |
| 8121 // An object requiring access checks is never allowed to have fast | 8120 // An object requiring access checks is never allowed to have fast |
| 8122 // elements. If it had fast elements we would skip security checks. | 8121 // elements. If it had fast elements we would skip security checks. |
| 8123 if (IsAccessCheckNeeded()) return false; | 8122 if (IsAccessCheckNeeded()) return false; |
| (...skipping 2470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10594 if (break_point_objects()->IsUndefined()) return 0; | 10593 if (break_point_objects()->IsUndefined()) return 0; |
| 10595 // Single beak point. | 10594 // Single beak point. |
| 10596 if (!break_point_objects()->IsFixedArray()) return 1; | 10595 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10597 // Multiple break points. | 10596 // Multiple break points. |
| 10598 return FixedArray::cast(break_point_objects())->length(); | 10597 return FixedArray::cast(break_point_objects())->length(); |
| 10599 } | 10598 } |
| 10600 #endif | 10599 #endif |
| 10601 | 10600 |
| 10602 | 10601 |
| 10603 } } // namespace v8::internal | 10602 } } // namespace v8::internal |
| OLD | NEW |