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