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.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/contexts.h" | 10 #include "src/contexts.h" |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 | 181 |
182 if (JSArray::HasReadOnlyLength(array)) { | 182 if (JSArray::HasReadOnlyLength(array)) { |
183 return CallJsIntrinsic(isolate, isolate->array_push(), args); | 183 return CallJsIntrinsic(isolate, isolate->array_push(), args); |
184 } | 184 } |
185 | 185 |
186 ElementsAccessor* accessor = array->GetElementsAccessor(); | 186 ElementsAccessor* accessor = array->GetElementsAccessor(); |
187 int new_length = accessor->Push(array, &args, to_add); | 187 int new_length = accessor->Push(array, &args, to_add); |
188 return Smi::FromInt(new_length); | 188 return Smi::FromInt(new_length); |
189 } | 189 } |
190 | 190 |
191 void Builtins::Generate_FastArrayPush(compiler::CodeAssemblerState* state) { | 191 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
192 typedef compiler::Node Node; | 192 Variable arg_index(this, MachineType::PointerRepresentation()); |
193 typedef CodeStubAssembler::Label Label; | 193 Label default_label(this, &arg_index); |
194 typedef CodeStubAssembler::Variable Variable; | 194 Label smi_transition(this); |
195 CodeStubAssembler assembler(state); | 195 Label object_push_pre(this); |
196 Variable arg_index(&assembler, MachineType::PointerRepresentation()); | 196 Label object_push(this, &arg_index); |
197 Label default_label(&assembler, &arg_index); | 197 Label double_push(this, &arg_index); |
198 Label smi_transition(&assembler); | 198 Label double_transition(this); |
199 Label object_push_pre(&assembler); | 199 Label runtime(this, Label::kDeferred); |
200 Label object_push(&assembler, &arg_index); | |
201 Label double_push(&assembler, &arg_index); | |
202 Label double_transition(&assembler); | |
203 Label runtime(&assembler, Label::kDeferred); | |
204 | 200 |
205 Node* argc = assembler.Parameter(BuiltinDescriptor::kArgumentsCount); | 201 Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount); |
206 Node* context = assembler.Parameter(BuiltinDescriptor::kContext); | 202 Node* context = Parameter(BuiltinDescriptor::kContext); |
207 Node* new_target = assembler.Parameter(BuiltinDescriptor::kNewTarget); | 203 Node* new_target = Parameter(BuiltinDescriptor::kNewTarget); |
208 | 204 |
209 CodeStubArguments args(&assembler, assembler.ChangeInt32ToIntPtr(argc)); | 205 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); |
210 Node* receiver = args.GetReceiver(); | 206 Node* receiver = args.GetReceiver(); |
211 Node* kind = nullptr; | 207 Node* kind = nullptr; |
212 | 208 |
213 Label fast(&assembler); | 209 Label fast(this); |
214 { | 210 BranchIfFastJSArray(receiver, context, FastJSArrayAccessMode::ANY_ACCESS, |
215 assembler.BranchIfFastJSArray( | 211 &fast, &runtime); |
216 receiver, context, CodeStubAssembler::FastJSArrayAccessMode::ANY_ACCESS, | |
217 &fast, &runtime); | |
218 } | |
219 | 212 |
220 assembler.Bind(&fast); | 213 Bind(&fast); |
221 { | 214 { |
222 // Disallow pushing onto prototypes. It might be the JSArray prototype. | 215 // Disallow pushing onto prototypes. It might be the JSArray prototype. |
223 // Disallow pushing onto non-extensible objects. | 216 // Disallow pushing onto non-extensible objects. |
224 assembler.Comment("Disallow pushing onto prototypes"); | 217 Comment("Disallow pushing onto prototypes"); |
225 Node* map = assembler.LoadMap(receiver); | 218 Node* map = LoadMap(receiver); |
226 Node* bit_field2 = assembler.LoadMapBitField2(map); | 219 Node* bit_field2 = LoadMapBitField2(map); |
227 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | | 220 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | |
228 (1 << Map::kIsExtensible); | 221 (1 << Map::kIsExtensible); |
229 Node* test = assembler.Word32And(bit_field2, assembler.Int32Constant(mask)); | 222 Node* test = Word32And(bit_field2, Int32Constant(mask)); |
230 assembler.GotoIf( | 223 GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), |
231 assembler.Word32NotEqual( | 224 &runtime); |
232 test, assembler.Int32Constant(1 << Map::kIsExtensible)), | |
233 &runtime); | |
234 | 225 |
235 // Disallow pushing onto arrays in dictionary named property mode. We need | 226 // Disallow pushing onto arrays in dictionary named property mode. We need |
236 // to figure out whether the length property is still writable. | 227 // to figure out whether the length property is still writable. |
237 assembler.Comment( | 228 Comment("Disallow pushing onto arrays in dictionary named property mode"); |
238 "Disallow pushing onto arrays in dictionary named property mode"); | 229 GotoIf(IsDictionaryMap(map), &runtime); |
239 assembler.GotoIf(assembler.IsDictionaryMap(map), &runtime); | |
240 | 230 |
241 // Check whether the length property is writable. The length property is the | 231 // Check whether the length property is writable. The length property is the |
242 // only default named property on arrays. It's nonconfigurable, hence is | 232 // only default named property on arrays. It's nonconfigurable, hence is |
243 // guaranteed to stay the first property. | 233 // guaranteed to stay the first property. |
244 Node* descriptors = assembler.LoadMapDescriptors(map); | 234 Node* descriptors = LoadMapDescriptors(map); |
245 Node* details = assembler.LoadFixedArrayElement( | 235 Node* details = |
246 descriptors, DescriptorArray::ToDetailsIndex(0)); | 236 LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); |
247 assembler.GotoIf( | 237 GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), |
248 assembler.IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), | 238 &runtime); |
249 &runtime); | |
250 | 239 |
251 arg_index.Bind(assembler.IntPtrConstant(0)); | 240 arg_index.Bind(IntPtrConstant(0)); |
252 kind = assembler.DecodeWord32<Map::ElementsKindBits>(bit_field2); | 241 kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
253 | 242 |
254 assembler.GotoIf( | 243 GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), |
255 assembler.Int32GreaterThan( | 244 &object_push_pre); |
256 kind, assembler.Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), | |
257 &object_push_pre); | |
258 | 245 |
259 Node* new_length = assembler.BuildAppendJSArray( | 246 Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, context, receiver, |
260 FAST_SMI_ELEMENTS, context, receiver, args, arg_index, &smi_transition); | 247 args, arg_index, &smi_transition); |
261 args.PopAndReturn(new_length); | 248 args.PopAndReturn(new_length); |
262 } | 249 } |
263 | 250 |
264 // If the argument is not a smi, then use a heavyweight SetProperty to | 251 // If the argument is not a smi, then use a heavyweight SetProperty to |
265 // transition the array for only the single next element. If the argument is | 252 // transition the array for only the single next element. If the argument is |
266 // a smi, the failure is due to some other reason and we should fall back on | 253 // a smi, the failure is due to some other reason and we should fall back on |
267 // the most generic implementation for the rest of the array. | 254 // the most generic implementation for the rest of the array. |
268 assembler.Bind(&smi_transition); | 255 Bind(&smi_transition); |
269 { | 256 { |
270 Node* arg = args.AtIndex(arg_index.value()); | 257 Node* arg = args.AtIndex(arg_index.value()); |
271 assembler.GotoIf(assembler.TaggedIsSmi(arg), &default_label); | 258 GotoIf(TaggedIsSmi(arg), &default_label); |
272 Node* length = assembler.LoadJSArrayLength(receiver); | 259 Node* length = LoadJSArrayLength(receiver); |
273 // TODO(danno): Use the KeyedStoreGeneric stub here when possible, | 260 // TODO(danno): Use the KeyedStoreGeneric stub here when possible, |
274 // calling into the runtime to do the elements transition is overkill. | 261 // calling into the runtime to do the elements transition is overkill. |
275 assembler.CallRuntime(Runtime::kSetProperty, context, receiver, length, arg, | 262 CallRuntime(Runtime::kSetProperty, context, receiver, length, arg, |
276 assembler.SmiConstant(STRICT)); | 263 SmiConstant(STRICT)); |
277 assembler.Increment(arg_index); | 264 Increment(arg_index); |
278 // The runtime SetProperty call could have converted the array to dictionary | 265 // The runtime SetProperty call could have converted the array to dictionary |
279 // mode, which must be detected to abort the fast-path. | 266 // mode, which must be detected to abort the fast-path. |
280 Node* map = assembler.LoadMap(receiver); | 267 Node* map = LoadMap(receiver); |
281 Node* bit_field2 = assembler.LoadMapBitField2(map); | 268 Node* bit_field2 = LoadMapBitField2(map); |
282 Node* kind = assembler.DecodeWord32<Map::ElementsKindBits>(bit_field2); | 269 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
283 assembler.GotoIf(assembler.Word32Equal( | 270 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), |
284 kind, assembler.Int32Constant(DICTIONARY_ELEMENTS)), | 271 &default_label); |
285 &default_label); | |
286 | 272 |
287 assembler.GotoIfNotNumber(arg, &object_push); | 273 GotoIfNotNumber(arg, &object_push); |
288 assembler.Goto(&double_push); | 274 Goto(&double_push); |
289 } | 275 } |
290 | 276 |
291 assembler.Bind(&object_push_pre); | 277 Bind(&object_push_pre); |
292 { | 278 { |
293 assembler.Branch(assembler.Int32GreaterThan( | 279 Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
294 kind, assembler.Int32Constant(FAST_HOLEY_ELEMENTS)), | 280 &double_push, &object_push); |
295 &double_push, &object_push); | |
296 } | 281 } |
297 | 282 |
298 assembler.Bind(&object_push); | 283 Bind(&object_push); |
299 { | 284 { |
300 Node* new_length = assembler.BuildAppendJSArray( | 285 Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, context, receiver, |
301 FAST_ELEMENTS, context, receiver, args, arg_index, &default_label); | 286 args, arg_index, &default_label); |
302 args.PopAndReturn(new_length); | 287 args.PopAndReturn(new_length); |
303 } | 288 } |
304 | 289 |
305 assembler.Bind(&double_push); | 290 Bind(&double_push); |
306 { | 291 { |
307 Node* new_length = | 292 Node* new_length = |
308 assembler.BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, | 293 BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, args, |
309 args, arg_index, &double_transition); | 294 arg_index, &double_transition); |
310 args.PopAndReturn(new_length); | 295 args.PopAndReturn(new_length); |
311 } | 296 } |
312 | 297 |
313 // If the argument is not a double, then use a heavyweight SetProperty to | 298 // If the argument is not a double, then use a heavyweight SetProperty to |
314 // transition the array for only the single next element. If the argument is | 299 // transition the array for only the single next element. If the argument is |
315 // a double, the failure is due to some other reason and we should fall back | 300 // a double, the failure is due to some other reason and we should fall back |
316 // on the most generic implementation for the rest of the array. | 301 // on the most generic implementation for the rest of the array. |
317 assembler.Bind(&double_transition); | 302 Bind(&double_transition); |
318 { | 303 { |
319 Node* arg = args.AtIndex(arg_index.value()); | 304 Node* arg = args.AtIndex(arg_index.value()); |
320 assembler.GotoIfNumber(arg, &default_label); | 305 GotoIfNumber(arg, &default_label); |
321 Node* length = assembler.LoadJSArrayLength(receiver); | 306 Node* length = LoadJSArrayLength(receiver); |
322 // TODO(danno): Use the KeyedStoreGeneric stub here when possible, | 307 // TODO(danno): Use the KeyedStoreGeneric stub here when possible, |
323 // calling into the runtime to do the elements transition is overkill. | 308 // calling into the runtime to do the elements transition is overkill. |
324 assembler.CallRuntime(Runtime::kSetProperty, context, receiver, length, arg, | 309 CallRuntime(Runtime::kSetProperty, context, receiver, length, arg, |
325 assembler.SmiConstant(STRICT)); | 310 SmiConstant(STRICT)); |
326 assembler.Increment(arg_index); | 311 Increment(arg_index); |
327 // The runtime SetProperty call could have converted the array to dictionary | 312 // The runtime SetProperty call could have converted the array to dictionary |
328 // mode, which must be detected to abort the fast-path. | 313 // mode, which must be detected to abort the fast-path. |
329 Node* map = assembler.LoadMap(receiver); | 314 Node* map = LoadMap(receiver); |
330 Node* bit_field2 = assembler.LoadMapBitField2(map); | 315 Node* bit_field2 = LoadMapBitField2(map); |
331 Node* kind = assembler.DecodeWord32<Map::ElementsKindBits>(bit_field2); | 316 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
332 assembler.GotoIf(assembler.Word32Equal( | 317 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)), |
333 kind, assembler.Int32Constant(DICTIONARY_ELEMENTS)), | 318 &default_label); |
334 &default_label); | 319 Goto(&object_push); |
335 assembler.Goto(&object_push); | |
336 } | 320 } |
337 | 321 |
338 // Fallback that stores un-processed arguments using the full, heavyweight | 322 // Fallback that stores un-processed arguments using the full, heavyweight |
339 // SetProperty machinery. | 323 // SetProperty machinery. |
340 assembler.Bind(&default_label); | 324 Bind(&default_label); |
341 { | 325 { |
342 args.ForEach( | 326 args.ForEach( |
343 [&assembler, receiver, context](Node* arg) { | 327 [this, receiver, context](Node* arg) { |
344 Node* length = assembler.LoadJSArrayLength(receiver); | 328 Node* length = LoadJSArrayLength(receiver); |
345 assembler.CallRuntime(Runtime::kSetProperty, context, receiver, | 329 CallRuntime(Runtime::kSetProperty, context, receiver, length, arg, |
346 length, arg, assembler.SmiConstant(STRICT)); | 330 SmiConstant(STRICT)); |
347 }, | 331 }, |
348 arg_index.value()); | 332 arg_index.value()); |
349 args.PopAndReturn(assembler.LoadJSArrayLength(receiver)); | 333 args.PopAndReturn(LoadJSArrayLength(receiver)); |
350 } | 334 } |
351 | 335 |
352 assembler.Bind(&runtime); | 336 Bind(&runtime); |
353 { | 337 { |
354 Node* target = assembler.LoadFromFrame( | 338 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset, |
355 StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer()); | 339 MachineType::TaggedPointer()); |
356 assembler.TailCallStub(CodeFactory::ArrayPush(assembler.isolate()), context, | 340 TailCallStub(CodeFactory::ArrayPush(isolate()), context, target, new_target, |
357 target, new_target, argc); | 341 argc); |
358 } | 342 } |
359 } | 343 } |
360 | 344 |
361 BUILTIN(ArrayPop) { | 345 BUILTIN(ArrayPop) { |
362 HandleScope scope(isolate); | 346 HandleScope scope(isolate); |
363 Handle<Object> receiver = args.receiver(); | 347 Handle<Object> receiver = args.receiver(); |
364 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) { | 348 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) { |
365 return CallJsIntrinsic(isolate, isolate->array_pop(), args); | 349 return CallJsIntrinsic(isolate, isolate->array_pop(), args); |
366 } | 350 } |
367 | 351 |
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); | 1622 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); |
1639 if (*species == *isolate->array_function()) { | 1623 if (*species == *isolate->array_function()) { |
1640 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { | 1624 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { |
1641 return *result_array; | 1625 return *result_array; |
1642 } | 1626 } |
1643 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 1627 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
1644 } | 1628 } |
1645 return Slow_ArrayConcat(&args, species, isolate); | 1629 return Slow_ArrayConcat(&args, species, isolate); |
1646 } | 1630 } |
1647 | 1631 |
1648 void Builtins::Generate_ArrayIsArray(compiler::CodeAssemblerState* state) { | 1632 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
1649 typedef compiler::Node Node; | 1633 Node* object = Parameter(1); |
1650 typedef CodeStubAssembler::Label Label; | 1634 Node* context = Parameter(4); |
1651 CodeStubAssembler assembler(state); | |
1652 | 1635 |
1653 Node* object = assembler.Parameter(1); | 1636 Label call_runtime(this), return_true(this), return_false(this); |
1654 Node* context = assembler.Parameter(4); | |
1655 | 1637 |
1656 Label call_runtime(&assembler), return_true(&assembler), | 1638 GotoIf(TaggedIsSmi(object), &return_false); |
1657 return_false(&assembler); | 1639 Node* instance_type = LoadInstanceType(object); |
1658 | 1640 |
1659 assembler.GotoIf(assembler.TaggedIsSmi(object), &return_false); | 1641 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), |
1660 Node* instance_type = assembler.LoadInstanceType(object); | 1642 &return_true); |
1661 | |
1662 assembler.GotoIf(assembler.Word32Equal( | |
1663 instance_type, assembler.Int32Constant(JS_ARRAY_TYPE)), | |
1664 &return_true); | |
1665 | 1643 |
1666 // TODO(verwaest): Handle proxies in-place. | 1644 // TODO(verwaest): Handle proxies in-place. |
1667 assembler.Branch(assembler.Word32Equal( | 1645 Branch(Word32Equal(instance_type, Int32Constant(JS_PROXY_TYPE)), |
1668 instance_type, assembler.Int32Constant(JS_PROXY_TYPE)), | 1646 &call_runtime, &return_false); |
1669 &call_runtime, &return_false); | |
1670 | 1647 |
1671 assembler.Bind(&return_true); | 1648 Bind(&return_true); |
1672 assembler.Return(assembler.BooleanConstant(true)); | 1649 Return(BooleanConstant(true)); |
1673 | 1650 |
1674 assembler.Bind(&return_false); | 1651 Bind(&return_false); |
1675 assembler.Return(assembler.BooleanConstant(false)); | 1652 Return(BooleanConstant(false)); |
1676 | 1653 |
1677 assembler.Bind(&call_runtime); | 1654 Bind(&call_runtime); |
1678 assembler.Return( | 1655 Return(CallRuntime(Runtime::kArrayIsArray, context, object)); |
1679 assembler.CallRuntime(Runtime::kArrayIsArray, context, object)); | |
1680 } | 1656 } |
1681 | 1657 |
1682 TF_BUILTIN(ArrayIncludes, CodeStubAssembler) { | 1658 TF_BUILTIN(ArrayIncludes, CodeStubAssembler) { |
1683 Node* const array = Parameter(0); | 1659 Node* const array = Parameter(0); |
1684 Node* const search_element = Parameter(1); | 1660 Node* const search_element = Parameter(1); |
1685 Node* const start_from = Parameter(2); | 1661 Node* const start_from = Parameter(2); |
1686 Node* const context = Parameter(3 + 2); | 1662 Node* const context = Parameter(3 + 2); |
1687 | 1663 |
1688 Variable index_var(this, MachineType::PointerRepresentation()); | 1664 Variable index_var(this, MachineType::PointerRepresentation()); |
1689 | 1665 |
1690 Label init_k(this), return_true(this), return_false(this), call_runtime(this); | 1666 Label init_k(this), return_true(this), return_false(this), call_runtime(this); |
1691 Label init_len(this), select_loop(this); | 1667 Label init_len(this), select_loop(this); |
1692 | 1668 |
1693 index_var.Bind(IntPtrConstant(0)); | 1669 index_var.Bind(IntPtrConstant(0)); |
1694 | 1670 |
1695 // Take slow path if not a JSArray, if retrieving elements requires | 1671 // Take slow path if not a JSArray, if retrieving elements requires |
1696 // traversing prototype, or if access checks are required. | 1672 // traversing prototype, or if access checks are required. |
1697 BranchIfFastJSArray(array, context, | 1673 BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, |
1698 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | |
1699 &init_len, &call_runtime); | 1674 &init_len, &call_runtime); |
1700 | 1675 |
1701 Bind(&init_len); | 1676 Bind(&init_len); |
1702 // JSArray length is always an Smi for fast arrays. | 1677 // JSArray length is always an Smi for fast arrays. |
1703 CSA_ASSERT(this, TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); | 1678 CSA_ASSERT(this, TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); |
1704 Node* const len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); | 1679 Node* const len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); |
1705 | 1680 |
1706 GotoIf(IsUndefined(start_from), &select_loop); | 1681 GotoIf(IsUndefined(start_from), &select_loop); |
1707 | 1682 |
1708 // Bailout to slow path if startIndex is not an Smi. | 1683 // Bailout to slow path if startIndex is not an Smi. |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 | 1885 |
1911 // Search for HeapNumber | 1886 // Search for HeapNumber |
1912 Bind(¬_nan_loop); | 1887 Bind(¬_nan_loop); |
1913 { | 1888 { |
1914 Label continue_loop(this); | 1889 Label continue_loop(this); |
1915 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); | 1890 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1916 | 1891 |
1917 // Load double value or continue if it contains a double hole. | 1892 // Load double value or continue if it contains a double hole. |
1918 Node* element_k = LoadFixedDoubleArrayElement( | 1893 Node* element_k = LoadFixedDoubleArrayElement( |
1919 elements, index_var.value(), MachineType::Float64(), 0, | 1894 elements, index_var.value(), MachineType::Float64(), 0, |
1920 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1895 INTPTR_PARAMETERS, &continue_loop); |
1921 | 1896 |
1922 Branch(Float64Equal(element_k, search_num.value()), &return_true, | 1897 Branch(Float64Equal(element_k, search_num.value()), &return_true, |
1923 &continue_loop); | 1898 &continue_loop); |
1924 Bind(&continue_loop); | 1899 Bind(&continue_loop); |
1925 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1900 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1926 Goto(¬_nan_loop); | 1901 Goto(¬_nan_loop); |
1927 } | 1902 } |
1928 | 1903 |
1929 // Search for NaN | 1904 // Search for NaN |
1930 Bind(&nan_loop); | 1905 Bind(&nan_loop); |
1931 { | 1906 { |
1932 Label continue_loop(this); | 1907 Label continue_loop(this); |
1933 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); | 1908 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1934 | 1909 |
1935 // Load double value or continue if it contains a double hole. | 1910 // Load double value or continue if it contains a double hole. |
1936 Node* element_k = LoadFixedDoubleArrayElement( | 1911 Node* element_k = LoadFixedDoubleArrayElement( |
1937 elements, index_var.value(), MachineType::Float64(), 0, | 1912 elements, index_var.value(), MachineType::Float64(), 0, |
1938 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1913 INTPTR_PARAMETERS, &continue_loop); |
1939 | 1914 |
1940 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); | 1915 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); |
1941 Bind(&continue_loop); | 1916 Bind(&continue_loop); |
1942 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1917 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1943 Goto(&nan_loop); | 1918 Goto(&nan_loop); |
1944 } | 1919 } |
1945 | 1920 |
1946 // Search for the Hole | 1921 // Search for the Hole |
1947 Bind(&hole_loop); | 1922 Bind(&hole_loop); |
1948 { | 1923 { |
1949 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); | 1924 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1950 | 1925 |
1951 // Check if the element is a double hole, but don't load it. | 1926 // Check if the element is a double hole, but don't load it. |
1952 LoadFixedDoubleArrayElement( | 1927 LoadFixedDoubleArrayElement(elements, index_var.value(), |
1953 elements, index_var.value(), MachineType::None(), 0, | 1928 MachineType::None(), 0, INTPTR_PARAMETERS, |
1954 CodeStubAssembler::INTPTR_PARAMETERS, &return_true); | 1929 &return_true); |
1955 | 1930 |
1956 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1931 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1957 Goto(&hole_loop); | 1932 Goto(&hole_loop); |
1958 } | 1933 } |
1959 } | 1934 } |
1960 | 1935 |
1961 Bind(&return_true); | 1936 Bind(&return_true); |
1962 Return(TrueConstant()); | 1937 Return(TrueConstant()); |
1963 | 1938 |
1964 Bind(&return_false); | 1939 Bind(&return_false); |
1965 Return(FalseConstant()); | 1940 Return(FalseConstant()); |
1966 | 1941 |
1967 Bind(&call_runtime); | 1942 Bind(&call_runtime); |
1968 Return(CallRuntime(Runtime::kArrayIncludes_Slow, context, array, | 1943 Return(CallRuntime(Runtime::kArrayIncludes_Slow, context, array, |
1969 search_element, start_from)); | 1944 search_element, start_from)); |
1970 } | 1945 } |
1971 | 1946 |
1972 void Builtins::Generate_ArrayIndexOf(compiler::CodeAssemblerState* state) { | 1947 TF_BUILTIN(ArrayIndexOf, CodeStubAssembler) { |
1973 typedef compiler::Node Node; | 1948 Node* array = Parameter(0); |
1974 typedef CodeStubAssembler::Label Label; | 1949 Node* search_element = Parameter(1); |
1975 typedef CodeStubAssembler::Variable Variable; | 1950 Node* start_from = Parameter(2); |
1976 CodeStubAssembler assembler(state); | 1951 Node* context = Parameter(3 + 2); |
1977 | 1952 |
1978 Node* array = assembler.Parameter(0); | 1953 Node* intptr_zero = IntPtrConstant(0); |
1979 Node* search_element = assembler.Parameter(1); | 1954 Node* intptr_one = IntPtrConstant(1); |
1980 Node* start_from = assembler.Parameter(2); | |
1981 Node* context = assembler.Parameter(3 + 2); | |
1982 | 1955 |
1983 Node* intptr_zero = assembler.IntPtrConstant(0); | 1956 Variable len_var(this, MachineType::PointerRepresentation()), |
1984 Node* intptr_one = assembler.IntPtrConstant(1); | 1957 index_var(this, MachineType::PointerRepresentation()), |
| 1958 start_from_var(this, MachineType::PointerRepresentation()); |
1985 | 1959 |
1986 Node* undefined = assembler.UndefinedConstant(); | 1960 Label init_k(this), return_found(this), return_not_found(this), |
| 1961 call_runtime(this); |
1987 | 1962 |
1988 Variable len_var(&assembler, MachineType::PointerRepresentation()), | 1963 Label init_len(this); |
1989 index_var(&assembler, MachineType::PointerRepresentation()), | |
1990 start_from_var(&assembler, MachineType::PointerRepresentation()); | |
1991 | |
1992 Label init_k(&assembler), return_found(&assembler), | |
1993 return_not_found(&assembler), call_runtime(&assembler); | |
1994 | |
1995 Label init_len(&assembler); | |
1996 | 1964 |
1997 index_var.Bind(intptr_zero); | 1965 index_var.Bind(intptr_zero); |
1998 len_var.Bind(intptr_zero); | 1966 len_var.Bind(intptr_zero); |
1999 | 1967 |
2000 // Take slow path if not a JSArray, if retrieving elements requires | 1968 // Take slow path if not a JSArray, if retrieving elements requires |
2001 // traversing prototype, or if access checks are required. | 1969 // traversing prototype, or if access checks are required. |
2002 assembler.BranchIfFastJSArray( | 1970 BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, |
2003 array, context, CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | 1971 &init_len, &call_runtime); |
2004 &init_len, &call_runtime); | |
2005 | 1972 |
2006 assembler.Bind(&init_len); | 1973 Bind(&init_len); |
2007 { | 1974 { |
2008 // JSArray length is always an Smi for fast arrays. | 1975 // JSArray length is always an Smi for fast arrays. |
2009 CSA_ASSERT(&assembler, assembler.TaggedIsSmi(assembler.LoadObjectField( | 1976 CSA_ASSERT(this, |
2010 array, JSArray::kLengthOffset))); | 1977 TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); |
2011 Node* len = | 1978 Node* len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); |
2012 assembler.LoadAndUntagObjectField(array, JSArray::kLengthOffset); | |
2013 | 1979 |
2014 len_var.Bind(len); | 1980 len_var.Bind(len); |
2015 assembler.Branch(assembler.WordEqual(len_var.value(), intptr_zero), | 1981 Branch(WordEqual(len_var.value(), intptr_zero), &return_not_found, &init_k); |
2016 &return_not_found, &init_k); | |
2017 } | 1982 } |
2018 | 1983 |
2019 assembler.Bind(&init_k); | 1984 Bind(&init_k); |
2020 { | 1985 { |
2021 Label done(&assembler), init_k_smi(&assembler), init_k_heap_num(&assembler), | 1986 Label done(this), init_k_smi(this), init_k_heap_num(this), |
2022 init_k_zero(&assembler), init_k_n(&assembler); | 1987 init_k_zero(this), init_k_n(this); |
2023 Node* tagged_n = assembler.ToInteger(context, start_from); | 1988 Node* tagged_n = ToInteger(context, start_from); |
2024 | 1989 |
2025 assembler.Branch(assembler.TaggedIsSmi(tagged_n), &init_k_smi, | 1990 Branch(TaggedIsSmi(tagged_n), &init_k_smi, &init_k_heap_num); |
2026 &init_k_heap_num); | |
2027 | 1991 |
2028 assembler.Bind(&init_k_smi); | 1992 Bind(&init_k_smi); |
2029 { | 1993 { |
2030 start_from_var.Bind(assembler.SmiUntag(tagged_n)); | 1994 start_from_var.Bind(SmiUntag(tagged_n)); |
2031 assembler.Goto(&init_k_n); | 1995 Goto(&init_k_n); |
2032 } | 1996 } |
2033 | 1997 |
2034 assembler.Bind(&init_k_heap_num); | 1998 Bind(&init_k_heap_num); |
2035 { | 1999 { |
2036 Label do_return_not_found(&assembler); | 2000 Label do_return_not_found(this); |
2037 // This round is lossless for all valid lengths. | 2001 // This round is lossless for all valid lengths. |
2038 Node* fp_len = assembler.RoundIntPtrToFloat64(len_var.value()); | 2002 Node* fp_len = RoundIntPtrToFloat64(len_var.value()); |
2039 Node* fp_n = assembler.LoadHeapNumberValue(tagged_n); | 2003 Node* fp_n = LoadHeapNumberValue(tagged_n); |
2040 assembler.GotoIf(assembler.Float64GreaterThanOrEqual(fp_n, fp_len), | 2004 GotoIf(Float64GreaterThanOrEqual(fp_n, fp_len), &do_return_not_found); |
2041 &do_return_not_found); | 2005 start_from_var.Bind(ChangeInt32ToIntPtr(TruncateFloat64ToWord32(fp_n))); |
2042 start_from_var.Bind(assembler.ChangeInt32ToIntPtr( | 2006 Goto(&init_k_n); |
2043 assembler.TruncateFloat64ToWord32(fp_n))); | |
2044 assembler.Goto(&init_k_n); | |
2045 | 2007 |
2046 assembler.Bind(&do_return_not_found); | 2008 Bind(&do_return_not_found); |
2047 { | 2009 { |
2048 index_var.Bind(intptr_zero); | 2010 index_var.Bind(intptr_zero); |
2049 assembler.Goto(&return_not_found); | 2011 Goto(&return_not_found); |
2050 } | 2012 } |
2051 } | 2013 } |
2052 | 2014 |
2053 assembler.Bind(&init_k_n); | 2015 Bind(&init_k_n); |
2054 { | 2016 { |
2055 Label if_positive(&assembler), if_negative(&assembler), done(&assembler); | 2017 Label if_positive(this), if_negative(this), done(this); |
2056 assembler.Branch( | 2018 Branch(IntPtrLessThan(start_from_var.value(), intptr_zero), &if_negative, |
2057 assembler.IntPtrLessThan(start_from_var.value(), intptr_zero), | 2019 &if_positive); |
2058 &if_negative, &if_positive); | |
2059 | 2020 |
2060 assembler.Bind(&if_positive); | 2021 Bind(&if_positive); |
2061 { | 2022 { |
2062 index_var.Bind(start_from_var.value()); | 2023 index_var.Bind(start_from_var.value()); |
2063 assembler.Goto(&done); | 2024 Goto(&done); |
2064 } | 2025 } |
2065 | 2026 |
2066 assembler.Bind(&if_negative); | 2027 Bind(&if_negative); |
2067 { | 2028 { |
2068 index_var.Bind( | 2029 index_var.Bind(IntPtrAdd(len_var.value(), start_from_var.value())); |
2069 assembler.IntPtrAdd(len_var.value(), start_from_var.value())); | 2030 Branch(IntPtrLessThan(index_var.value(), intptr_zero), &init_k_zero, |
2070 assembler.Branch( | 2031 &done); |
2071 assembler.IntPtrLessThan(index_var.value(), intptr_zero), | |
2072 &init_k_zero, &done); | |
2073 } | 2032 } |
2074 | 2033 |
2075 assembler.Bind(&init_k_zero); | 2034 Bind(&init_k_zero); |
2076 { | 2035 { |
2077 index_var.Bind(intptr_zero); | 2036 index_var.Bind(intptr_zero); |
2078 assembler.Goto(&done); | 2037 Goto(&done); |
2079 } | 2038 } |
2080 | 2039 |
2081 assembler.Bind(&done); | 2040 Bind(&done); |
2082 } | 2041 } |
2083 } | 2042 } |
2084 | 2043 |
2085 static int32_t kElementsKind[] = { | 2044 static int32_t kElementsKind[] = { |
2086 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 2045 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
2087 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, | 2046 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, |
2088 }; | 2047 }; |
2089 | 2048 |
2090 Label if_smiorobjects(&assembler), if_packed_doubles(&assembler), | 2049 Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this); |
2091 if_holey_doubles(&assembler); | |
2092 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, | 2050 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, |
2093 &if_smiorobjects, &if_smiorobjects, | 2051 &if_smiorobjects, &if_smiorobjects, |
2094 &if_packed_doubles, &if_holey_doubles}; | 2052 &if_packed_doubles, &if_holey_doubles}; |
2095 | 2053 |
2096 Node* map = assembler.LoadMap(array); | 2054 Node* map = LoadMap(array); |
2097 Node* elements_kind = assembler.LoadMapElementsKind(map); | 2055 Node* elements_kind = LoadMapElementsKind(map); |
2098 Node* elements = assembler.LoadElements(array); | 2056 Node* elements = LoadElements(array); |
2099 assembler.Switch(elements_kind, &return_not_found, kElementsKind, | 2057 Switch(elements_kind, &return_not_found, kElementsKind, element_kind_handlers, |
2100 element_kind_handlers, arraysize(kElementsKind)); | 2058 arraysize(kElementsKind)); |
2101 | 2059 |
2102 assembler.Bind(&if_smiorobjects); | 2060 Bind(&if_smiorobjects); |
2103 { | 2061 { |
2104 Variable search_num(&assembler, MachineRepresentation::kFloat64); | 2062 Variable search_num(this, MachineRepresentation::kFloat64); |
2105 Label ident_loop(&assembler, &index_var), | 2063 Label ident_loop(this, &index_var), heap_num_loop(this, &search_num), |
2106 heap_num_loop(&assembler, &search_num), | 2064 string_loop(this, &index_var), not_smi(this), not_heap_num(this); |
2107 string_loop(&assembler, &index_var), undef_loop(&assembler, &index_var), | 2065 |
2108 not_smi(&assembler), not_heap_num(&assembler); | 2066 GotoIfNot(TaggedIsSmi(search_element), ¬_smi); |
2109 | 2067 search_num.Bind(SmiToFloat64(search_element)); |
2110 assembler.GotoIfNot(assembler.TaggedIsSmi(search_element), ¬_smi); | 2068 Goto(&heap_num_loop); |
2111 search_num.Bind(assembler.SmiToFloat64(search_element)); | 2069 |
2112 assembler.Goto(&heap_num_loop); | 2070 Bind(¬_smi); |
2113 | 2071 Node* map = LoadMap(search_element); |
2114 assembler.Bind(¬_smi); | 2072 GotoIfNot(IsHeapNumberMap(map), ¬_heap_num); |
2115 assembler.GotoIf(assembler.WordEqual(search_element, undefined), | 2073 search_num.Bind(LoadHeapNumberValue(search_element)); |
2116 &undef_loop); | 2074 Goto(&heap_num_loop); |
2117 Node* map = assembler.LoadMap(search_element); | 2075 |
2118 assembler.GotoIfNot(assembler.IsHeapNumberMap(map), ¬_heap_num); | 2076 Bind(¬_heap_num); |
2119 search_num.Bind(assembler.LoadHeapNumberValue(search_element)); | 2077 Node* search_type = LoadMapInstanceType(map); |
2120 assembler.Goto(&heap_num_loop); | 2078 GotoIf(IsStringInstanceType(search_type), &string_loop); |
2121 | 2079 Goto(&ident_loop); |
2122 assembler.Bind(¬_heap_num); | 2080 |
2123 Node* search_type = assembler.LoadMapInstanceType(map); | 2081 Bind(&ident_loop); |
2124 assembler.GotoIf(assembler.IsStringInstanceType(search_type), &string_loop); | 2082 { |
2125 assembler.Goto(&ident_loop); | 2083 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), |
2126 | 2084 &return_not_found); |
2127 assembler.Bind(&ident_loop); | 2085 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
2128 { | 2086 GotoIf(WordEqual(element_k, search_element), &return_found); |
2129 assembler.GotoIfNot( | 2087 |
2130 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | 2088 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
2131 &return_not_found); | 2089 Goto(&ident_loop); |
2132 Node* element_k = | 2090 } |
2133 assembler.LoadFixedArrayElement(elements, index_var.value()); | 2091 |
2134 assembler.GotoIf(assembler.WordEqual(element_k, search_element), | 2092 Bind(&heap_num_loop); |
2135 &return_found); | 2093 { |
2136 | 2094 Label not_nan_loop(this, &index_var); |
2137 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | 2095 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, |
2138 assembler.Goto(&ident_loop); | 2096 ¬_nan_loop); |
2139 } | 2097 |
2140 | 2098 Bind(¬_nan_loop); |
2141 assembler.Bind(&undef_loop); | |
2142 { | |
2143 assembler.GotoIfNot( | |
2144 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | |
2145 &return_not_found); | |
2146 Node* element_k = | |
2147 assembler.LoadFixedArrayElement(elements, index_var.value()); | |
2148 assembler.GotoIf(assembler.WordEqual(element_k, undefined), | |
2149 &return_found); | |
2150 | |
2151 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | |
2152 assembler.Goto(&undef_loop); | |
2153 } | |
2154 | |
2155 assembler.Bind(&heap_num_loop); | |
2156 { | |
2157 Label not_nan_loop(&assembler, &index_var); | |
2158 assembler.BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
2159 ¬_nan_loop); | |
2160 | |
2161 assembler.Bind(¬_nan_loop); | |
2162 { | 2099 { |
2163 Label continue_loop(&assembler), not_smi(&assembler); | 2100 Label continue_loop(this), not_smi(this); |
2164 assembler.GotoIfNot( | 2101 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), |
2165 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | 2102 &return_not_found); |
2166 &return_not_found); | 2103 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
2167 Node* element_k = | 2104 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); |
2168 assembler.LoadFixedArrayElement(elements, index_var.value()); | 2105 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), |
2169 assembler.GotoIfNot(assembler.TaggedIsSmi(element_k), ¬_smi); | 2106 &return_found, &continue_loop); |
2170 assembler.Branch( | 2107 |
2171 assembler.Float64Equal(search_num.value(), | 2108 Bind(¬_smi); |
2172 assembler.SmiToFloat64(element_k)), | 2109 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
2173 &return_found, &continue_loop); | 2110 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), |
2174 | 2111 &return_found, &continue_loop); |
2175 assembler.Bind(¬_smi); | 2112 |
2176 assembler.GotoIfNot( | 2113 Bind(&continue_loop); |
2177 assembler.IsHeapNumberMap(assembler.LoadMap(element_k)), | 2114 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
2178 &continue_loop); | 2115 Goto(¬_nan_loop); |
2179 assembler.Branch( | |
2180 assembler.Float64Equal(search_num.value(), | |
2181 assembler.LoadHeapNumberValue(element_k)), | |
2182 &return_found, &continue_loop); | |
2183 | |
2184 assembler.Bind(&continue_loop); | |
2185 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | |
2186 assembler.Goto(¬_nan_loop); | |
2187 } | 2116 } |
2188 } | 2117 } |
2189 | 2118 |
2190 assembler.Bind(&string_loop); | 2119 Bind(&string_loop); |
2191 { | 2120 { |
2192 Label continue_loop(&assembler); | 2121 Label continue_loop(this); |
2193 assembler.GotoIfNot( | 2122 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), |
2194 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | 2123 &return_not_found); |
2195 &return_not_found); | 2124 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
2196 Node* element_k = | 2125 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
2197 assembler.LoadFixedArrayElement(elements, index_var.value()); | 2126 GotoIfNot(IsString(element_k), &continue_loop); |
2198 assembler.GotoIf(assembler.TaggedIsSmi(element_k), &continue_loop); | |
2199 assembler.GotoIfNot( | |
2200 assembler.IsStringInstanceType(assembler.LoadInstanceType(element_k)), | |
2201 &continue_loop); | |
2202 | 2127 |
2203 // TODO(bmeurer): Consider inlining the StringEqual logic here. | 2128 // TODO(bmeurer): Consider inlining the StringEqual logic here. |
2204 Callable callable = CodeFactory::StringEqual(assembler.isolate()); | 2129 Callable callable = CodeFactory::StringEqual(isolate()); |
2205 Node* result = | 2130 Node* result = CallStub(callable, context, search_element, element_k); |
2206 assembler.CallStub(callable, context, search_element, element_k); | 2131 Branch(WordEqual(BooleanConstant(true), result), &return_found, |
2207 assembler.Branch( | 2132 &continue_loop); |
2208 assembler.WordEqual(assembler.BooleanConstant(true), result), | 2133 |
2209 &return_found, &continue_loop); | 2134 Bind(&continue_loop); |
2210 | 2135 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
2211 assembler.Bind(&continue_loop); | 2136 Goto(&string_loop); |
2212 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | 2137 } |
2213 assembler.Goto(&string_loop); | 2138 } |
2214 } | 2139 |
2215 } | 2140 Bind(&if_packed_doubles); |
2216 | 2141 { |
2217 assembler.Bind(&if_packed_doubles); | 2142 Label not_nan_loop(this, &index_var), search_notnan(this); |
2218 { | 2143 Variable search_num(this, MachineRepresentation::kFloat64); |
2219 Label not_nan_loop(&assembler, &index_var), search_notnan(&assembler); | 2144 |
2220 Variable search_num(&assembler, MachineRepresentation::kFloat64); | 2145 GotoIfNot(TaggedIsSmi(search_element), &search_notnan); |
2221 | 2146 search_num.Bind(SmiToFloat64(search_element)); |
2222 assembler.GotoIfNot(assembler.TaggedIsSmi(search_element), &search_notnan); | 2147 Goto(¬_nan_loop); |
2223 search_num.Bind(assembler.SmiToFloat64(search_element)); | 2148 |
2224 assembler.Goto(¬_nan_loop); | 2149 Bind(&search_notnan); |
2225 | 2150 GotoIfNot(IsHeapNumber(search_element), &return_not_found); |
2226 assembler.Bind(&search_notnan); | 2151 |
2227 assembler.GotoIfNot( | 2152 search_num.Bind(LoadHeapNumberValue(search_element)); |
2228 assembler.IsHeapNumberMap(assembler.LoadMap(search_element)), | 2153 |
2229 &return_not_found); | 2154 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); |
2230 | |
2231 search_num.Bind(assembler.LoadHeapNumberValue(search_element)); | |
2232 | |
2233 assembler.BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
2234 ¬_nan_loop); | |
2235 | 2155 |
2236 // Search for HeapNumber | 2156 // Search for HeapNumber |
2237 assembler.Bind(¬_nan_loop); | 2157 Bind(¬_nan_loop); |
2238 { | 2158 { |
2239 Label continue_loop(&assembler); | 2159 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), |
2240 assembler.GotoIfNot( | 2160 &return_not_found); |
2241 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | 2161 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
2242 &return_not_found); | 2162 MachineType::Float64()); |
2243 Node* element_k = assembler.LoadFixedDoubleArrayElement( | 2163 GotoIf(Float64Equal(element_k, search_num.value()), &return_found); |
2244 elements, index_var.value(), MachineType::Float64()); | 2164 |
2245 assembler.Branch(assembler.Float64Equal(element_k, search_num.value()), | 2165 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
2246 &return_found, &continue_loop); | 2166 Goto(¬_nan_loop); |
2247 assembler.Bind(&continue_loop); | 2167 } |
2248 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | 2168 } |
2249 assembler.Goto(¬_nan_loop); | 2169 |
2250 } | 2170 Bind(&if_holey_doubles); |
2251 } | 2171 { |
2252 | 2172 Label not_nan_loop(this, &index_var), search_notnan(this); |
2253 assembler.Bind(&if_holey_doubles); | 2173 Variable search_num(this, MachineRepresentation::kFloat64); |
2254 { | 2174 |
2255 Label not_nan_loop(&assembler, &index_var), search_notnan(&assembler); | 2175 GotoIfNot(TaggedIsSmi(search_element), &search_notnan); |
2256 Variable search_num(&assembler, MachineRepresentation::kFloat64); | 2176 search_num.Bind(SmiToFloat64(search_element)); |
2257 | 2177 Goto(¬_nan_loop); |
2258 assembler.GotoIfNot(assembler.TaggedIsSmi(search_element), &search_notnan); | 2178 |
2259 search_num.Bind(assembler.SmiToFloat64(search_element)); | 2179 Bind(&search_notnan); |
2260 assembler.Goto(¬_nan_loop); | 2180 GotoIfNot(IsHeapNumber(search_element), &return_not_found); |
2261 | 2181 |
2262 assembler.Bind(&search_notnan); | 2182 search_num.Bind(LoadHeapNumberValue(search_element)); |
2263 assembler.GotoIfNot( | 2183 |
2264 assembler.IsHeapNumberMap(assembler.LoadMap(search_element)), | 2184 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); |
2265 &return_not_found); | |
2266 | |
2267 search_num.Bind(assembler.LoadHeapNumberValue(search_element)); | |
2268 | |
2269 assembler.BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
2270 ¬_nan_loop); | |
2271 | 2185 |
2272 // Search for HeapNumber | 2186 // Search for HeapNumber |
2273 assembler.Bind(¬_nan_loop); | 2187 Bind(¬_nan_loop); |
2274 { | 2188 { |
2275 Label continue_loop(&assembler); | 2189 Label continue_loop(this); |
2276 assembler.GotoIfNot( | 2190 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), |
2277 assembler.UintPtrLessThan(index_var.value(), len_var.value()), | 2191 &return_not_found); |
2278 &return_not_found); | |
2279 | 2192 |
2280 // Load double value or continue if it contains a double hole. | 2193 // Load double value or continue if it contains a double hole. |
2281 Node* element_k = assembler.LoadFixedDoubleArrayElement( | 2194 Node* element_k = LoadFixedDoubleArrayElement( |
2282 elements, index_var.value(), MachineType::Float64(), 0, | 2195 elements, index_var.value(), MachineType::Float64(), 0, |
2283 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 2196 INTPTR_PARAMETERS, &continue_loop); |
2284 | 2197 |
2285 assembler.Branch(assembler.Float64Equal(element_k, search_num.value()), | 2198 Branch(Float64Equal(element_k, search_num.value()), &return_found, |
2286 &return_found, &continue_loop); | 2199 &continue_loop); |
2287 assembler.Bind(&continue_loop); | 2200 Bind(&continue_loop); |
2288 index_var.Bind(assembler.IntPtrAdd(index_var.value(), intptr_one)); | 2201 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
2289 assembler.Goto(¬_nan_loop); | 2202 Goto(¬_nan_loop); |
2290 } | 2203 } |
2291 } | 2204 } |
2292 | 2205 |
2293 assembler.Bind(&return_found); | 2206 Bind(&return_found); |
2294 assembler.Return(assembler.SmiTag(index_var.value())); | 2207 Return(SmiTag(index_var.value())); |
2295 | 2208 |
2296 assembler.Bind(&return_not_found); | 2209 Bind(&return_not_found); |
2297 assembler.Return(assembler.NumberConstant(-1)); | 2210 Return(NumberConstant(-1)); |
2298 | 2211 |
2299 assembler.Bind(&call_runtime); | 2212 Bind(&call_runtime); |
2300 assembler.Return(assembler.CallRuntime(Runtime::kArrayIndexOf, context, array, | 2213 Return(CallRuntime(Runtime::kArrayIndexOf, context, array, search_element, |
2301 search_element, start_from)); | 2214 start_from)); |
2302 } | 2215 } |
2303 | 2216 |
2304 namespace { | 2217 class ArrayPrototypeIterationAssembler : public CodeStubAssembler { |
2305 | 2218 public: |
2306 template <IterationKind kIterationKind> | 2219 explicit ArrayPrototypeIterationAssembler(compiler::CodeAssemblerState* state) |
2307 void Generate_ArrayPrototypeIterationMethod( | 2220 : CodeStubAssembler(state) {} |
2308 compiler::CodeAssemblerState* state) { | 2221 |
2309 typedef compiler::Node Node; | 2222 protected: |
2310 typedef CodeStubAssembler::Label Label; | 2223 void Generate_ArrayPrototypeIterationMethod(IterationKind iteration_kind) { |
2311 typedef CodeStubAssembler::Variable Variable; | 2224 Node* receiver = Parameter(0); |
2312 CodeStubAssembler assembler(state); | 2225 Node* context = Parameter(3); |
2313 | 2226 |
2314 Node* receiver = assembler.Parameter(0); | 2227 Variable var_array(this, MachineRepresentation::kTagged); |
2315 Node* context = assembler.Parameter(3); | 2228 Variable var_map(this, MachineRepresentation::kTagged); |
2316 | 2229 Variable var_type(this, MachineRepresentation::kWord32); |
2317 Variable var_array(&assembler, MachineRepresentation::kTagged); | 2230 |
2318 Variable var_map(&assembler, MachineRepresentation::kTagged); | 2231 Label if_isnotobject(this, Label::kDeferred); |
2319 Variable var_type(&assembler, MachineRepresentation::kWord32); | 2232 Label create_array_iterator(this); |
2320 | 2233 |
2321 Label if_isnotobject(&assembler, Label::kDeferred); | 2234 GotoIf(TaggedIsSmi(receiver), &if_isnotobject); |
2322 Label create_array_iterator(&assembler); | 2235 var_array.Bind(receiver); |
2323 | 2236 var_map.Bind(LoadMap(receiver)); |
2324 assembler.GotoIf(assembler.TaggedIsSmi(receiver), &if_isnotobject); | 2237 var_type.Bind(LoadMapInstanceType(var_map.value())); |
2325 var_array.Bind(receiver); | 2238 Branch(IsJSReceiverInstanceType(var_type.value()), &create_array_iterator, |
2326 var_map.Bind(assembler.LoadMap(receiver)); | 2239 &if_isnotobject); |
2327 var_type.Bind(assembler.LoadMapInstanceType(var_map.value())); | 2240 |
2328 assembler.Branch(assembler.IsJSReceiverInstanceType(var_type.value()), | 2241 Bind(&if_isnotobject); |
2329 &create_array_iterator, &if_isnotobject); | 2242 { |
2330 | 2243 Callable callable = CodeFactory::ToObject(isolate()); |
2331 assembler.Bind(&if_isnotobject); | 2244 Node* result = CallStub(callable, context, receiver); |
2332 { | 2245 var_array.Bind(result); |
2333 Callable callable = CodeFactory::ToObject(assembler.isolate()); | 2246 var_map.Bind(LoadMap(result)); |
2334 Node* result = assembler.CallStub(callable, context, receiver); | 2247 var_type.Bind(LoadMapInstanceType(var_map.value())); |
2335 var_array.Bind(result); | 2248 Goto(&create_array_iterator); |
2336 var_map.Bind(assembler.LoadMap(result)); | 2249 } |
2337 var_type.Bind(assembler.LoadMapInstanceType(var_map.value())); | 2250 |
2338 assembler.Goto(&create_array_iterator); | 2251 Bind(&create_array_iterator); |
2339 } | 2252 Return(CreateArrayIterator(var_array.value(), var_map.value(), |
2340 | 2253 var_type.value(), context, iteration_kind)); |
2341 assembler.Bind(&create_array_iterator); | 2254 } |
2342 assembler.Return( | 2255 }; |
2343 assembler.CreateArrayIterator(var_array.value(), var_map.value(), | 2256 |
2344 var_type.value(), context, kIterationKind)); | 2257 TF_BUILTIN(ArrayPrototypeValues, ArrayPrototypeIterationAssembler) { |
2345 } | 2258 Generate_ArrayPrototypeIterationMethod(IterationKind::kValues); |
2346 | 2259 } |
2347 } // namespace | 2260 |
2348 | 2261 TF_BUILTIN(ArrayPrototypeEntries, ArrayPrototypeIterationAssembler) { |
2349 void Builtins::Generate_ArrayPrototypeValues( | 2262 Generate_ArrayPrototypeIterationMethod(IterationKind::kEntries); |
2350 compiler::CodeAssemblerState* state) { | 2263 } |
2351 Generate_ArrayPrototypeIterationMethod<IterationKind::kValues>(state); | 2264 |
2352 } | 2265 TF_BUILTIN(ArrayPrototypeKeys, ArrayPrototypeIterationAssembler) { |
2353 | 2266 Generate_ArrayPrototypeIterationMethod(IterationKind::kKeys); |
2354 void Builtins::Generate_ArrayPrototypeEntries( | 2267 } |
2355 compiler::CodeAssemblerState* state) { | 2268 |
2356 Generate_ArrayPrototypeIterationMethod<IterationKind::kEntries>(state); | 2269 TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { |
2357 } | 2270 Handle<String> operation = factory()->NewStringFromAsciiChecked( |
2358 | |
2359 void Builtins::Generate_ArrayPrototypeKeys( | |
2360 compiler::CodeAssemblerState* state) { | |
2361 Generate_ArrayPrototypeIterationMethod<IterationKind::kKeys>(state); | |
2362 } | |
2363 | |
2364 void Builtins::Generate_ArrayIteratorPrototypeNext( | |
2365 compiler::CodeAssemblerState* state) { | |
2366 typedef compiler::Node Node; | |
2367 typedef CodeStubAssembler::Label Label; | |
2368 typedef CodeStubAssembler::Variable Variable; | |
2369 CodeStubAssembler assembler(state); | |
2370 | |
2371 Handle<String> operation = assembler.factory()->NewStringFromAsciiChecked( | |
2372 "Array Iterator.prototype.next", TENURED); | 2271 "Array Iterator.prototype.next", TENURED); |
2373 | 2272 |
2374 Node* iterator = assembler.Parameter(0); | 2273 Node* iterator = Parameter(0); |
2375 Node* context = assembler.Parameter(3); | 2274 Node* context = Parameter(3); |
2376 | 2275 |
2377 Variable var_value(&assembler, MachineRepresentation::kTagged); | 2276 Variable var_value(this, MachineRepresentation::kTagged); |
2378 Variable var_done(&assembler, MachineRepresentation::kTagged); | 2277 Variable var_done(this, MachineRepresentation::kTagged); |
2379 | 2278 |
2380 // Required, or else `throw_bad_receiver` fails a DCHECK due to these | 2279 // Required, or else `throw_bad_receiver` fails a DCHECK due to these |
2381 // variables not being bound along all paths, despite not being used. | 2280 // variables not being bound along all paths, despite not being used. |
2382 var_done.Bind(assembler.TrueConstant()); | 2281 var_done.Bind(TrueConstant()); |
2383 var_value.Bind(assembler.UndefinedConstant()); | 2282 var_value.Bind(UndefinedConstant()); |
2384 | 2283 |
2385 Label throw_bad_receiver(&assembler, Label::kDeferred); | 2284 Label throw_bad_receiver(this, Label::kDeferred); |
2386 Label set_done(&assembler); | 2285 Label set_done(this); |
2387 Label allocate_key_result(&assembler); | 2286 Label allocate_key_result(this); |
2388 Label allocate_entry_if_needed(&assembler); | 2287 Label allocate_entry_if_needed(this); |
2389 Label allocate_iterator_result(&assembler); | 2288 Label allocate_iterator_result(this); |
2390 Label generic_values(&assembler); | 2289 Label generic_values(this); |
2391 | 2290 |
2392 // If O does not have all of the internal slots of an Array Iterator Instance | 2291 // If O does not have all of the internal slots of an Array Iterator Instance |
2393 // (22.1.5.3), throw a TypeError exception | 2292 // (22.1.5.3), throw a TypeError exception |
2394 assembler.GotoIf(assembler.TaggedIsSmi(iterator), &throw_bad_receiver); | 2293 GotoIf(TaggedIsSmi(iterator), &throw_bad_receiver); |
2395 Node* instance_type = assembler.LoadInstanceType(iterator); | 2294 Node* instance_type = LoadInstanceType(iterator); |
2396 assembler.GotoIf( | 2295 GotoIf( |
2397 assembler.Uint32LessThan( | 2296 Uint32LessThan( |
2398 assembler.Int32Constant(LAST_ARRAY_ITERATOR_TYPE - | 2297 Int32Constant(LAST_ARRAY_ITERATOR_TYPE - FIRST_ARRAY_ITERATOR_TYPE), |
2399 FIRST_ARRAY_ITERATOR_TYPE), | 2298 Int32Sub(instance_type, Int32Constant(FIRST_ARRAY_ITERATOR_TYPE))), |
2400 assembler.Int32Sub(instance_type, assembler.Int32Constant( | |
2401 FIRST_ARRAY_ITERATOR_TYPE))), | |
2402 &throw_bad_receiver); | 2299 &throw_bad_receiver); |
2403 | 2300 |
2404 // Let a be O.[[IteratedObject]]. | 2301 // Let a be O.[[IteratedObject]]. |
2405 Node* array = assembler.LoadObjectField( | 2302 Node* array = |
2406 iterator, JSArrayIterator::kIteratedObjectOffset); | 2303 LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset); |
2407 | 2304 |
2408 // Let index be O.[[ArrayIteratorNextIndex]]. | 2305 // Let index be O.[[ArrayIteratorNextIndex]]. |
2409 Node* index = | 2306 Node* index = LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset); |
2410 assembler.LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset); | 2307 Node* orig_map = |
2411 Node* orig_map = assembler.LoadObjectField( | 2308 LoadObjectField(iterator, JSArrayIterator::kIteratedObjectMapOffset); |
2412 iterator, JSArrayIterator::kIteratedObjectMapOffset); | 2309 Node* array_map = LoadMap(array); |
2413 Node* array_map = assembler.LoadMap(array); | 2310 |
2414 | 2311 Label if_isfastarray(this), if_isnotfastarray(this), |
2415 Label if_isfastarray(&assembler), if_isnotfastarray(&assembler), | 2312 if_isdetached(this, Label::kDeferred); |
2416 if_isdetached(&assembler, Label::kDeferred); | 2313 |
2417 | 2314 Branch(WordEqual(orig_map, array_map), &if_isfastarray, &if_isnotfastarray); |
2418 assembler.Branch(assembler.WordEqual(orig_map, array_map), &if_isfastarray, | 2315 |
2419 &if_isnotfastarray); | 2316 Bind(&if_isfastarray); |
2420 | 2317 { |
2421 assembler.Bind(&if_isfastarray); | 2318 CSA_ASSERT(this, Word32Equal(LoadMapInstanceType(array_map), |
2422 { | 2319 Int32Constant(JS_ARRAY_TYPE))); |
2423 CSA_ASSERT(&assembler, | 2320 |
2424 assembler.Word32Equal(assembler.LoadMapInstanceType(array_map), | 2321 Node* length = LoadObjectField(array, JSArray::kLengthOffset); |
2425 assembler.Int32Constant(JS_ARRAY_TYPE))); | 2322 |
2426 | 2323 CSA_ASSERT(this, TaggedIsSmi(length)); |
2427 Node* length = assembler.LoadObjectField(array, JSArray::kLengthOffset); | 2324 CSA_ASSERT(this, TaggedIsSmi(index)); |
2428 | 2325 |
2429 CSA_ASSERT(&assembler, assembler.TaggedIsSmi(length)); | 2326 GotoIfNot(SmiBelow(index, length), &set_done); |
2430 CSA_ASSERT(&assembler, assembler.TaggedIsSmi(index)); | 2327 |
2431 | 2328 Node* one = SmiConstant(Smi::FromInt(1)); |
2432 assembler.GotoIfNot(assembler.SmiBelow(index, length), &set_done); | 2329 StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset, |
2433 | 2330 SmiAdd(index, one)); |
2434 Node* one = assembler.SmiConstant(Smi::FromInt(1)); | 2331 |
2435 assembler.StoreObjectFieldNoWriteBarrier(iterator, | 2332 var_done.Bind(FalseConstant()); |
2436 JSArrayIterator::kNextIndexOffset, | 2333 Node* elements = LoadElements(array); |
2437 assembler.SmiAdd(index, one)); | |
2438 | |
2439 var_done.Bind(assembler.FalseConstant()); | |
2440 Node* elements = assembler.LoadElements(array); | |
2441 | 2334 |
2442 static int32_t kInstanceType[] = { | 2335 static int32_t kInstanceType[] = { |
2443 JS_FAST_ARRAY_KEY_ITERATOR_TYPE, | 2336 JS_FAST_ARRAY_KEY_ITERATOR_TYPE, |
2444 JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2337 JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2445 JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2338 JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2446 JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2339 JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2447 JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2340 JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2448 JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2341 JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2449 JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2342 JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2450 JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE, | 2343 JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE, |
2451 JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE, | 2344 JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE, |
2452 JS_FAST_ARRAY_VALUE_ITERATOR_TYPE, | 2345 JS_FAST_ARRAY_VALUE_ITERATOR_TYPE, |
2453 JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE, | 2346 JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE, |
2454 JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, | 2347 JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, |
2455 JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, | 2348 JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, |
2456 }; | 2349 }; |
2457 | 2350 |
2458 Label packed_object_values(&assembler), holey_object_values(&assembler), | 2351 Label packed_object_values(this), holey_object_values(this), |
2459 packed_double_values(&assembler), holey_double_values(&assembler); | 2352 packed_double_values(this), holey_double_values(this); |
2460 Label* kInstanceTypeHandlers[] = { | 2353 Label* kInstanceTypeHandlers[] = { |
2461 &allocate_key_result, &packed_object_values, &holey_object_values, | 2354 &allocate_key_result, &packed_object_values, &holey_object_values, |
2462 &packed_object_values, &holey_object_values, &packed_double_values, | 2355 &packed_object_values, &holey_object_values, &packed_double_values, |
2463 &holey_double_values, &packed_object_values, &holey_object_values, | 2356 &holey_double_values, &packed_object_values, &holey_object_values, |
2464 &packed_object_values, &holey_object_values, &packed_double_values, | 2357 &packed_object_values, &holey_object_values, &packed_double_values, |
2465 &holey_double_values}; | 2358 &holey_double_values}; |
2466 | 2359 |
2467 assembler.Switch(instance_type, &throw_bad_receiver, kInstanceType, | 2360 Switch(instance_type, &throw_bad_receiver, kInstanceType, |
2468 kInstanceTypeHandlers, arraysize(kInstanceType)); | 2361 kInstanceTypeHandlers, arraysize(kInstanceType)); |
2469 | 2362 |
2470 assembler.Bind(&packed_object_values); | 2363 Bind(&packed_object_values); |
2471 { | 2364 { |
2472 var_value.Bind(assembler.LoadFixedArrayElement( | 2365 var_value.Bind(LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS)); |
2473 elements, index, 0, CodeStubAssembler::SMI_PARAMETERS)); | 2366 Goto(&allocate_entry_if_needed); |
2474 assembler.Goto(&allocate_entry_if_needed); | |
2475 } | 2367 } |
2476 | 2368 |
2477 assembler.Bind(&packed_double_values); | 2369 Bind(&packed_double_values); |
2478 { | 2370 { |
2479 Node* value = assembler.LoadFixedDoubleArrayElement( | 2371 Node* value = LoadFixedDoubleArrayElement( |
2480 elements, index, MachineType::Float64(), 0, | 2372 elements, index, MachineType::Float64(), 0, SMI_PARAMETERS); |
2481 CodeStubAssembler::SMI_PARAMETERS); | 2373 var_value.Bind(AllocateHeapNumberWithValue(value)); |
2482 var_value.Bind(assembler.AllocateHeapNumberWithValue(value)); | 2374 Goto(&allocate_entry_if_needed); |
2483 assembler.Goto(&allocate_entry_if_needed); | |
2484 } | 2375 } |
2485 | 2376 |
2486 assembler.Bind(&holey_object_values); | 2377 Bind(&holey_object_values); |
2487 { | 2378 { |
2488 // Check the array_protector cell, and take the slow path if it's invalid. | 2379 // Check the array_protector cell, and take the slow path if it's invalid. |
2489 Node* invalid = | 2380 Node* invalid = SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); |
2490 assembler.SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); | 2381 Node* cell = LoadRoot(Heap::kArrayProtectorRootIndex); |
2491 Node* cell = assembler.LoadRoot(Heap::kArrayProtectorRootIndex); | 2382 Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset); |
2492 Node* cell_value = | 2383 GotoIf(WordEqual(cell_value, invalid), &generic_values); |
2493 assembler.LoadObjectField(cell, PropertyCell::kValueOffset); | |
2494 assembler.GotoIf(assembler.WordEqual(cell_value, invalid), | |
2495 &generic_values); | |
2496 | 2384 |
2497 var_value.Bind(assembler.UndefinedConstant()); | 2385 var_value.Bind(UndefinedConstant()); |
2498 Node* value = assembler.LoadFixedArrayElement( | 2386 Node* value = LoadFixedArrayElement(elements, index, 0, SMI_PARAMETERS); |
2499 elements, index, 0, CodeStubAssembler::SMI_PARAMETERS); | 2387 GotoIf(WordEqual(value, TheHoleConstant()), &allocate_entry_if_needed); |
2500 assembler.GotoIf(assembler.WordEqual(value, assembler.TheHoleConstant()), | |
2501 &allocate_entry_if_needed); | |
2502 var_value.Bind(value); | 2388 var_value.Bind(value); |
2503 assembler.Goto(&allocate_entry_if_needed); | 2389 Goto(&allocate_entry_if_needed); |
2504 } | 2390 } |
2505 | 2391 |
2506 assembler.Bind(&holey_double_values); | 2392 Bind(&holey_double_values); |
2507 { | 2393 { |
2508 // Check the array_protector cell, and take the slow path if it's invalid. | 2394 // Check the array_protector cell, and take the slow path if it's invalid. |
2509 Node* invalid = | 2395 Node* invalid = SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); |
2510 assembler.SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); | 2396 Node* cell = LoadRoot(Heap::kArrayProtectorRootIndex); |
2511 Node* cell = assembler.LoadRoot(Heap::kArrayProtectorRootIndex); | 2397 Node* cell_value = LoadObjectField(cell, PropertyCell::kValueOffset); |
2512 Node* cell_value = | 2398 GotoIf(WordEqual(cell_value, invalid), &generic_values); |
2513 assembler.LoadObjectField(cell, PropertyCell::kValueOffset); | |
2514 assembler.GotoIf(assembler.WordEqual(cell_value, invalid), | |
2515 &generic_values); | |
2516 | 2399 |
2517 var_value.Bind(assembler.UndefinedConstant()); | 2400 var_value.Bind(UndefinedConstant()); |
2518 Node* value = assembler.LoadFixedDoubleArrayElement( | 2401 Node* value = LoadFixedDoubleArrayElement( |
2519 elements, index, MachineType::Float64(), 0, | 2402 elements, index, MachineType::Float64(), 0, SMI_PARAMETERS, |
2520 CodeStubAssembler::SMI_PARAMETERS, &allocate_entry_if_needed); | 2403 &allocate_entry_if_needed); |
2521 var_value.Bind(assembler.AllocateHeapNumberWithValue(value)); | 2404 var_value.Bind(AllocateHeapNumberWithValue(value)); |
2522 assembler.Goto(&allocate_entry_if_needed); | 2405 Goto(&allocate_entry_if_needed); |
2523 } | 2406 } |
2524 } | 2407 } |
2525 | 2408 |
2526 assembler.Bind(&if_isnotfastarray); | 2409 Bind(&if_isnotfastarray); |
2527 { | 2410 { |
2528 Label if_istypedarray(&assembler), if_isgeneric(&assembler); | 2411 Label if_istypedarray(this), if_isgeneric(this); |
2529 | 2412 |
2530 // If a is undefined, return CreateIterResultObject(undefined, true) | 2413 // If a is undefined, return CreateIterResultObject(undefined, true) |
2531 assembler.GotoIf(assembler.WordEqual(array, assembler.UndefinedConstant()), | 2414 GotoIf(WordEqual(array, UndefinedConstant()), &allocate_iterator_result); |
2532 &allocate_iterator_result); | |
2533 | 2415 |
2534 Node* array_type = assembler.LoadInstanceType(array); | 2416 Node* array_type = LoadInstanceType(array); |
2535 assembler.Branch( | 2417 Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)), |
2536 assembler.Word32Equal(array_type, | 2418 &if_istypedarray, &if_isgeneric); |
2537 assembler.Int32Constant(JS_TYPED_ARRAY_TYPE)), | |
2538 &if_istypedarray, &if_isgeneric); | |
2539 | 2419 |
2540 assembler.Bind(&if_isgeneric); | 2420 Bind(&if_isgeneric); |
2541 { | 2421 { |
2542 Label if_wasfastarray(&assembler); | 2422 Label if_wasfastarray(this); |
2543 | 2423 |
2544 Node* length = nullptr; | 2424 Node* length = nullptr; |
2545 { | 2425 { |
2546 Variable var_length(&assembler, MachineRepresentation::kTagged); | 2426 Variable var_length(this, MachineRepresentation::kTagged); |
2547 Label if_isarray(&assembler), if_isnotarray(&assembler), | 2427 Label if_isarray(this), if_isnotarray(this), done(this); |
2548 done(&assembler); | 2428 Branch(Word32Equal(array_type, Int32Constant(JS_ARRAY_TYPE)), |
2549 assembler.Branch( | 2429 &if_isarray, &if_isnotarray); |
2550 assembler.Word32Equal(array_type, | |
2551 assembler.Int32Constant(JS_ARRAY_TYPE)), | |
2552 &if_isarray, &if_isnotarray); | |
2553 | 2430 |
2554 assembler.Bind(&if_isarray); | 2431 Bind(&if_isarray); |
2555 { | 2432 { |
2556 var_length.Bind( | 2433 var_length.Bind(LoadObjectField(array, JSArray::kLengthOffset)); |
2557 assembler.LoadObjectField(array, JSArray::kLengthOffset)); | |
2558 | 2434 |
2559 // Invalidate protector cell if needed | 2435 // Invalidate protector cell if needed |
2560 assembler.Branch( | 2436 Branch(WordNotEqual(orig_map, UndefinedConstant()), &if_wasfastarray, |
2561 assembler.WordNotEqual(orig_map, assembler.UndefinedConstant()), | 2437 &done); |
2562 &if_wasfastarray, &done); | |
2563 | 2438 |
2564 assembler.Bind(&if_wasfastarray); | 2439 Bind(&if_wasfastarray); |
2565 { | 2440 { |
2566 Label if_invalid(&assembler, Label::kDeferred); | 2441 Label if_invalid(this, Label::kDeferred); |
2567 // A fast array iterator transitioned to a slow iterator during | 2442 // A fast array iterator transitioned to a slow iterator during |
2568 // iteration. Invalidate fast_array_iteration_prtoector cell to | 2443 // iteration. Invalidate fast_array_iteration_prtoector cell to |
2569 // prevent potential deopt loops. | 2444 // prevent potential deopt loops. |
2570 assembler.StoreObjectFieldNoWriteBarrier( | 2445 StoreObjectFieldNoWriteBarrier( |
2571 iterator, JSArrayIterator::kIteratedObjectMapOffset, | 2446 iterator, JSArrayIterator::kIteratedObjectMapOffset, |
2572 assembler.UndefinedConstant()); | 2447 UndefinedConstant()); |
2573 assembler.GotoIf( | 2448 GotoIf(Uint32LessThanOrEqual( |
2574 assembler.Uint32LessThanOrEqual( | 2449 instance_type, |
2575 instance_type, assembler.Int32Constant( | 2450 Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)), |
2576 JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)), | 2451 &done); |
2577 &done); | |
2578 | 2452 |
2579 Node* invalid = | 2453 Node* invalid = |
2580 assembler.SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); | 2454 SmiConstant(Smi::FromInt(Isolate::kProtectorInvalid)); |
2581 Node* cell = | 2455 Node* cell = LoadRoot(Heap::kFastArrayIterationProtectorRootIndex); |
2582 assembler.LoadRoot(Heap::kFastArrayIterationProtectorRootIndex); | 2456 StoreObjectFieldNoWriteBarrier(cell, Cell::kValueOffset, invalid); |
2583 assembler.StoreObjectFieldNoWriteBarrier(cell, Cell::kValueOffset, | 2457 Goto(&done); |
2584 invalid); | |
2585 assembler.Goto(&done); | |
2586 } | 2458 } |
2587 } | 2459 } |
2588 | 2460 |
2589 assembler.Bind(&if_isnotarray); | 2461 Bind(&if_isnotarray); |
2590 { | 2462 { |
2591 Node* length_string = assembler.HeapConstant( | 2463 Node* length_string = HeapConstant(factory()->length_string()); |
2592 assembler.isolate()->factory()->length_string()); | 2464 Callable get_property = CodeFactory::GetProperty(isolate()); |
2593 Callable get_property = CodeFactory::GetProperty(assembler.isolate()); | 2465 Node* length = CallStub(get_property, context, array, length_string); |
2594 Node* length = | 2466 Callable to_length = CodeFactory::ToLength(isolate()); |
2595 assembler.CallStub(get_property, context, array, length_string); | 2467 var_length.Bind(CallStub(to_length, context, length)); |
2596 Callable to_length = CodeFactory::ToLength(assembler.isolate()); | 2468 Goto(&done); |
2597 var_length.Bind(assembler.CallStub(to_length, context, length)); | |
2598 assembler.Goto(&done); | |
2599 } | 2469 } |
2600 | 2470 |
2601 assembler.Bind(&done); | 2471 Bind(&done); |
2602 length = var_length.value(); | 2472 length = var_length.value(); |
2603 } | 2473 } |
2604 | 2474 |
2605 assembler.GotoUnlessNumberLessThan(index, length, &set_done); | 2475 GotoUnlessNumberLessThan(index, length, &set_done); |
2606 | 2476 |
2607 assembler.StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, | 2477 StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, |
2608 assembler.NumberInc(index)); | 2478 NumberInc(index)); |
2609 var_done.Bind(assembler.FalseConstant()); | 2479 var_done.Bind(FalseConstant()); |
2610 | 2480 |
2611 assembler.Branch( | 2481 Branch( |
2612 assembler.Uint32LessThanOrEqual( | 2482 Uint32LessThanOrEqual( |
2613 instance_type, | 2483 instance_type, Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)), |
2614 assembler.Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)), | |
2615 &allocate_key_result, &generic_values); | 2484 &allocate_key_result, &generic_values); |
2616 | 2485 |
2617 assembler.Bind(&generic_values); | 2486 Bind(&generic_values); |
2618 { | 2487 { |
2619 Callable get_property = CodeFactory::GetProperty(assembler.isolate()); | 2488 Callable get_property = CodeFactory::GetProperty(isolate()); |
2620 var_value.Bind(assembler.CallStub(get_property, context, array, index)); | 2489 var_value.Bind(CallStub(get_property, context, array, index)); |
2621 assembler.Goto(&allocate_entry_if_needed); | 2490 Goto(&allocate_entry_if_needed); |
2622 } | 2491 } |
2623 } | 2492 } |
2624 | 2493 |
2625 assembler.Bind(&if_istypedarray); | 2494 Bind(&if_istypedarray); |
2626 { | 2495 { |
2627 Node* buffer = | 2496 Node* buffer = LoadObjectField(array, JSTypedArray::kBufferOffset); |
2628 assembler.LoadObjectField(array, JSTypedArray::kBufferOffset); | 2497 GotoIf(IsDetachedBuffer(buffer), &if_isdetached); |
2629 assembler.GotoIf(assembler.IsDetachedBuffer(buffer), &if_isdetached); | |
2630 | 2498 |
2631 Node* length = | 2499 Node* length = LoadObjectField(array, JSTypedArray::kLengthOffset); |
2632 assembler.LoadObjectField(array, JSTypedArray::kLengthOffset); | |
2633 | 2500 |
2634 CSA_ASSERT(&assembler, assembler.TaggedIsSmi(length)); | 2501 CSA_ASSERT(this, TaggedIsSmi(length)); |
2635 CSA_ASSERT(&assembler, assembler.TaggedIsSmi(index)); | 2502 CSA_ASSERT(this, TaggedIsSmi(index)); |
2636 | 2503 |
2637 assembler.GotoIfNot(assembler.SmiBelow(index, length), &set_done); | 2504 GotoIfNot(SmiBelow(index, length), &set_done); |
2638 | 2505 |
2639 Node* one = assembler.SmiConstant(1); | 2506 Node* one = SmiConstant(1); |
2640 assembler.StoreObjectFieldNoWriteBarrier( | 2507 StoreObjectFieldNoWriteBarrier( |
2641 iterator, JSArrayIterator::kNextIndexOffset, | 2508 iterator, JSArrayIterator::kNextIndexOffset, SmiAdd(index, one)); |
2642 assembler.SmiAdd(index, one)); | 2509 var_done.Bind(FalseConstant()); |
2643 var_done.Bind(assembler.FalseConstant()); | |
2644 | 2510 |
2645 Node* elements = assembler.LoadElements(array); | 2511 Node* elements = LoadElements(array); |
2646 Node* base_ptr = assembler.LoadObjectField( | 2512 Node* base_ptr = |
2647 elements, FixedTypedArrayBase::kBasePointerOffset); | 2513 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); |
2648 Node* external_ptr = assembler.LoadObjectField( | 2514 Node* external_ptr = |
2649 elements, FixedTypedArrayBase::kExternalPointerOffset, | 2515 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, |
2650 MachineType::Pointer()); | 2516 MachineType::Pointer()); |
2651 Node* data_ptr = assembler.IntPtrAdd( | 2517 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr); |
2652 assembler.BitcastTaggedToWord(base_ptr), external_ptr); | |
2653 | 2518 |
2654 static int32_t kInstanceType[] = { | 2519 static int32_t kInstanceType[] = { |
2655 JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, | 2520 JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, |
2656 JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2521 JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2657 JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2522 JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2658 JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2523 JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2659 JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2524 JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2660 JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2525 JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2661 JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2526 JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2662 JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2527 JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2663 JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2528 JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2664 JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE, | 2529 JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
2665 JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE, | 2530 JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE, |
2666 JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE, | 2531 JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE, |
2667 JS_INT8_ARRAY_VALUE_ITERATOR_TYPE, | 2532 JS_INT8_ARRAY_VALUE_ITERATOR_TYPE, |
2668 JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE, | 2533 JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE, |
2669 JS_INT16_ARRAY_VALUE_ITERATOR_TYPE, | 2534 JS_INT16_ARRAY_VALUE_ITERATOR_TYPE, |
2670 JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE, | 2535 JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE, |
2671 JS_INT32_ARRAY_VALUE_ITERATOR_TYPE, | 2536 JS_INT32_ARRAY_VALUE_ITERATOR_TYPE, |
2672 JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE, | 2537 JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE, |
2673 JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE, | 2538 JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE, |
2674 }; | 2539 }; |
2675 | 2540 |
2676 Label uint8_values(&assembler), int8_values(&assembler), | 2541 Label uint8_values(this), int8_values(this), uint16_values(this), |
2677 uint16_values(&assembler), int16_values(&assembler), | 2542 int16_values(this), uint32_values(this), int32_values(this), |
2678 uint32_values(&assembler), int32_values(&assembler), | 2543 float32_values(this), float64_values(this); |
2679 float32_values(&assembler), float64_values(&assembler); | |
2680 Label* kInstanceTypeHandlers[] = { | 2544 Label* kInstanceTypeHandlers[] = { |
2681 &allocate_key_result, &uint8_values, &uint8_values, | 2545 &allocate_key_result, &uint8_values, &uint8_values, |
2682 &int8_values, &uint16_values, &int16_values, | 2546 &int8_values, &uint16_values, &int16_values, |
2683 &uint32_values, &int32_values, &float32_values, | 2547 &uint32_values, &int32_values, &float32_values, |
2684 &float64_values, &uint8_values, &uint8_values, | 2548 &float64_values, &uint8_values, &uint8_values, |
2685 &int8_values, &uint16_values, &int16_values, | 2549 &int8_values, &uint16_values, &int16_values, |
2686 &uint32_values, &int32_values, &float32_values, | 2550 &uint32_values, &int32_values, &float32_values, |
2687 &float64_values, | 2551 &float64_values, |
2688 }; | 2552 }; |
2689 | 2553 |
2690 var_done.Bind(assembler.FalseConstant()); | 2554 var_done.Bind(FalseConstant()); |
2691 assembler.Switch(instance_type, &throw_bad_receiver, kInstanceType, | 2555 Switch(instance_type, &throw_bad_receiver, kInstanceType, |
2692 kInstanceTypeHandlers, arraysize(kInstanceType)); | 2556 kInstanceTypeHandlers, arraysize(kInstanceType)); |
2693 | 2557 |
2694 assembler.Bind(&uint8_values); | 2558 Bind(&uint8_values); |
2695 { | 2559 { |
2696 Node* value_uint8 = assembler.LoadFixedTypedArrayElement( | 2560 Node* value_uint8 = LoadFixedTypedArrayElement( |
2697 data_ptr, index, UINT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); | 2561 data_ptr, index, UINT8_ELEMENTS, SMI_PARAMETERS); |
2698 var_value.Bind(assembler.SmiFromWord32(value_uint8)); | 2562 var_value.Bind(SmiFromWord32(value_uint8)); |
2699 assembler.Goto(&allocate_entry_if_needed); | 2563 Goto(&allocate_entry_if_needed); |
2700 } | 2564 } |
2701 | 2565 Bind(&int8_values); |
2702 assembler.Bind(&int8_values); | |
2703 { | 2566 { |
2704 Node* value_int8 = assembler.LoadFixedTypedArrayElement( | 2567 Node* value_int8 = LoadFixedTypedArrayElement( |
2705 data_ptr, index, INT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); | 2568 data_ptr, index, INT8_ELEMENTS, SMI_PARAMETERS); |
2706 var_value.Bind(assembler.SmiFromWord32(value_int8)); | 2569 var_value.Bind(SmiFromWord32(value_int8)); |
2707 assembler.Goto(&allocate_entry_if_needed); | 2570 Goto(&allocate_entry_if_needed); |
2708 } | 2571 } |
2709 | 2572 Bind(&uint16_values); |
2710 assembler.Bind(&uint16_values); | |
2711 { | 2573 { |
2712 Node* value_uint16 = assembler.LoadFixedTypedArrayElement( | 2574 Node* value_uint16 = LoadFixedTypedArrayElement( |
2713 data_ptr, index, UINT16_ELEMENTS, | 2575 data_ptr, index, UINT16_ELEMENTS, SMI_PARAMETERS); |
2714 CodeStubAssembler::SMI_PARAMETERS); | 2576 var_value.Bind(SmiFromWord32(value_uint16)); |
2715 var_value.Bind(assembler.SmiFromWord32(value_uint16)); | 2577 Goto(&allocate_entry_if_needed); |
2716 assembler.Goto(&allocate_entry_if_needed); | |
2717 } | 2578 } |
2718 | 2579 Bind(&int16_values); |
2719 assembler.Bind(&int16_values); | |
2720 { | 2580 { |
2721 Node* value_int16 = assembler.LoadFixedTypedArrayElement( | 2581 Node* value_int16 = LoadFixedTypedArrayElement( |
2722 data_ptr, index, INT16_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); | 2582 data_ptr, index, INT16_ELEMENTS, SMI_PARAMETERS); |
2723 var_value.Bind(assembler.SmiFromWord32(value_int16)); | 2583 var_value.Bind(SmiFromWord32(value_int16)); |
2724 assembler.Goto(&allocate_entry_if_needed); | 2584 Goto(&allocate_entry_if_needed); |
2725 } | 2585 } |
2726 | 2586 Bind(&uint32_values); |
2727 assembler.Bind(&uint32_values); | |
2728 { | 2587 { |
2729 Node* value_uint32 = assembler.LoadFixedTypedArrayElement( | 2588 Node* value_uint32 = LoadFixedTypedArrayElement( |
2730 data_ptr, index, UINT32_ELEMENTS, | 2589 data_ptr, index, UINT32_ELEMENTS, SMI_PARAMETERS); |
2731 CodeStubAssembler::SMI_PARAMETERS); | 2590 var_value.Bind(ChangeUint32ToTagged(value_uint32)); |
2732 var_value.Bind(assembler.ChangeUint32ToTagged(value_uint32)); | 2591 Goto(&allocate_entry_if_needed); |
2733 assembler.Goto(&allocate_entry_if_needed); | |
2734 } | 2592 } |
2735 assembler.Bind(&int32_values); | 2593 Bind(&int32_values); |
2736 { | 2594 { |
2737 Node* value_int32 = assembler.LoadFixedTypedArrayElement( | 2595 Node* value_int32 = LoadFixedTypedArrayElement( |
2738 data_ptr, index, INT32_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); | 2596 data_ptr, index, INT32_ELEMENTS, SMI_PARAMETERS); |
2739 var_value.Bind(assembler.ChangeInt32ToTagged(value_int32)); | 2597 var_value.Bind(ChangeInt32ToTagged(value_int32)); |
2740 assembler.Goto(&allocate_entry_if_needed); | 2598 Goto(&allocate_entry_if_needed); |
2741 } | 2599 } |
2742 assembler.Bind(&float32_values); | 2600 Bind(&float32_values); |
2743 { | 2601 { |
2744 Node* value_float32 = assembler.LoadFixedTypedArrayElement( | 2602 Node* value_float32 = LoadFixedTypedArrayElement( |
2745 data_ptr, index, FLOAT32_ELEMENTS, | 2603 data_ptr, index, FLOAT32_ELEMENTS, SMI_PARAMETERS); |
2746 CodeStubAssembler::SMI_PARAMETERS); | 2604 var_value.Bind( |
2747 var_value.Bind(assembler.AllocateHeapNumberWithValue( | 2605 AllocateHeapNumberWithValue(ChangeFloat32ToFloat64(value_float32))); |
2748 assembler.ChangeFloat32ToFloat64(value_float32))); | 2606 Goto(&allocate_entry_if_needed); |
2749 assembler.Goto(&allocate_entry_if_needed); | |
2750 } | 2607 } |
2751 assembler.Bind(&float64_values); | 2608 Bind(&float64_values); |
2752 { | 2609 { |
2753 Node* value_float64 = assembler.LoadFixedTypedArrayElement( | 2610 Node* value_float64 = LoadFixedTypedArrayElement( |
2754 data_ptr, index, FLOAT64_ELEMENTS, | 2611 data_ptr, index, FLOAT64_ELEMENTS, SMI_PARAMETERS); |
2755 CodeStubAssembler::SMI_PARAMETERS); | 2612 var_value.Bind(AllocateHeapNumberWithValue(value_float64)); |
2756 var_value.Bind(assembler.AllocateHeapNumberWithValue(value_float64)); | 2613 Goto(&allocate_entry_if_needed); |
2757 assembler.Goto(&allocate_entry_if_needed); | |
2758 } | 2614 } |
2759 } | 2615 } |
2760 } | 2616 } |
2761 | 2617 |
2762 assembler.Bind(&set_done); | 2618 Bind(&set_done); |
2763 { | 2619 { |
2764 assembler.StoreObjectFieldNoWriteBarrier( | 2620 StoreObjectFieldNoWriteBarrier( |
2765 iterator, JSArrayIterator::kIteratedObjectOffset, | 2621 iterator, JSArrayIterator::kIteratedObjectOffset, UndefinedConstant()); |
2766 assembler.UndefinedConstant()); | 2622 Goto(&allocate_iterator_result); |
2767 assembler.Goto(&allocate_iterator_result); | |
2768 } | 2623 } |
2769 | 2624 |
2770 assembler.Bind(&allocate_key_result); | 2625 Bind(&allocate_key_result); |
2771 { | 2626 { |
2772 var_value.Bind(index); | 2627 var_value.Bind(index); |
2773 var_done.Bind(assembler.FalseConstant()); | 2628 var_done.Bind(FalseConstant()); |
2774 assembler.Goto(&allocate_iterator_result); | 2629 Goto(&allocate_iterator_result); |
2775 } | 2630 } |
2776 | 2631 |
2777 assembler.Bind(&allocate_entry_if_needed); | 2632 Bind(&allocate_entry_if_needed); |
2778 { | 2633 { |
2779 assembler.GotoIf( | 2634 GotoIf(Int32GreaterThan(instance_type, |
2780 assembler.Int32GreaterThan( | 2635 Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)), |
2781 instance_type, | 2636 &allocate_iterator_result); |
2782 assembler.Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)), | |
2783 &allocate_iterator_result); | |
2784 | 2637 |
2785 Node* elements = assembler.AllocateFixedArray(FAST_ELEMENTS, | 2638 Node* elements = AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2)); |
2786 assembler.IntPtrConstant(2)); | 2639 StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER); |
2787 assembler.StoreFixedArrayElement(elements, 0, index, SKIP_WRITE_BARRIER); | 2640 StoreFixedArrayElement(elements, 1, var_value.value(), SKIP_WRITE_BARRIER); |
2788 assembler.StoreFixedArrayElement(elements, 1, var_value.value(), | |
2789 SKIP_WRITE_BARRIER); | |
2790 | 2641 |
2791 Node* entry = assembler.Allocate(JSArray::kSize); | 2642 Node* entry = Allocate(JSArray::kSize); |
2792 Node* map = | 2643 Node* map = LoadContextElement(LoadNativeContext(context), |
2793 assembler.LoadContextElement(assembler.LoadNativeContext(context), | 2644 Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX); |
2794 Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX); | |
2795 | 2645 |
2796 assembler.StoreMapNoWriteBarrier(entry, map); | 2646 StoreMapNoWriteBarrier(entry, map); |
2797 assembler.StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset, | 2647 StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset, |
2798 Heap::kEmptyFixedArrayRootIndex); | 2648 Heap::kEmptyFixedArrayRootIndex); |
2799 assembler.StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset, | 2649 StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset, elements); |
2800 elements); | 2650 StoreObjectFieldNoWriteBarrier(entry, JSArray::kLengthOffset, |
2801 assembler.StoreObjectFieldNoWriteBarrier( | 2651 SmiConstant(Smi::FromInt(2))); |
2802 entry, JSArray::kLengthOffset, assembler.SmiConstant(Smi::FromInt(2))); | |
2803 | 2652 |
2804 var_value.Bind(entry); | 2653 var_value.Bind(entry); |
2805 assembler.Goto(&allocate_iterator_result); | 2654 Goto(&allocate_iterator_result); |
2806 } | 2655 } |
2807 | 2656 |
2808 assembler.Bind(&allocate_iterator_result); | 2657 Bind(&allocate_iterator_result); |
2809 { | 2658 { |
2810 Node* result = assembler.Allocate(JSIteratorResult::kSize); | 2659 Node* result = Allocate(JSIteratorResult::kSize); |
2811 Node* map = | 2660 Node* map = LoadContextElement(LoadNativeContext(context), |
2812 assembler.LoadContextElement(assembler.LoadNativeContext(context), | 2661 Context::ITERATOR_RESULT_MAP_INDEX); |
2813 Context::ITERATOR_RESULT_MAP_INDEX); | 2662 StoreMapNoWriteBarrier(result, map); |
2814 assembler.StoreMapNoWriteBarrier(result, map); | 2663 StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, |
2815 assembler.StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, | 2664 Heap::kEmptyFixedArrayRootIndex); |
2816 Heap::kEmptyFixedArrayRootIndex); | 2665 StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, |
2817 assembler.StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, | 2666 Heap::kEmptyFixedArrayRootIndex); |
2818 Heap::kEmptyFixedArrayRootIndex); | 2667 StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, |
2819 assembler.StoreObjectFieldNoWriteBarrier( | 2668 var_value.value()); |
2820 result, JSIteratorResult::kValueOffset, var_value.value()); | 2669 StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, |
2821 assembler.StoreObjectFieldNoWriteBarrier( | 2670 var_done.value()); |
2822 result, JSIteratorResult::kDoneOffset, var_done.value()); | 2671 Return(result); |
2823 assembler.Return(result); | |
2824 } | 2672 } |
2825 | 2673 |
2826 assembler.Bind(&throw_bad_receiver); | 2674 Bind(&throw_bad_receiver); |
2827 { | 2675 { |
2828 // The {receiver} is not a valid JSArrayIterator. | 2676 // The {receiver} is not a valid JSArrayIterator. |
2829 assembler.CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | 2677 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
2830 assembler.HeapConstant(operation), iterator); | 2678 HeapConstant(operation), iterator); |
2831 assembler.Unreachable(); | 2679 Unreachable(); |
2832 } | 2680 } |
2833 | 2681 |
2834 assembler.Bind(&if_isdetached); | 2682 Bind(&if_isdetached); |
2835 { | 2683 { |
2836 Node* message = assembler.SmiConstant(MessageTemplate::kDetachedOperation); | 2684 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); |
2837 assembler.CallRuntime(Runtime::kThrowTypeError, context, message, | 2685 CallRuntime(Runtime::kThrowTypeError, context, message, |
2838 assembler.HeapConstant(operation)); | 2686 HeapConstant(operation)); |
2839 assembler.Unreachable(); | 2687 Unreachable(); |
2840 } | 2688 } |
2841 } | 2689 } |
2842 | 2690 |
2843 } // namespace internal | 2691 } // namespace internal |
2844 } // namespace v8 | 2692 } // namespace v8 |
OLD | NEW |