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 |