OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 2398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 HValue* checked_object, | 2409 HValue* checked_object, |
2410 HValue* key, | 2410 HValue* key, |
2411 HValue* val, | 2411 HValue* val, |
2412 bool is_js_array, | 2412 bool is_js_array, |
2413 ElementsKind elements_kind, | 2413 ElementsKind elements_kind, |
2414 PropertyAccessType access_type, | 2414 PropertyAccessType access_type, |
2415 LoadKeyedHoleMode load_mode, | 2415 LoadKeyedHoleMode load_mode, |
2416 KeyedAccessStoreMode store_mode) { | 2416 KeyedAccessStoreMode store_mode) { |
2417 DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() || | 2417 DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() || |
2418 checked_object->IsCheckMaps()); | 2418 checked_object->IsCheckMaps()); |
2419 DCHECK((!IsExternalArrayElementsKind(elements_kind) && | 2419 DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array); |
2420 !IsFixedTypedArrayElementsKind(elements_kind)) || | |
2421 !is_js_array); | |
2422 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 2420 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
2423 // on a HElementsTransition instruction. The flag can also be removed if the | 2421 // on a HElementsTransition instruction. The flag can also be removed if the |
2424 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 2422 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
2425 // ElementsKind transitions. Finally, the dependency can be removed for stores | 2423 // ElementsKind transitions. Finally, the dependency can be removed for stores |
2426 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 2424 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
2427 // generated store code. | 2425 // generated store code. |
2428 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 2426 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
2429 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { | 2427 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { |
2430 checked_object->ClearDependsOnFlag(kElementsKind); | 2428 checked_object->ClearDependsOnFlag(kElementsKind); |
2431 } | 2429 } |
(...skipping 10 matching lines...) Expand all Loading... |
2442 HInstruction* length = NULL; | 2440 HInstruction* length = NULL; |
2443 if (is_js_array) { | 2441 if (is_js_array) { |
2444 length = Add<HLoadNamedField>( | 2442 length = Add<HLoadNamedField>( |
2445 checked_object->ActualValue(), checked_object, | 2443 checked_object->ActualValue(), checked_object, |
2446 HObjectAccess::ForArrayLength(elements_kind)); | 2444 HObjectAccess::ForArrayLength(elements_kind)); |
2447 } else { | 2445 } else { |
2448 length = AddLoadFixedArrayLength(elements); | 2446 length = AddLoadFixedArrayLength(elements); |
2449 } | 2447 } |
2450 length->set_type(HType::Smi()); | 2448 length->set_type(HType::Smi()); |
2451 HValue* checked_key = NULL; | 2449 HValue* checked_key = NULL; |
2452 if (IsExternalArrayElementsKind(elements_kind) || | 2450 if (IsFixedTypedArrayElementsKind(elements_kind)) { |
2453 IsFixedTypedArrayElementsKind(elements_kind)) { | |
2454 checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object); | 2451 checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object); |
2455 | 2452 |
2456 HValue* backing_store; | 2453 HValue* external_pointer = Add<HLoadNamedField>( |
2457 if (IsExternalArrayElementsKind(elements_kind)) { | 2454 elements, nullptr, |
2458 backing_store = Add<HLoadNamedField>( | 2455 HObjectAccess::ForFixedTypedArrayBaseExternalPointer()); |
2459 elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); | 2456 HValue* base_pointer = Add<HLoadNamedField>( |
2460 } else { | 2457 elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer()); |
2461 HValue* external_pointer = Add<HLoadNamedField>( | 2458 HValue* backing_store = AddUncasted<HAdd>( |
2462 elements, nullptr, | 2459 external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged); |
2463 HObjectAccess::ForFixedTypedArrayBaseExternalPointer()); | 2460 |
2464 HValue* base_pointer = Add<HLoadNamedField>( | |
2465 elements, nullptr, | |
2466 HObjectAccess::ForFixedTypedArrayBaseBasePointer()); | |
2467 backing_store = AddUncasted<HAdd>(external_pointer, base_pointer, | |
2468 Strength::WEAK, AddOfExternalAndTagged); | |
2469 } | |
2470 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2461 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
2471 NoObservableSideEffectsScope no_effects(this); | 2462 NoObservableSideEffectsScope no_effects(this); |
2472 IfBuilder length_checker(this); | 2463 IfBuilder length_checker(this); |
2473 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2464 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
2474 length_checker.Then(); | 2465 length_checker.Then(); |
2475 IfBuilder negative_checker(this); | 2466 IfBuilder negative_checker(this); |
2476 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2467 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
2477 key, graph()->GetConstant0(), Token::GTE); | 2468 key, graph()->GetConstant0(), Token::GTE); |
2478 negative_checker.Then(); | 2469 negative_checker.Then(); |
2479 HInstruction* result = AddElementAccess( | 2470 HInstruction* result = AddElementAccess( |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2691 HInstruction* HGraphBuilder::AddElementAccess( | 2682 HInstruction* HGraphBuilder::AddElementAccess( |
2692 HValue* elements, | 2683 HValue* elements, |
2693 HValue* checked_key, | 2684 HValue* checked_key, |
2694 HValue* val, | 2685 HValue* val, |
2695 HValue* dependency, | 2686 HValue* dependency, |
2696 ElementsKind elements_kind, | 2687 ElementsKind elements_kind, |
2697 PropertyAccessType access_type, | 2688 PropertyAccessType access_type, |
2698 LoadKeyedHoleMode load_mode) { | 2689 LoadKeyedHoleMode load_mode) { |
2699 if (access_type == STORE) { | 2690 if (access_type == STORE) { |
2700 DCHECK(val != NULL); | 2691 DCHECK(val != NULL); |
2701 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || | 2692 if (elements_kind == UINT8_CLAMPED_ELEMENTS) { |
2702 elements_kind == UINT8_CLAMPED_ELEMENTS) { | |
2703 val = Add<HClampToUint8>(val); | 2693 val = Add<HClampToUint8>(val); |
2704 } | 2694 } |
2705 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, | 2695 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, |
2706 STORE_TO_INITIALIZED_ENTRY); | 2696 STORE_TO_INITIALIZED_ENTRY); |
2707 } | 2697 } |
2708 | 2698 |
2709 DCHECK(access_type == LOAD); | 2699 DCHECK(access_type == LOAD); |
2710 DCHECK(val == NULL); | 2700 DCHECK(val == NULL); |
2711 HLoadKeyed* load = Add<HLoadKeyed>( | 2701 HLoadKeyed* load = Add<HLoadKeyed>( |
2712 elements, checked_key, dependency, elements_kind, load_mode); | 2702 elements, checked_key, dependency, elements_kind, load_mode); |
2713 if (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2703 if (elements_kind == UINT32_ELEMENTS) { |
2714 elements_kind == UINT32_ELEMENTS) { | |
2715 graph()->RecordUint32Instruction(load); | 2704 graph()->RecordUint32Instruction(load); |
2716 } | 2705 } |
2717 return load; | 2706 return load; |
2718 } | 2707 } |
2719 | 2708 |
2720 | 2709 |
2721 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object, | 2710 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object, |
2722 HValue* dependency) { | 2711 HValue* dependency) { |
2723 return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap()); | 2712 return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap()); |
2724 } | 2713 } |
(...skipping 4681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7406 New<HCompareMap>(object, map, this_map, other_map); | 7395 New<HCompareMap>(object, map, this_map, other_map); |
7407 FinishCurrentBlock(mapcompare); | 7396 FinishCurrentBlock(mapcompare); |
7408 | 7397 |
7409 set_current_block(this_map); | 7398 set_current_block(this_map); |
7410 HInstruction* access = NULL; | 7399 HInstruction* access = NULL; |
7411 if (!CanInlineElementAccess(map)) { | 7400 if (!CanInlineElementAccess(map)) { |
7412 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, | 7401 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
7413 val)); | 7402 val)); |
7414 } else { | 7403 } else { |
7415 DCHECK(IsFastElementsKind(elements_kind) || | 7404 DCHECK(IsFastElementsKind(elements_kind) || |
7416 IsExternalArrayElementsKind(elements_kind) || | |
7417 IsFixedTypedArrayElementsKind(elements_kind)); | 7405 IsFixedTypedArrayElementsKind(elements_kind)); |
7418 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 7406 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
7419 // Happily, mapcompare is a checked object. | 7407 // Happily, mapcompare is a checked object. |
7420 access = BuildUncheckedMonomorphicElementAccess( | 7408 access = BuildUncheckedMonomorphicElementAccess( |
7421 mapcompare, key, val, | 7409 mapcompare, key, val, |
7422 map->instance_type() == JS_ARRAY_TYPE, | 7410 map->instance_type() == JS_ARRAY_TYPE, |
7423 elements_kind, access_type, | 7411 elements_kind, access_type, |
7424 load_mode, | 7412 load_mode, |
7425 store_mode); | 7413 store_mode); |
7426 } | 7414 } |
(...skipping 2514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9941 Handle<Map> map(fun->initial_map()); | 9929 Handle<Map> map(fun->initial_map()); |
9942 return Map::AsElementsKind(map, target_kind); | 9930 return Map::AsElementsKind(map, target_kind); |
9943 } | 9931 } |
9944 | 9932 |
9945 | 9933 |
9946 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements( | 9934 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements( |
9947 ExternalArrayType array_type, | 9935 ExternalArrayType array_type, |
9948 bool is_zero_byte_offset, | 9936 bool is_zero_byte_offset, |
9949 HValue* buffer, HValue* byte_offset, HValue* length) { | 9937 HValue* buffer, HValue* byte_offset, HValue* length) { |
9950 Handle<Map> external_array_map( | 9938 Handle<Map> external_array_map( |
9951 isolate()->heap()->MapForExternalArrayType(array_type)); | 9939 isolate()->heap()->MapForFixedTypedArray(array_type)); |
9952 | 9940 |
9953 // The HForceRepresentation is to prevent possible deopt on int-smi | 9941 // The HForceRepresentation is to prevent possible deopt on int-smi |
9954 // conversion after allocation but before the new object fields are set. | 9942 // conversion after allocation but before the new object fields are set. |
9955 length = AddUncasted<HForceRepresentation>(length, Representation::Smi()); | 9943 length = AddUncasted<HForceRepresentation>(length, Representation::Smi()); |
9956 HValue* elements = | 9944 HValue* elements = Add<HAllocate>( |
9957 Add<HAllocate>(Add<HConstant>(ExternalArray::kSize), HType::HeapObject(), | 9945 Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(), |
9958 NOT_TENURED, external_array_map->instance_type()); | 9946 NOT_TENURED, external_array_map->instance_type()); |
9959 | 9947 |
9960 AddStoreMapConstant(elements, external_array_map); | 9948 AddStoreMapConstant(elements, external_array_map); |
9961 Add<HStoreNamedField>(elements, | 9949 Add<HStoreNamedField>(elements, |
9962 HObjectAccess::ForFixedArrayLength(), length); | 9950 HObjectAccess::ForFixedArrayLength(), length); |
9963 | 9951 |
9964 HValue* backing_store = Add<HLoadNamedField>( | 9952 HValue* backing_store = Add<HLoadNamedField>( |
9965 buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore()); | 9953 buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore()); |
9966 | 9954 |
9967 HValue* typed_array_start; | 9955 HValue* typed_array_start; |
9968 if (is_zero_byte_offset) { | 9956 if (is_zero_byte_offset) { |
9969 typed_array_start = backing_store; | 9957 typed_array_start = backing_store; |
9970 } else { | 9958 } else { |
9971 HInstruction* external_pointer = | 9959 HInstruction* external_pointer = |
9972 AddUncasted<HAdd>(backing_store, byte_offset); | 9960 AddUncasted<HAdd>(backing_store, byte_offset); |
9973 // Arguments are checked prior to call to TypedArrayInitialize, | 9961 // Arguments are checked prior to call to TypedArrayInitialize, |
9974 // including byte_offset. | 9962 // including byte_offset. |
9975 external_pointer->ClearFlag(HValue::kCanOverflow); | 9963 external_pointer->ClearFlag(HValue::kCanOverflow); |
9976 typed_array_start = external_pointer; | 9964 typed_array_start = external_pointer; |
9977 } | 9965 } |
9978 | 9966 |
9979 Add<HStoreNamedField>(elements, | 9967 Add<HStoreNamedField>(elements, |
9980 HObjectAccess::ForExternalArrayExternalPointer(), | 9968 HObjectAccess::ForFixedTypedArrayBaseBasePointer(), |
9981 typed_array_start); | 9969 graph()->GetConstant0()); |
| 9970 Add<HStoreNamedField>(elements, |
| 9971 HObjectAccess::ForFixedTypedArrayBaseExternalPointer(), |
| 9972 typed_array_start); |
9982 | 9973 |
9983 return elements; | 9974 return elements; |
9984 } | 9975 } |
9985 | 9976 |
9986 | 9977 |
9987 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray( | 9978 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray( |
9988 ExternalArrayType array_type, size_t element_size, | 9979 ExternalArrayType array_type, size_t element_size, |
9989 ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length, | 9980 ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length, |
9990 bool initialize) { | 9981 bool initialize) { |
9991 STATIC_ASSERT( | 9982 STATIC_ASSERT( |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10118 IfBuilder byte_offset_smi(this); | 10109 IfBuilder byte_offset_smi(this); |
10119 | 10110 |
10120 if (!is_zero_byte_offset) { | 10111 if (!is_zero_byte_offset) { |
10121 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); | 10112 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); |
10122 byte_offset_smi.Then(); | 10113 byte_offset_smi.Then(); |
10123 } | 10114 } |
10124 | 10115 |
10125 ExternalArrayType array_type = | 10116 ExternalArrayType array_type = |
10126 kExternalInt8Array; // Bogus initialization. | 10117 kExternalInt8Array; // Bogus initialization. |
10127 size_t element_size = 1; // Bogus initialization. | 10118 size_t element_size = 1; // Bogus initialization. |
10128 ElementsKind external_elements_kind = // Bogus initialization. | |
10129 EXTERNAL_INT8_ELEMENTS; | |
10130 ElementsKind fixed_elements_kind = // Bogus initialization. | 10119 ElementsKind fixed_elements_kind = // Bogus initialization. |
10131 INT8_ELEMENTS; | 10120 INT8_ELEMENTS; |
10132 Runtime::ArrayIdToTypeAndSize(array_id, | 10121 Runtime::ArrayIdToTypeAndSize(array_id, |
10133 &array_type, | 10122 &array_type, |
10134 &external_elements_kind, | |
10135 &fixed_elements_kind, | 10123 &fixed_elements_kind, |
10136 &element_size); | 10124 &element_size); |
10137 | 10125 |
10138 | 10126 |
10139 { // byte_offset is Smi. | 10127 { // byte_offset is Smi. |
10140 HValue* allocated_buffer = buffer; | 10128 HValue* allocated_buffer = buffer; |
10141 if (buffer == NULL) { | 10129 if (buffer == NULL) { |
10142 allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length); | 10130 allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length); |
10143 } | 10131 } |
10144 BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer, | 10132 BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer, |
10145 byte_offset, byte_length); | 10133 byte_offset, byte_length); |
10146 | 10134 |
10147 | 10135 |
10148 HInstruction* length = AddUncasted<HDiv>(byte_length, | 10136 HInstruction* length = AddUncasted<HDiv>(byte_length, |
10149 Add<HConstant>(static_cast<int32_t>(element_size))); | 10137 Add<HConstant>(static_cast<int32_t>(element_size))); |
10150 | 10138 |
10151 Add<HStoreNamedField>(obj, | 10139 Add<HStoreNamedField>(obj, |
10152 HObjectAccess::ForJSTypedArrayLength(), | 10140 HObjectAccess::ForJSTypedArrayLength(), |
10153 length); | 10141 length); |
10154 | 10142 |
10155 HValue* elements; | 10143 HValue* elements; |
10156 if (buffer != NULL) { | 10144 if (buffer != NULL) { |
10157 elements = BuildAllocateExternalElements( | 10145 elements = BuildAllocateExternalElements( |
10158 array_type, is_zero_byte_offset, buffer, byte_offset, length); | 10146 array_type, is_zero_byte_offset, buffer, byte_offset, length); |
10159 Handle<Map> obj_map = TypedArrayMap( | 10147 Handle<Map> obj_map = |
10160 isolate(), array_type, external_elements_kind); | 10148 TypedArrayMap(isolate(), array_type, fixed_elements_kind); |
10161 AddStoreMapConstant(obj, obj_map); | 10149 AddStoreMapConstant(obj, obj_map); |
10162 } else { | 10150 } else { |
10163 DCHECK(is_zero_byte_offset); | 10151 DCHECK(is_zero_byte_offset); |
10164 elements = BuildAllocateFixedTypedArray(array_type, element_size, | 10152 elements = BuildAllocateFixedTypedArray(array_type, element_size, |
10165 fixed_elements_kind, byte_length, | 10153 fixed_elements_kind, byte_length, |
10166 length, initialize); | 10154 length, initialize); |
10167 } | 10155 } |
10168 Add<HStoreNamedField>( | 10156 Add<HStoreNamedField>( |
10169 obj, HObjectAccess::ForElementsPointer(), elements); | 10157 obj, HObjectAccess::ForElementsPointer(), elements); |
10170 } | 10158 } |
(...skipping 3164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13335 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13323 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13336 } | 13324 } |
13337 | 13325 |
13338 #ifdef DEBUG | 13326 #ifdef DEBUG |
13339 graph_->Verify(false); // No full verify. | 13327 graph_->Verify(false); // No full verify. |
13340 #endif | 13328 #endif |
13341 } | 13329 } |
13342 | 13330 |
13343 } // namespace internal | 13331 } // namespace internal |
13344 } // namespace v8 | 13332 } // namespace v8 |
OLD | NEW |