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