| 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 |