| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| 11 namespace internal { | 11 namespace internal { |
| 12 | 12 |
| 13 using compiler::Node; |
| 14 |
| 15 class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler { |
| 16 public: |
| 17 explicit SharedArrayBufferBuiltinsAssembler( |
| 18 compiler::CodeAssemblerState* state) |
| 19 : CodeStubAssembler(state) {} |
| 20 |
| 21 protected: |
| 22 void ValidateSharedTypedArray(Node* tagged, Node* context, |
| 23 Node** out_instance_type, |
| 24 Node** out_backing_store); |
| 25 Node* ConvertTaggedAtomicIndexToWord32(Node* tagged, Node* context, |
| 26 Node** number_index); |
| 27 void ValidateAtomicIndex(Node* index_word, Node* array_length_word, |
| 28 Node* context); |
| 29 }; |
| 30 |
| 13 // ES7 sharedmem 6.3.4.1 get SharedArrayBuffer.prototype.byteLength | 31 // ES7 sharedmem 6.3.4.1 get SharedArrayBuffer.prototype.byteLength |
| 14 BUILTIN(SharedArrayBufferPrototypeGetByteLength) { | 32 BUILTIN(SharedArrayBufferPrototypeGetByteLength) { |
| 15 HandleScope scope(isolate); | 33 HandleScope scope(isolate); |
| 16 CHECK_RECEIVER(JSArrayBuffer, array_buffer, | 34 CHECK_RECEIVER(JSArrayBuffer, array_buffer, |
| 17 "get SharedArrayBuffer.prototype.byteLength"); | 35 "get SharedArrayBuffer.prototype.byteLength"); |
| 18 if (!array_buffer->is_shared()) { | 36 if (!array_buffer->is_shared()) { |
| 19 THROW_NEW_ERROR_RETURN_FAILURE( | 37 THROW_NEW_ERROR_RETURN_FAILURE( |
| 20 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | 38 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, |
| 21 isolate->factory()->NewStringFromAsciiChecked( | 39 isolate->factory()->NewStringFromAsciiChecked( |
| 22 "get SharedArrayBuffer.prototype.byteLength"), | 40 "get SharedArrayBuffer.prototype.byteLength"), |
| 23 args.receiver())); | 41 args.receiver())); |
| 24 } | 42 } |
| 25 return array_buffer->byte_length(); | 43 return array_buffer->byte_length(); |
| 26 } | 44 } |
| 27 | 45 |
| 28 namespace { | 46 void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray( |
| 29 | 47 Node* tagged, Node* context, Node** out_instance_type, |
| 30 void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged, | 48 Node** out_backing_store) { |
| 31 compiler::Node* context, | 49 Label not_float_or_clamped(this), invalid(this); |
| 32 compiler::Node** out_instance_type, | |
| 33 compiler::Node** out_backing_store) { | |
| 34 using compiler::Node; | |
| 35 CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a), | |
| 36 not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a), | |
| 37 not_float_or_clamped(a), invalid(a); | |
| 38 | 50 |
| 39 // Fail if it is not a heap object. | 51 // Fail if it is not a heap object. |
| 40 a->Branch(a->TaggedIsSmi(tagged), &is_smi, ¬_smi); | 52 GotoIf(TaggedIsSmi(tagged), &invalid); |
| 41 a->Bind(&is_smi); | |
| 42 a->Goto(&invalid); | |
| 43 | 53 |
| 44 // Fail if the array's instance type is not JSTypedArray. | 54 // Fail if the array's instance type is not JSTypedArray. |
| 45 a->Bind(¬_smi); | 55 GotoIf(Word32NotEqual(LoadInstanceType(tagged), |
| 46 a->Branch(a->Word32Equal(a->LoadInstanceType(tagged), | 56 Int32Constant(JS_TYPED_ARRAY_TYPE)), |
| 47 a->Int32Constant(JS_TYPED_ARRAY_TYPE)), | 57 &invalid); |
| 48 &is_typed_array, ¬_typed_array); | |
| 49 a->Bind(¬_typed_array); | |
| 50 a->Goto(&invalid); | |
| 51 | 58 |
| 52 // Fail if the array's JSArrayBuffer is not shared. | 59 // Fail if the array's JSArrayBuffer is not shared. |
| 53 a->Bind(&is_typed_array); | 60 Node* array_buffer = LoadObjectField(tagged, JSTypedArray::kBufferOffset); |
| 54 Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset); | 61 Node* bitfield = LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldOffset, |
| 55 Node* is_buffer_shared = | 62 MachineType::Uint32()); |
| 56 a->IsSetWord32<JSArrayBuffer::IsShared>(a->LoadObjectField( | 63 GotoIfNot(IsSetWord32<JSArrayBuffer::IsShared>(bitfield), &invalid); |
| 57 array_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32())); | |
| 58 a->Branch(is_buffer_shared, &is_shared, ¬_shared); | |
| 59 a->Bind(¬_shared); | |
| 60 a->Goto(&invalid); | |
| 61 | 64 |
| 62 // Fail if the array's element type is float32, float64 or clamped. | 65 // Fail if the array's element type is float32, float64 or clamped. |
| 63 a->Bind(&is_shared); | 66 Node* elements_instance_type = |
| 64 Node* elements_instance_type = a->LoadInstanceType( | 67 LoadInstanceType(LoadObjectField(tagged, JSObject::kElementsOffset)); |
| 65 a->LoadObjectField(tagged, JSObject::kElementsOffset)); | |
| 66 STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 68 STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 67 STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 69 STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 68 STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 70 STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 69 STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 71 STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 70 STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 72 STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 71 STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); | 73 STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE); |
| 72 a->Branch(a->Int32LessThan(elements_instance_type, | 74 Branch(Int32LessThan(elements_instance_type, |
| 73 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)), | 75 Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)), |
| 74 ¬_float_or_clamped, &is_float_or_clamped); | 76 ¬_float_or_clamped, &invalid); |
| 75 a->Bind(&is_float_or_clamped); | 77 |
| 76 a->Goto(&invalid); | 78 Bind(&invalid); |
| 77 | 79 { |
| 78 a->Bind(&invalid); | 80 CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context, |
| 79 a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context, | 81 tagged); |
| 80 tagged); | 82 Unreachable(); |
| 81 a->Unreachable(); | 83 } |
| 82 | 84 |
| 83 a->Bind(¬_float_or_clamped); | 85 Bind(¬_float_or_clamped); |
| 84 *out_instance_type = elements_instance_type; | 86 *out_instance_type = elements_instance_type; |
| 85 | 87 |
| 86 Node* backing_store = | 88 Node* backing_store = |
| 87 a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset); | 89 LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset); |
| 88 Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32( | 90 Node* byte_offset = ChangeUint32ToWord(TruncateTaggedToWord32( |
| 89 context, | 91 context, LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset))); |
| 90 a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset))); | |
| 91 *out_backing_store = | 92 *out_backing_store = |
| 92 a->IntPtrAdd(a->BitcastTaggedToWord(backing_store), byte_offset); | 93 IntPtrAdd(BitcastTaggedToWord(backing_store), byte_offset); |
| 93 } | 94 } |
| 94 | 95 |
| 95 // https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomic
Access | 96 // https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomic
Access |
| 96 compiler::Node* ConvertTaggedAtomicIndexToWord32( | 97 Node* SharedArrayBufferBuiltinsAssembler::ConvertTaggedAtomicIndexToWord32( |
| 97 CodeStubAssembler* a, compiler::Node* tagged, compiler::Node* context, | 98 Node* tagged, Node* context, Node** number_index) { |
| 98 compiler::Node** number_index) { | 99 Variable var_result(this, MachineRepresentation::kWord32); |
| 99 using compiler::Node; | 100 |
| 100 CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32); | 101 // TODO(jkummerow): Skip ToNumber call when |tagged| is a number already. |
| 101 | 102 // Maybe this can be unified with other tagged-to-index conversions? |
| 102 Callable to_number = CodeFactory::ToNumber(a->isolate()); | 103 // Why does this return an int32, and not an intptr? |
| 103 *number_index = a->CallStub(to_number, context, tagged); | 104 // Why is there the additional |number_index| output parameter? |
| 104 CodeStubAssembler::Label done(a, &var_result); | 105 Callable to_number = CodeFactory::ToNumber(isolate()); |
| 105 | 106 *number_index = CallStub(to_number, context, tagged); |
| 106 CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a); | 107 Label done(this, &var_result); |
| 107 a->Branch(a->TaggedIsSmi(*number_index), &if_numberissmi, &if_numberisnotsmi); | 108 |
| 108 | 109 Label if_numberissmi(this), if_numberisnotsmi(this); |
| 109 a->Bind(&if_numberissmi); | 110 Branch(TaggedIsSmi(*number_index), &if_numberissmi, &if_numberisnotsmi); |
| 111 |
| 112 Bind(&if_numberissmi); |
| 110 { | 113 { |
| 111 var_result.Bind(a->SmiToWord32(*number_index)); | 114 var_result.Bind(SmiToWord32(*number_index)); |
| 112 a->Goto(&done); | 115 Goto(&done); |
| 113 } | 116 } |
| 114 | 117 |
| 115 a->Bind(&if_numberisnotsmi); | 118 Bind(&if_numberisnotsmi); |
| 116 { | 119 { |
| 117 Node* number_index_value = a->LoadHeapNumberValue(*number_index); | 120 Node* number_index_value = LoadHeapNumberValue(*number_index); |
| 118 Node* access_index = a->TruncateFloat64ToWord32(number_index_value); | 121 Node* access_index = TruncateFloat64ToWord32(number_index_value); |
| 119 Node* test_index = a->ChangeInt32ToFloat64(access_index); | 122 Node* test_index = ChangeInt32ToFloat64(access_index); |
| 120 | 123 |
| 121 CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a); | 124 Label if_indexesareequal(this), if_indexesarenotequal(this); |
| 122 a->Branch(a->Float64Equal(number_index_value, test_index), | 125 Branch(Float64Equal(number_index_value, test_index), &if_indexesareequal, |
| 123 &if_indexesareequal, &if_indexesarenotequal); | 126 &if_indexesarenotequal); |
| 124 | 127 |
| 125 a->Bind(&if_indexesareequal); | 128 Bind(&if_indexesareequal); |
| 126 { | 129 { |
| 127 var_result.Bind(access_index); | 130 var_result.Bind(access_index); |
| 128 a->Goto(&done); | 131 Goto(&done); |
| 129 } | 132 } |
| 130 | 133 |
| 131 a->Bind(&if_indexesarenotequal); | 134 Bind(&if_indexesarenotequal); |
| 132 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); | 135 { |
| 133 a->Unreachable(); | 136 CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); |
| 137 Unreachable(); |
| 138 } |
| 134 } | 139 } |
| 135 | 140 |
| 136 a->Bind(&done); | 141 Bind(&done); |
| 137 return var_result.value(); | 142 return var_result.value(); |
| 138 } | 143 } |
| 139 | 144 |
| 140 void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word, | 145 void SharedArrayBufferBuiltinsAssembler::ValidateAtomicIndex( |
| 141 compiler::Node* array_length_word, | 146 Node* index_word, Node* array_length_word, Node* context) { |
| 142 compiler::Node* context) { | |
| 143 using compiler::Node; | |
| 144 // Check if the index is in bounds. If not, throw RangeError. | 147 // Check if the index is in bounds. If not, throw RangeError. |
| 145 CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a); | 148 Label check_passed(this); |
| 146 // TODO(jkummerow): Use unsigned comparison instead of "i<0 || i>length". | 149 GotoIf(Uint32LessThan(index_word, array_length_word), &check_passed); |
| 147 a->Branch( | 150 |
| 148 a->Word32Or(a->Int32LessThan(index_word, a->Int32Constant(0)), | 151 CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); |
| 149 a->Int32GreaterThanOrEqual(index_word, array_length_word)), | 152 Unreachable(); |
| 150 &if_notinbounds, &if_inbounds); | 153 |
| 151 a->Bind(&if_notinbounds); | 154 Bind(&check_passed); |
| 152 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context); | 155 } |
| 153 a->Unreachable(); | 156 |
| 154 a->Bind(&if_inbounds); | 157 TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) { |
| 155 } | 158 Node* array = Parameter(1); |
| 156 | 159 Node* index = Parameter(2); |
| 157 } // anonymous namespace | 160 Node* context = Parameter(3 + 2); |
| 158 | |
| 159 void Builtins::Generate_AtomicsLoad(compiler::CodeAssemblerState* state) { | |
| 160 using compiler::Node; | |
| 161 CodeStubAssembler a(state); | |
| 162 Node* array = a.Parameter(1); | |
| 163 Node* index = a.Parameter(2); | |
| 164 Node* context = a.Parameter(3 + 2); | |
| 165 | 161 |
| 166 Node* instance_type; | 162 Node* instance_type; |
| 167 Node* backing_store; | 163 Node* backing_store; |
| 168 ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store); | 164 ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
| 169 | 165 |
| 170 Node* index_integer; | 166 Node* index_integer; |
| 171 Node* index_word32 = | 167 Node* index_word32 = |
| 172 ConvertTaggedAtomicIndexToWord32(&a, index, context, &index_integer); | 168 ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
| 173 Node* array_length_word32 = a.TruncateTaggedToWord32( | 169 Node* array_length_word32 = TruncateTaggedToWord32( |
| 174 context, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); | 170 context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
| 175 ValidateAtomicIndex(&a, index_word32, array_length_word32, context); | 171 ValidateAtomicIndex(index_word32, array_length_word32, context); |
| 176 Node* index_word = a.ChangeUint32ToWord(index_word32); | 172 Node* index_word = ChangeUint32ToWord(index_word32); |
| 177 | 173 |
| 178 CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a), | 174 Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), |
| 179 other(&a); | 175 other(this); |
| 180 int32_t case_values[] = { | 176 int32_t case_values[] = { |
| 181 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, | 177 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, |
| 182 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, | 178 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, |
| 183 }; | 179 }; |
| 184 CodeStubAssembler::Label* case_labels[] = { | 180 Label* case_labels[] = { |
| 185 &i8, &u8, &i16, &u16, &i32, &u32, | 181 &i8, &u8, &i16, &u16, &i32, &u32, |
| 186 }; | 182 }; |
| 187 a.Switch(instance_type, &other, case_values, case_labels, | 183 Switch(instance_type, &other, case_values, case_labels, |
| 188 arraysize(case_labels)); | 184 arraysize(case_labels)); |
| 189 | 185 |
| 190 a.Bind(&i8); | 186 Bind(&i8); |
| 191 a.Return(a.SmiFromWord32( | 187 Return(SmiFromWord32( |
| 192 a.AtomicLoad(MachineType::Int8(), backing_store, index_word))); | 188 AtomicLoad(MachineType::Int8(), backing_store, index_word))); |
| 193 | 189 |
| 194 a.Bind(&u8); | 190 Bind(&u8); |
| 195 a.Return(a.SmiFromWord32( | 191 Return(SmiFromWord32( |
| 196 a.AtomicLoad(MachineType::Uint8(), backing_store, index_word))); | 192 AtomicLoad(MachineType::Uint8(), backing_store, index_word))); |
| 197 | 193 |
| 198 a.Bind(&i16); | 194 Bind(&i16); |
| 199 a.Return(a.SmiFromWord32(a.AtomicLoad(MachineType::Int16(), backing_store, | 195 Return(SmiFromWord32( |
| 200 a.WordShl(index_word, 1)))); | 196 AtomicLoad(MachineType::Int16(), backing_store, WordShl(index_word, 1)))); |
| 201 | 197 |
| 202 a.Bind(&u16); | 198 Bind(&u16); |
| 203 a.Return(a.SmiFromWord32(a.AtomicLoad(MachineType::Uint16(), backing_store, | 199 Return(SmiFromWord32(AtomicLoad(MachineType::Uint16(), backing_store, |
| 204 a.WordShl(index_word, 1)))); | 200 WordShl(index_word, 1)))); |
| 205 | 201 |
| 206 a.Bind(&i32); | 202 Bind(&i32); |
| 207 a.Return(a.ChangeInt32ToTagged(a.AtomicLoad( | 203 Return(ChangeInt32ToTagged( |
| 208 MachineType::Int32(), backing_store, a.WordShl(index_word, 2)))); | 204 AtomicLoad(MachineType::Int32(), backing_store, WordShl(index_word, 2)))); |
| 209 | 205 |
| 210 a.Bind(&u32); | 206 Bind(&u32); |
| 211 a.Return(a.ChangeUint32ToTagged(a.AtomicLoad( | 207 Return(ChangeUint32ToTagged(AtomicLoad(MachineType::Uint32(), backing_store, |
| 212 MachineType::Uint32(), backing_store, a.WordShl(index_word, 2)))); | 208 WordShl(index_word, 2)))); |
| 213 | 209 |
| 214 // This shouldn't happen, we've already validated the type. | 210 // This shouldn't happen, we've already validated the type. |
| 215 a.Bind(&other); | 211 Bind(&other); |
| 216 a.Return(a.SmiConstant(0)); | 212 Unreachable(); |
| 217 } | 213 } |
| 218 | 214 |
| 219 void Builtins::Generate_AtomicsStore(compiler::CodeAssemblerState* state) { | 215 TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) { |
| 220 using compiler::Node; | 216 Node* array = Parameter(1); |
| 221 CodeStubAssembler a(state); | 217 Node* index = Parameter(2); |
| 222 Node* array = a.Parameter(1); | 218 Node* value = Parameter(3); |
| 223 Node* index = a.Parameter(2); | 219 Node* context = Parameter(4 + 2); |
| 224 Node* value = a.Parameter(3); | |
| 225 Node* context = a.Parameter(4 + 2); | |
| 226 | 220 |
| 227 Node* instance_type; | 221 Node* instance_type; |
| 228 Node* backing_store; | 222 Node* backing_store; |
| 229 ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store); | 223 ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
| 230 | 224 |
| 231 Node* index_integer; | 225 Node* index_integer; |
| 232 Node* index_word32 = | 226 Node* index_word32 = |
| 233 ConvertTaggedAtomicIndexToWord32(&a, index, context, &index_integer); | 227 ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
| 234 Node* array_length_word32 = a.TruncateTaggedToWord32( | 228 Node* array_length_word32 = TruncateTaggedToWord32( |
| 235 context, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); | 229 context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
| 236 ValidateAtomicIndex(&a, index_word32, array_length_word32, context); | 230 ValidateAtomicIndex(index_word32, array_length_word32, context); |
| 237 Node* index_word = a.ChangeUint32ToWord(index_word32); | 231 Node* index_word = ChangeUint32ToWord(index_word32); |
| 238 | 232 |
| 239 Node* value_integer = a.ToInteger(context, value); | 233 Node* value_integer = ToInteger(context, value); |
| 240 Node* value_word32 = a.TruncateTaggedToWord32(context, value_integer); | 234 Node* value_word32 = TruncateTaggedToWord32(context, value_integer); |
| 241 | 235 |
| 242 CodeStubAssembler::Label u8(&a), u16(&a), u32(&a), other(&a); | 236 Label u8(this), u16(this), u32(this), other(this); |
| 243 int32_t case_values[] = { | 237 int32_t case_values[] = { |
| 244 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, | 238 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, |
| 245 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, | 239 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, |
| 246 }; | 240 }; |
| 247 CodeStubAssembler::Label* case_labels[] = { | 241 Label* case_labels[] = { |
| 248 &u8, &u8, &u16, &u16, &u32, &u32, | 242 &u8, &u8, &u16, &u16, &u32, &u32, |
| 249 }; | 243 }; |
| 250 a.Switch(instance_type, &other, case_values, case_labels, | 244 Switch(instance_type, &other, case_values, case_labels, |
| 251 arraysize(case_labels)); | 245 arraysize(case_labels)); |
| 252 | 246 |
| 253 a.Bind(&u8); | 247 Bind(&u8); |
| 254 a.AtomicStore(MachineRepresentation::kWord8, backing_store, index_word, | 248 AtomicStore(MachineRepresentation::kWord8, backing_store, index_word, |
| 255 value_word32); | 249 value_word32); |
| 256 a.Return(value_integer); | 250 Return(value_integer); |
| 257 | 251 |
| 258 a.Bind(&u16); | 252 Bind(&u16); |
| 259 a.AtomicStore(MachineRepresentation::kWord16, backing_store, | 253 AtomicStore(MachineRepresentation::kWord16, backing_store, |
| 260 a.WordShl(index_word, 1), value_word32); | 254 WordShl(index_word, 1), value_word32); |
| 261 a.Return(value_integer); | 255 Return(value_integer); |
| 262 | 256 |
| 263 a.Bind(&u32); | 257 Bind(&u32); |
| 264 a.AtomicStore(MachineRepresentation::kWord32, backing_store, | 258 AtomicStore(MachineRepresentation::kWord32, backing_store, |
| 265 a.WordShl(index_word, 2), value_word32); | 259 WordShl(index_word, 2), value_word32); |
| 266 a.Return(value_integer); | 260 Return(value_integer); |
| 267 | 261 |
| 268 // This shouldn't happen, we've already validated the type. | 262 // This shouldn't happen, we've already validated the type. |
| 269 a.Bind(&other); | 263 Bind(&other); |
| 270 a.Return(a.SmiConstant(0)); | 264 Unreachable(); |
| 271 } | 265 } |
| 272 | 266 |
| 273 void Builtins::Generate_AtomicsExchange(compiler::CodeAssemblerState* state) { | 267 TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) { |
| 274 using compiler::Node; | 268 Node* array = Parameter(1); |
| 275 CodeStubAssembler a(state); | 269 Node* index = Parameter(2); |
| 276 Node* array = a.Parameter(1); | 270 Node* value = Parameter(3); |
| 277 Node* index = a.Parameter(2); | 271 Node* context = Parameter(4 + 2); |
| 278 Node* value = a.Parameter(3); | |
| 279 Node* context = a.Parameter(4 + 2); | |
| 280 | 272 |
| 281 Node* instance_type; | 273 Node* instance_type; |
| 282 Node* backing_store; | 274 Node* backing_store; |
| 283 ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store); | 275 ValidateSharedTypedArray(array, context, &instance_type, &backing_store); |
| 284 | 276 |
| 285 Node* index_integer; | 277 Node* index_integer; |
| 286 Node* index_word32 = | 278 Node* index_word32 = |
| 287 ConvertTaggedAtomicIndexToWord32(&a, index, context, &index_integer); | 279 ConvertTaggedAtomicIndexToWord32(index, context, &index_integer); |
| 288 Node* array_length_word32 = a.TruncateTaggedToWord32( | 280 Node* array_length_word32 = TruncateTaggedToWord32( |
| 289 context, a.LoadObjectField(array, JSTypedArray::kLengthOffset)); | 281 context, LoadObjectField(array, JSTypedArray::kLengthOffset)); |
| 290 ValidateAtomicIndex(&a, index_word32, array_length_word32, context); | 282 ValidateAtomicIndex(index_word32, array_length_word32, context); |
| 291 | 283 |
| 292 Node* value_integer = a.ToInteger(context, value); | 284 Node* value_integer = ToInteger(context, value); |
| 293 | 285 |
| 294 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ | 286 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \ |
| 295 V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X | 287 V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X |
| 296 // Node* index_integer = a.ToInteger(context, index); | 288 Return(CallRuntime(Runtime::kAtomicsExchange, context, array, index_integer, |
| 297 a.Return(a.CallRuntime(Runtime::kAtomicsExchange, context, array, | 289 value_integer)); |
| 298 index_integer, value_integer)); | |
| 299 #else | 290 #else |
| 300 Node* index_word = a.ChangeUint32ToWord(index_word32); | 291 Node* index_word = ChangeUint32ToWord(index_word32); |
| 301 | 292 |
| 302 Node* value_word32 = a.TruncateTaggedToWord32(context, value_integer); | 293 Node* value_word32 = TruncateTaggedToWord32(context, value_integer); |
| 303 | 294 |
| 304 CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a), | 295 Label i8(this), u8(this), i16(this), u16(this), i32(this), u32(this), |
| 305 other(&a); | 296 other(this); |
| 306 int32_t case_values[] = { | 297 int32_t case_values[] = { |
| 307 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, | 298 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, |
| 308 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, | 299 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE, |
| 309 }; | 300 }; |
| 310 CodeStubAssembler::Label* case_labels[] = { | 301 Label* case_labels[] = { |
| 311 &i8, &u8, &i16, &u16, &i32, &u32, | 302 &i8, &u8, &i16, &u16, &i32, &u32, |
| 312 }; | 303 }; |
| 313 a.Switch(instance_type, &other, case_values, case_labels, | 304 Switch(instance_type, &other, case_values, case_labels, |
| 314 arraysize(case_labels)); | 305 arraysize(case_labels)); |
| 315 | 306 |
| 316 a.Bind(&i8); | 307 Bind(&i8); |
| 317 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Int8(), backing_store, | 308 Return(SmiFromWord32(AtomicExchange(MachineType::Int8(), backing_store, |
| 318 index_word, value_word32))); | 309 index_word, value_word32))); |
| 319 | 310 |
| 320 a.Bind(&u8); | 311 Bind(&u8); |
| 321 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Uint8(), backing_store, | 312 Return(SmiFromWord32(AtomicExchange(MachineType::Uint8(), backing_store, |
| 322 index_word, value_word32))); | 313 index_word, value_word32))); |
| 323 | 314 |
| 324 a.Bind(&i16); | 315 Bind(&i16); |
| 325 a.Return(a.SmiFromWord32(a.AtomicExchange(MachineType::Int16(), backing_store, | 316 Return(SmiFromWord32(AtomicExchange(MachineType::Int16(), backing_store, |
| 326 a.WordShl(index_word, 1), | 317 WordShl(index_word, 1), value_word32))); |
| 318 |
| 319 Bind(&u16); |
| 320 Return(SmiFromWord32(AtomicExchange(MachineType::Uint16(), backing_store, |
| 321 WordShl(index_word, 1), value_word32))); |
| 322 |
| 323 Bind(&i32); |
| 324 Return(ChangeInt32ToTagged(AtomicExchange(MachineType::Int32(), backing_store, |
| 325 WordShl(index_word, 2), |
| 327 value_word32))); | 326 value_word32))); |
| 328 | 327 |
| 329 a.Bind(&u16); | 328 Bind(&u32); |
| 330 a.Return(a.SmiFromWord32( | 329 Return(ChangeUint32ToTagged( |
| 331 a.AtomicExchange(MachineType::Uint16(), backing_store, | 330 AtomicExchange(MachineType::Uint32(), backing_store, |
| 332 a.WordShl(index_word, 1), value_word32))); | 331 WordShl(index_word, 2), value_word32))); |
| 333 | |
| 334 a.Bind(&i32); | |
| 335 a.Return(a.ChangeInt32ToTagged( | |
| 336 a.AtomicExchange(MachineType::Int32(), backing_store, | |
| 337 a.WordShl(index_word, 2), value_word32))); | |
| 338 | |
| 339 a.Bind(&u32); | |
| 340 a.Return(a.ChangeUint32ToTagged( | |
| 341 a.AtomicExchange(MachineType::Uint32(), backing_store, | |
| 342 a.WordShl(index_word, 2), value_word32))); | |
| 343 | 332 |
| 344 // This shouldn't happen, we've already validated the type. | 333 // This shouldn't happen, we've already validated the type. |
| 345 a.Bind(&other); | 334 Bind(&other); |
| 346 a.Return(a.SmiConstant(0)); | 335 Unreachable(); |
| 347 #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 | 336 #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 |
| 348 // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X | 337 // || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X |
| 349 } | 338 } |
| 350 | 339 |
| 351 } // namespace internal | 340 } // namespace internal |
| 352 } // namespace v8 | 341 } // namespace v8 |
| OLD | NEW |