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