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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 #endif | 51 #endif |
52 | 52 |
53 namespace v8 { | 53 namespace v8 { |
54 namespace internal { | 54 namespace internal { |
55 | 55 |
56 // Getters and setters are stored in a fixed array property. These are | 56 // Getters and setters are stored in a fixed array property. These are |
57 // constants for their indices. | 57 // constants for their indices. |
58 const int kGetterIndex = 0; | 58 const int kGetterIndex = 0; |
59 const int kSetterIndex = 1; | 59 const int kSetterIndex = 1; |
60 | 60 |
61 uint64_t FixedDoubleArray::kHoleNanInt64 = -1; | |
62 uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000; | |
63 uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 = | |
64 kCanonicalNonHoleNanLower32 << 32; | |
65 | |
66 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 61 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
67 Object* value) { | 62 Object* value) { |
68 Object* result; | 63 Object* result; |
69 { MaybeObject* maybe_result = | 64 { MaybeObject* maybe_result = |
70 constructor->GetHeap()->AllocateJSObject(constructor); | 65 constructor->GetHeap()->AllocateJSObject(constructor); |
71 if (!maybe_result->ToObject(&result)) return maybe_result; | 66 if (!maybe_result->ToObject(&result)) return maybe_result; |
72 } | 67 } |
73 JSValue::cast(result)->set_value(value); | 68 JSValue::cast(result)->set_value(value); |
74 return result; | 69 return result; |
75 } | 70 } |
(...skipping 2728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2804 ASSERT(!IsGlobalObject()); | 2799 ASSERT(!IsGlobalObject()); |
2805 return property_dictionary()-> | 2800 return property_dictionary()-> |
2806 TransformPropertiesToFastFor(this, unused_property_fields); | 2801 TransformPropertiesToFastFor(this, unused_property_fields); |
2807 } | 2802 } |
2808 | 2803 |
2809 | 2804 |
2810 MaybeObject* JSObject::NormalizeElements() { | 2805 MaybeObject* JSObject::NormalizeElements() { |
2811 ASSERT(!HasExternalArrayElements()); | 2806 ASSERT(!HasExternalArrayElements()); |
2812 | 2807 |
2813 // Find the backing store. | 2808 // Find the backing store. |
2814 FixedArray* array = FixedArray::cast(elements()); | 2809 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
2815 Map* old_map = array->map(); | 2810 Map* old_map = array->map(); |
2816 bool is_arguments = | 2811 bool is_arguments = |
2817 (old_map == old_map->heap()->non_strict_arguments_elements_map()); | 2812 (old_map == old_map->heap()->non_strict_arguments_elements_map()); |
2818 if (is_arguments) { | 2813 if (is_arguments) { |
2819 array = FixedArray::cast(array->get(1)); | 2814 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
2820 } | 2815 } |
2821 if (array->IsDictionary()) return array; | 2816 if (array->IsDictionary()) return array; |
2822 | 2817 |
2823 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 2818 ASSERT(HasFastElements() || |
| 2819 HasFastDoubleElements() || |
| 2820 HasFastArgumentsElements()); |
2824 // Compute the effective length and allocate a new backing store. | 2821 // Compute the effective length and allocate a new backing store. |
2825 int length = IsJSArray() | 2822 int length = IsJSArray() |
2826 ? Smi::cast(JSArray::cast(this)->length())->value() | 2823 ? Smi::cast(JSArray::cast(this)->length())->value() |
2827 : array->length(); | 2824 : array->length(); |
2828 NumberDictionary* dictionary = NULL; | 2825 NumberDictionary* dictionary = NULL; |
2829 { Object* object; | 2826 { Object* object; |
2830 MaybeObject* maybe = NumberDictionary::Allocate(length); | 2827 MaybeObject* maybe = NumberDictionary::Allocate(length); |
2831 if (!maybe->ToObject(&object)) return maybe; | 2828 if (!maybe->ToObject(&object)) return maybe; |
2832 dictionary = NumberDictionary::cast(object); | 2829 dictionary = NumberDictionary::cast(object); |
2833 } | 2830 } |
2834 | 2831 |
2835 // Copy the elements to the new backing store. | 2832 // Copy the elements to the new backing store. |
2836 bool has_double_elements = old_map->has_fast_double_elements(); | 2833 bool has_double_elements = array->IsFixedDoubleArray(); |
2837 for (int i = 0; i < length; i++) { | 2834 for (int i = 0; i < length; i++) { |
2838 Object* value = NULL; | 2835 Object* value = NULL; |
2839 if (has_double_elements) { | 2836 if (has_double_elements) { |
2840 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); | 2837 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
2841 if (double_array->is_the_hole(i)) { | 2838 if (double_array->is_the_hole(i)) { |
2842 value = GetIsolate()->heap()->the_hole_value(); | 2839 value = GetIsolate()->heap()->the_hole_value(); |
2843 } else { | 2840 } else { |
2844 // Objects must be allocated in the old object space, since the | 2841 // Objects must be allocated in the old object space, since the |
2845 // overall number of HeapNumbers needed for the conversion might | 2842 // overall number of HeapNumbers needed for the conversion might |
2846 // exceed the capacity of new space, and we would fail repeatedly | 2843 // exceed the capacity of new space, and we would fail repeatedly |
2847 // trying to convert the FixedDoubleArray. | 2844 // trying to convert the FixedDoubleArray. |
2848 MaybeObject* maybe_value_object = | 2845 MaybeObject* maybe_value_object = |
2849 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); | 2846 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); |
2850 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 2847 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
2851 } | 2848 } |
2852 } else { | 2849 } else { |
2853 ASSERT(old_map->has_fast_elements()); | 2850 ASSERT(old_map->has_fast_elements()); |
2854 value = array->get(i); | 2851 value = FixedArray::cast(array)->get(i); |
2855 } | 2852 } |
2856 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2853 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
2857 if (!value->IsTheHole()) { | 2854 if (!value->IsTheHole()) { |
2858 Object* result; | 2855 Object* result; |
2859 MaybeObject* maybe_result = | 2856 MaybeObject* maybe_result = |
2860 dictionary->AddNumberEntry(i, value, details); | 2857 dictionary->AddNumberEntry(i, value, details); |
2861 if (!maybe_result->ToObject(&result)) return maybe_result; | 2858 if (!maybe_result->ToObject(&result)) return maybe_result; |
2862 dictionary = NumberDictionary::cast(result); | 2859 dictionary = NumberDictionary::cast(result); |
2863 } | 2860 } |
2864 } | 2861 } |
(...skipping 4445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7310 | 7307 |
7311 // Find the new map to use for this object if there is a map change. | 7308 // Find the new map to use for this object if there is a map change. |
7312 Map* new_map = NULL; | 7309 Map* new_map = NULL; |
7313 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7310 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
7314 Object* object; | 7311 Object* object; |
7315 MaybeObject* maybe = map()->GetFastElementsMap(); | 7312 MaybeObject* maybe = map()->GetFastElementsMap(); |
7316 if (!maybe->ToObject(&object)) return maybe; | 7313 if (!maybe->ToObject(&object)) return maybe; |
7317 new_map = Map::cast(object); | 7314 new_map = Map::cast(object); |
7318 } | 7315 } |
7319 | 7316 |
7320 AssertNoAllocation no_gc; | |
7321 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | |
7322 switch (GetElementsKind()) { | 7317 switch (GetElementsKind()) { |
7323 case FAST_ELEMENTS: | 7318 case FAST_ELEMENTS: { |
| 7319 AssertNoAllocation no_gc; |
| 7320 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
7324 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7321 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
7325 set_map(new_map); | 7322 set_map(new_map); |
7326 set_elements(new_elements); | 7323 set_elements(new_elements); |
7327 break; | 7324 break; |
7328 case DICTIONARY_ELEMENTS: | 7325 } |
| 7326 case DICTIONARY_ELEMENTS: { |
| 7327 AssertNoAllocation no_gc; |
| 7328 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
7329 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 7329 CopySlowElementsToFast(NumberDictionary::cast(elements()), |
7330 new_elements, | 7330 new_elements, |
7331 mode); | 7331 mode); |
7332 set_map(new_map); | 7332 set_map(new_map); |
7333 set_elements(new_elements); | 7333 set_elements(new_elements); |
7334 break; | 7334 break; |
| 7335 } |
7335 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 7336 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 7337 AssertNoAllocation no_gc; |
| 7338 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
7336 // The object's map and the parameter map are unchanged, the unaliased | 7339 // The object's map and the parameter map are unchanged, the unaliased |
7337 // arguments are copied to the new backing store. | 7340 // arguments are copied to the new backing store. |
7338 FixedArray* parameter_map = FixedArray::cast(elements()); | 7341 FixedArray* parameter_map = FixedArray::cast(elements()); |
7339 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 7342 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
7340 if (arguments->IsDictionary()) { | 7343 if (arguments->IsDictionary()) { |
7341 CopySlowElementsToFast(NumberDictionary::cast(arguments), | 7344 CopySlowElementsToFast(NumberDictionary::cast(arguments), |
7342 new_elements, | 7345 new_elements, |
7343 mode); | 7346 mode); |
7344 } else { | 7347 } else { |
7345 CopyFastElementsToFast(arguments, new_elements, mode); | 7348 CopyFastElementsToFast(arguments, new_elements, mode); |
(...skipping 15 matching lines...) Expand all Loading... |
7361 MaybeObject* maybe_value_object = | 7364 MaybeObject* maybe_value_object = |
7362 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); | 7365 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); |
7363 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; | 7366 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; |
7364 // Force write barrier. It's not worth trying to exploit | 7367 // Force write barrier. It's not worth trying to exploit |
7365 // elems->GetWriteBarrierMode(), since it requires an | 7368 // elems->GetWriteBarrierMode(), since it requires an |
7366 // AssertNoAllocation stack object that would have to be positioned | 7369 // AssertNoAllocation stack object that would have to be positioned |
7367 // after the HeapNumber allocation anyway. | 7370 // after the HeapNumber allocation anyway. |
7368 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); | 7371 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); |
7369 } | 7372 } |
7370 } | 7373 } |
| 7374 set_map(new_map); |
| 7375 set_elements(new_elements); |
7371 break; | 7376 break; |
7372 } | 7377 } |
7373 case EXTERNAL_BYTE_ELEMENTS: | 7378 case EXTERNAL_BYTE_ELEMENTS: |
7374 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7379 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
7375 case EXTERNAL_SHORT_ELEMENTS: | 7380 case EXTERNAL_SHORT_ELEMENTS: |
7376 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7381 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
7377 case EXTERNAL_INT_ELEMENTS: | 7382 case EXTERNAL_INT_ELEMENTS: |
7378 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7383 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
7379 case EXTERNAL_FLOAT_ELEMENTS: | 7384 case EXTERNAL_FLOAT_ELEMENTS: |
7380 case EXTERNAL_DOUBLE_ELEMENTS: | 7385 case EXTERNAL_DOUBLE_ELEMENTS: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7423 } | 7428 } |
7424 case DICTIONARY_ELEMENTS: { | 7429 case DICTIONARY_ELEMENTS: { |
7425 elems->Initialize(NumberDictionary::cast(elements())); | 7430 elems->Initialize(NumberDictionary::cast(elements())); |
7426 break; | 7431 break; |
7427 } | 7432 } |
7428 default: | 7433 default: |
7429 UNREACHABLE(); | 7434 UNREACHABLE(); |
7430 break; | 7435 break; |
7431 } | 7436 } |
7432 | 7437 |
| 7438 ASSERT(new_map->has_fast_double_elements()); |
7433 set_map(new_map); | 7439 set_map(new_map); |
| 7440 ASSERT(elems->IsFixedDoubleArray()); |
7434 set_elements(elems); | 7441 set_elements(elems); |
7435 | 7442 |
7436 if (IsJSArray()) { | 7443 if (IsJSArray()) { |
7437 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 7444 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
7438 } | 7445 } |
7439 | 7446 |
7440 return this; | 7447 return this; |
7441 } | 7448 } |
7442 | 7449 |
7443 | 7450 |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8400 } | 8407 } |
8401 | 8408 |
8402 // Attempt to put this object back in fast case. | 8409 // Attempt to put this object back in fast case. |
8403 if (ShouldConvertToFastElements()) { | 8410 if (ShouldConvertToFastElements()) { |
8404 uint32_t new_length = 0; | 8411 uint32_t new_length = 0; |
8405 if (IsJSArray()) { | 8412 if (IsJSArray()) { |
8406 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8413 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
8407 } else { | 8414 } else { |
8408 new_length = dictionary->max_number_key() + 1; | 8415 new_length = dictionary->max_number_key() + 1; |
8409 } | 8416 } |
8410 MaybeObject* result = | 8417 MaybeObject* result = ShouldConvertToFastDoubleElements() |
8411 SetFastElementsCapacityAndLength(new_length, new_length); | 8418 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
| 8419 : SetFastElementsCapacityAndLength(new_length, new_length); |
8412 if (result->IsFailure()) return result; | 8420 if (result->IsFailure()) return result; |
8413 #ifdef DEBUG | 8421 #ifdef DEBUG |
8414 if (FLAG_trace_normalization) { | 8422 if (FLAG_trace_normalization) { |
8415 PrintF("Object elements are fast case again:\n"); | 8423 PrintF("Object elements are fast case again:\n"); |
8416 Print(); | 8424 Print(); |
8417 } | 8425 } |
8418 #endif | 8426 #endif |
8419 } | 8427 } |
8420 return value; | 8428 return value; |
8421 } | 8429 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8488 SetFastDoubleElementsCapacityAndLength(new_capacity, | 8496 SetFastDoubleElementsCapacityAndLength(new_capacity, |
8489 index + 1); | 8497 index + 1); |
8490 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8498 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
8491 } | 8499 } |
8492 FixedDoubleArray::cast(elements())->set(index, double_value); | 8500 FixedDoubleArray::cast(elements())->set(index, double_value); |
8493 return value; | 8501 return value; |
8494 } | 8502 } |
8495 } | 8503 } |
8496 | 8504 |
8497 // Otherwise default to slow case. | 8505 // Otherwise default to slow case. |
| 8506 ASSERT(HasFastDoubleElements()); |
| 8507 ASSERT(map()->has_fast_double_elements()); |
| 8508 ASSERT(elements()->IsFixedDoubleArray()); |
8498 Object* obj; | 8509 Object* obj; |
8499 { MaybeObject* maybe_obj = NormalizeElements(); | 8510 { MaybeObject* maybe_obj = NormalizeElements(); |
8500 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8511 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
8501 } | 8512 } |
8502 ASSERT(HasDictionaryElements()); | 8513 ASSERT(HasDictionaryElements()); |
8503 return SetElement(index, value, strict_mode, check_prototype); | 8514 return SetElement(index, value, strict_mode, check_prototype); |
8504 } | 8515 } |
8505 | 8516 |
8506 | 8517 |
8507 MaybeObject* JSObject::SetElement(uint32_t index, | 8518 MaybeObject* JSObject::SetElement(uint32_t index, |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8941 break; | 8952 break; |
8942 } | 8953 } |
8943 return GetHeap()->undefined_value(); | 8954 return GetHeap()->undefined_value(); |
8944 } | 8955 } |
8945 | 8956 |
8946 | 8957 |
8947 bool JSObject::HasDenseElements() { | 8958 bool JSObject::HasDenseElements() { |
8948 int capacity = 0; | 8959 int capacity = 0; |
8949 int number_of_elements = 0; | 8960 int number_of_elements = 0; |
8950 | 8961 |
8951 FixedArray* backing_store = FixedArray::cast(elements()); | 8962 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); |
| 8963 FixedArray* backing_store = NULL; |
8952 switch (GetElementsKind()) { | 8964 switch (GetElementsKind()) { |
8953 case NON_STRICT_ARGUMENTS_ELEMENTS: | 8965 case NON_STRICT_ARGUMENTS_ELEMENTS: |
8954 backing_store = FixedArray::cast(backing_store->get(1)); | 8966 backing_store_base = |
| 8967 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 8968 backing_store = FixedArray::cast(backing_store_base); |
8955 if (backing_store->IsDictionary()) { | 8969 if (backing_store->IsDictionary()) { |
8956 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 8970 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
8957 capacity = dictionary->Capacity(); | 8971 capacity = dictionary->Capacity(); |
8958 number_of_elements = dictionary->NumberOfElements(); | 8972 number_of_elements = dictionary->NumberOfElements(); |
8959 break; | 8973 break; |
8960 } | 8974 } |
8961 // Fall through. | 8975 // Fall through. |
8962 case FAST_ELEMENTS: | 8976 case FAST_ELEMENTS: |
| 8977 backing_store = FixedArray::cast(backing_store_base); |
8963 capacity = backing_store->length(); | 8978 capacity = backing_store->length(); |
8964 for (int i = 0; i < capacity; ++i) { | 8979 for (int i = 0; i < capacity; ++i) { |
8965 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements; | 8980 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements; |
8966 } | 8981 } |
8967 break; | 8982 break; |
8968 case DICTIONARY_ELEMENTS: { | 8983 case DICTIONARY_ELEMENTS: { |
8969 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 8984 NumberDictionary* dictionary = |
| 8985 NumberDictionary::cast(FixedArray::cast(elements())); |
8970 capacity = dictionary->Capacity(); | 8986 capacity = dictionary->Capacity(); |
8971 number_of_elements = dictionary->NumberOfElements(); | 8987 number_of_elements = dictionary->NumberOfElements(); |
8972 break; | 8988 break; |
8973 } | 8989 } |
8974 case FAST_DOUBLE_ELEMENTS: { | 8990 case FAST_DOUBLE_ELEMENTS: { |
8975 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 8991 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
8976 capacity = elms->length(); | 8992 capacity = elms->length(); |
8977 for (int i = 0; i < capacity; i++) { | 8993 for (int i = 0; i < capacity; i++) { |
8978 if (!elms->is_the_hole(i)) number_of_elements++; | 8994 if (!elms->is_the_hole(i)) number_of_elements++; |
8979 } | 8995 } |
(...skipping 2709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11689 if (break_point_objects()->IsUndefined()) return 0; | 11705 if (break_point_objects()->IsUndefined()) return 0; |
11690 // Single beak point. | 11706 // Single beak point. |
11691 if (!break_point_objects()->IsFixedArray()) return 1; | 11707 if (!break_point_objects()->IsFixedArray()) return 1; |
11692 // Multiple break points. | 11708 // Multiple break points. |
11693 return FixedArray::cast(break_point_objects())->length(); | 11709 return FixedArray::cast(break_point_objects())->length(); |
11694 } | 11710 } |
11695 #endif | 11711 #endif |
11696 | 11712 |
11697 | 11713 |
11698 } } // namespace v8::internal | 11714 } } // namespace v8::internal |
OLD | NEW |