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 3// found in the LICENSE file. 4 5#include "src/compiler/js-create-lowering.h" 6 7#include "src/codegen/code-factory.h" 8#include "src/compiler/access-builder.h" 9#include "src/compiler/allocation-builder-inl.h" 10#include "src/compiler/common-operator.h" 11#include "src/compiler/compilation-dependencies.h" 12#include "src/compiler/js-graph.h" 13#include "src/compiler/js-operator.h" 14#include "src/compiler/linkage.h" 15#include "src/compiler/node-matchers.h" 16#include "src/compiler/node-properties.h" 17#include "src/compiler/node.h" 18#include "src/compiler/operator-properties.h" 19#include "src/compiler/simplified-operator.h" 20#include "src/compiler/state-values-utils.h" 21#include "src/execution/protectors.h" 22#include "src/objects/arguments.h" 23#include "src/objects/hash-table-inl.h" 24#include "src/objects/heap-number.h" 25#include "src/objects/js-collection-iterator.h" 26#include "src/objects/js-generator.h" 27#include "src/objects/js-promise.h" 28#include "src/objects/js-regexp-inl.h" 29#include "src/objects/objects-inl.h" 30#include "src/objects/template-objects.h" 31 32namespace v8 { 33namespace internal { 34namespace compiler { 35 36namespace { 37 38// Retrieves the frame state holding actual argument values. 39FrameState GetArgumentsFrameState(FrameState frame_state) { 40 FrameState outer_state{NodeProperties::GetFrameStateInput(frame_state)}; 41 return outer_state.frame_state_info().type() == 42 FrameStateType::kArgumentsAdaptor 43 ? outer_state 44 : frame_state; 45} 46 47// When initializing arrays, we'll unfold the loop if the number of 48// elements is known to be of this type. 49const int kElementLoopUnrollLimit = 16; 50 51// Limits up to which context allocations are inlined. 52const int kFunctionContextAllocationLimit = 16; 53const int kBlockContextAllocationLimit = 16; 54 55} // namespace 56 57Reduction JSCreateLowering::Reduce(Node* node) { 58 switch (node->opcode()) { 59 case IrOpcode::kJSCreate: 60 return ReduceJSCreate(node); 61 case IrOpcode::kJSCreateArguments: 62 return ReduceJSCreateArguments(node); 63 case IrOpcode::kJSCreateArray: 64 return ReduceJSCreateArray(node); 65 case IrOpcode::kJSCreateArrayIterator: 66 return ReduceJSCreateArrayIterator(node); 67 case IrOpcode::kJSCreateAsyncFunctionObject: 68 return ReduceJSCreateAsyncFunctionObject(node); 69 case IrOpcode::kJSCreateBoundFunction: 70 return ReduceJSCreateBoundFunction(node); 71 case IrOpcode::kJSCreateClosure: 72 return ReduceJSCreateClosure(node); 73 case IrOpcode::kJSCreateCollectionIterator: 74 return ReduceJSCreateCollectionIterator(node); 75 case IrOpcode::kJSCreateIterResultObject: 76 return ReduceJSCreateIterResultObject(node); 77 case IrOpcode::kJSCreateStringIterator: 78 return ReduceJSCreateStringIterator(node); 79 case IrOpcode::kJSCreateKeyValueArray: 80 return ReduceJSCreateKeyValueArray(node); 81 case IrOpcode::kJSCreatePromise: 82 return ReduceJSCreatePromise(node); 83 case IrOpcode::kJSCreateLiteralArray: 84 case IrOpcode::kJSCreateLiteralObject: 85 return ReduceJSCreateLiteralArrayOrObject(node); 86 case IrOpcode::kJSCreateLiteralRegExp: 87 return ReduceJSCreateLiteralRegExp(node); 88 case IrOpcode::kJSGetTemplateObject: 89 return ReduceJSGetTemplateObject(node); 90 case IrOpcode::kJSCreateEmptyLiteralArray: 91 return ReduceJSCreateEmptyLiteralArray(node); 92 case IrOpcode::kJSCreateEmptyLiteralObject: 93 return ReduceJSCreateEmptyLiteralObject(node); 94 case IrOpcode::kJSCreateFunctionContext: 95 return ReduceJSCreateFunctionContext(node); 96 case IrOpcode::kJSCreateWithContext: 97 return ReduceJSCreateWithContext(node); 98 case IrOpcode::kJSCreateCatchContext: 99 return ReduceJSCreateCatchContext(node); 100 case IrOpcode::kJSCreateBlockContext: 101 return ReduceJSCreateBlockContext(node); 102 case IrOpcode::kJSCreateGeneratorObject: 103 return ReduceJSCreateGeneratorObject(node); 104 case IrOpcode::kJSCreateObject: 105 return ReduceJSCreateObject(node); 106 default: 107 break; 108 } 109 return NoChange(); 110} 111 112Reduction JSCreateLowering::ReduceJSCreate(Node* node) { 113 DCHECK_EQ(IrOpcode::kJSCreate, node->opcode()); 114 Node* const new_target = NodeProperties::GetValueInput(node, 1); 115 Node* const effect = NodeProperties::GetEffectInput(node); 116 Node* const control = NodeProperties::GetControlInput(node); 117 118 base::Optional<MapRef> initial_map = 119 NodeProperties::GetJSCreateMap(broker(), node); 120 if (!initial_map.has_value()) return NoChange(); 121 122 JSFunctionRef original_constructor = 123 HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction(); 124 SlackTrackingPrediction slack_tracking_prediction = 125 dependencies()->DependOnInitialMapInstanceSizePrediction( 126 original_constructor); 127 128 // Emit code to allocate the JSObject instance for the 129 // {original_constructor}. 130 AllocationBuilder a(jsgraph(), effect, control); 131 a.Allocate(slack_tracking_prediction.instance_size()); 132 a.Store(AccessBuilder::ForMap(), *initial_map); 133 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 134 jsgraph()->EmptyFixedArrayConstant()); 135 a.Store(AccessBuilder::ForJSObjectElements(), 136 jsgraph()->EmptyFixedArrayConstant()); 137 for (int i = 0; i < slack_tracking_prediction.inobject_property_count(); 138 ++i) { 139 a.Store(AccessBuilder::ForJSObjectInObjectProperty(*initial_map, i), 140 jsgraph()->UndefinedConstant()); 141 } 142 143 RelaxControls(node); 144 a.FinishAndChange(node); 145 return Changed(node); 146} 147 148Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { 149 DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode()); 150 CreateArgumentsType type = CreateArgumentsTypeOf(node->op()); 151 FrameState frame_state{NodeProperties::GetFrameStateInput(node)}; 152 Node* const control = graph()->start(); 153 FrameStateInfo state_info = frame_state.frame_state_info(); 154 SharedFunctionInfoRef shared = 155 MakeRef(broker(), state_info.shared_info().ToHandleChecked()); 156 157 // Use the ArgumentsAccessStub for materializing both mapped and unmapped 158 // arguments object, but only for non-inlined (i.e. outermost) frames. 159 if (frame_state.outer_frame_state()->opcode() != IrOpcode::kFrameState) { 160 switch (type) { 161 case CreateArgumentsType::kMappedArguments: { 162 // TODO(turbofan): Duplicate parameters are not handled yet. 163 if (shared.has_duplicate_parameters()) return NoChange(); 164 Node* const callee = NodeProperties::GetValueInput(node, 0); 165 Node* const context = NodeProperties::GetContextInput(node); 166 Node* effect = NodeProperties::GetEffectInput(node); 167 Node* const arguments_length = 168 graph()->NewNode(simplified()->ArgumentsLength()); 169 // Allocate the elements backing store. 170 bool has_aliased_arguments = false; 171 Node* const elements = effect = TryAllocateAliasedArguments( 172 effect, control, context, arguments_length, shared, 173 &has_aliased_arguments); 174 if (elements == nullptr) return NoChange(); 175 176 // Load the arguments object map. 177 Node* const arguments_map = jsgraph()->Constant( 178 has_aliased_arguments 179 ? native_context().fast_aliased_arguments_map() 180 : native_context().sloppy_arguments_map()); 181 // Actually allocate and initialize the arguments object. 182 AllocationBuilder a(jsgraph(), effect, control); 183 STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kTaggedSize); 184 a.Allocate(JSSloppyArgumentsObject::kSize); 185 a.Store(AccessBuilder::ForMap(), arguments_map); 186 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 187 jsgraph()->EmptyFixedArrayConstant()); 188 a.Store(AccessBuilder::ForJSObjectElements(), elements); 189 a.Store(AccessBuilder::ForArgumentsLength(), arguments_length); 190 a.Store(AccessBuilder::ForArgumentsCallee(), callee); 191 RelaxControls(node); 192 a.FinishAndChange(node); 193 return Changed(node); 194 } 195 case CreateArgumentsType::kUnmappedArguments: { 196 Node* effect = NodeProperties::GetEffectInput(node); 197 Node* const arguments_length = 198 graph()->NewNode(simplified()->ArgumentsLength()); 199 // Allocate the elements backing store. 200 Node* const elements = effect = graph()->NewNode( 201 simplified()->NewArgumentsElements( 202 CreateArgumentsType::kUnmappedArguments, 203 shared.internal_formal_parameter_count_without_receiver()), 204 arguments_length, effect); 205 // Load the arguments object map. 206 Node* const arguments_map = 207 jsgraph()->Constant(native_context().strict_arguments_map()); 208 // Actually allocate and initialize the arguments object. 209 AllocationBuilder a(jsgraph(), effect, control); 210 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kTaggedSize); 211 a.Allocate(JSStrictArgumentsObject::kSize); 212 a.Store(AccessBuilder::ForMap(), arguments_map); 213 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 214 jsgraph()->EmptyFixedArrayConstant()); 215 a.Store(AccessBuilder::ForJSObjectElements(), elements); 216 a.Store(AccessBuilder::ForArgumentsLength(), arguments_length); 217 RelaxControls(node); 218 a.FinishAndChange(node); 219 return Changed(node); 220 } 221 case CreateArgumentsType::kRestParameter: { 222 Node* effect = NodeProperties::GetEffectInput(node); 223 Node* const arguments_length = 224 graph()->NewNode(simplified()->ArgumentsLength()); 225 Node* const rest_length = graph()->NewNode(simplified()->RestLength( 226 shared.internal_formal_parameter_count_without_receiver())); 227 // Allocate the elements backing store. 228 Node* const elements = effect = graph()->NewNode( 229 simplified()->NewArgumentsElements( 230 CreateArgumentsType::kRestParameter, 231 shared.internal_formal_parameter_count_without_receiver()), 232 arguments_length, effect); 233 // Load the JSArray object map. 234 Node* const jsarray_map = jsgraph()->Constant( 235 native_context().js_array_packed_elements_map()); 236 // Actually allocate and initialize the jsarray. 237 AllocationBuilder a(jsgraph(), effect, control); 238 STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize); 239 a.Allocate(JSArray::kHeaderSize); 240 a.Store(AccessBuilder::ForMap(), jsarray_map); 241 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 242 jsgraph()->EmptyFixedArrayConstant()); 243 a.Store(AccessBuilder::ForJSObjectElements(), elements); 244 a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), rest_length); 245 RelaxControls(node); 246 a.FinishAndChange(node); 247 return Changed(node); 248 } 249 } 250 UNREACHABLE(); 251 } 252 // Use inline allocation for all mapped arguments objects within inlined 253 // (i.e. non-outermost) frames, independent of the object size. 254 DCHECK_EQ(frame_state.outer_frame_state()->opcode(), IrOpcode::kFrameState); 255 switch (type) { 256 case CreateArgumentsType::kMappedArguments: { 257 Node* const callee = NodeProperties::GetValueInput(node, 0); 258 Node* const context = NodeProperties::GetContextInput(node); 259 Node* effect = NodeProperties::GetEffectInput(node); 260 // TODO(turbofan): Duplicate parameters are not handled yet. 261 if (shared.has_duplicate_parameters()) return NoChange(); 262 // Choose the correct frame state and frame state info depending on 263 // whether there conceptually is an arguments adaptor frame in the call 264 // chain. 265 FrameState args_state = GetArgumentsFrameState(frame_state); 266 if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) { 267 // This protects against an incompletely propagated DeadValue node. 268 // If the FrameState has a DeadValue input, then this node will be 269 // pruned anyway. 270 return NoChange(); 271 } 272 FrameStateInfo args_state_info = args_state.frame_state_info(); 273 int length = args_state_info.parameter_count() - 1; // Minus receiver. 274 // Prepare element backing store to be used by arguments object. 275 bool has_aliased_arguments = false; 276 Node* const elements = TryAllocateAliasedArguments( 277 effect, control, args_state, context, shared, &has_aliased_arguments); 278 if (elements == nullptr) return NoChange(); 279 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; 280 // Load the arguments object map. 281 Node* const arguments_map = jsgraph()->Constant( 282 has_aliased_arguments ? native_context().fast_aliased_arguments_map() 283 : native_context().sloppy_arguments_map()); 284 // Actually allocate and initialize the arguments object. 285 AllocationBuilder a(jsgraph(), effect, control); 286 STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kTaggedSize); 287 a.Allocate(JSSloppyArgumentsObject::kSize); 288 a.Store(AccessBuilder::ForMap(), arguments_map); 289 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 290 jsgraph()->EmptyFixedArrayConstant()); 291 a.Store(AccessBuilder::ForJSObjectElements(), elements); 292 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); 293 a.Store(AccessBuilder::ForArgumentsCallee(), callee); 294 RelaxControls(node); 295 a.FinishAndChange(node); 296 return Changed(node); 297 } 298 case CreateArgumentsType::kUnmappedArguments: { 299 // Use inline allocation for all unmapped arguments objects within inlined 300 // (i.e. non-outermost) frames, independent of the object size. 301 Node* effect = NodeProperties::GetEffectInput(node); 302 // Choose the correct frame state and frame state info depending on 303 // whether there conceptually is an arguments adaptor frame in the call 304 // chain. 305 FrameState args_state = GetArgumentsFrameState(frame_state); 306 if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) { 307 // This protects against an incompletely propagated DeadValue node. 308 // If the FrameState has a DeadValue input, then this node will be 309 // pruned anyway. 310 return NoChange(); 311 } 312 FrameStateInfo args_state_info = args_state.frame_state_info(); 313 int length = args_state_info.parameter_count() - 1; // Minus receiver. 314 // Prepare element backing store to be used by arguments object. 315 Node* const elements = TryAllocateArguments(effect, control, args_state); 316 if (elements == nullptr) return NoChange(); 317 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; 318 // Load the arguments object map. 319 Node* const arguments_map = 320 jsgraph()->Constant(native_context().strict_arguments_map()); 321 // Actually allocate and initialize the arguments object. 322 AllocationBuilder a(jsgraph(), effect, control); 323 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kTaggedSize); 324 a.Allocate(JSStrictArgumentsObject::kSize); 325 a.Store(AccessBuilder::ForMap(), arguments_map); 326 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 327 jsgraph()->EmptyFixedArrayConstant()); 328 a.Store(AccessBuilder::ForJSObjectElements(), elements); 329 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); 330 RelaxControls(node); 331 a.FinishAndChange(node); 332 return Changed(node); 333 } 334 case CreateArgumentsType::kRestParameter: { 335 int start_index = 336 shared.internal_formal_parameter_count_without_receiver(); 337 // Use inline allocation for all unmapped arguments objects within inlined 338 // (i.e. non-outermost) frames, independent of the object size. 339 Node* effect = NodeProperties::GetEffectInput(node); 340 // Choose the correct frame state and frame state info depending on 341 // whether there conceptually is an arguments adaptor frame in the call 342 // chain. 343 FrameState args_state = GetArgumentsFrameState(frame_state); 344 if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) { 345 // This protects against an incompletely propagated DeadValue node. 346 // If the FrameState has a DeadValue input, then this node will be 347 // pruned anyway. 348 return NoChange(); 349 } 350 FrameStateInfo args_state_info = args_state.frame_state_info(); 351 // Prepare element backing store to be used by the rest array. 352 Node* const elements = 353 TryAllocateRestArguments(effect, control, args_state, start_index); 354 if (elements == nullptr) return NoChange(); 355 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; 356 // Load the JSArray object map. 357 Node* const jsarray_map = 358 jsgraph()->Constant(native_context().js_array_packed_elements_map()); 359 // Actually allocate and initialize the jsarray. 360 AllocationBuilder a(jsgraph(), effect, control); 361 362 // -1 to minus receiver 363 int argument_count = args_state_info.parameter_count() - 1; 364 int length = std::max(0, argument_count - start_index); 365 STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize); 366 a.Allocate(JSArray::kHeaderSize); 367 a.Store(AccessBuilder::ForMap(), jsarray_map); 368 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 369 jsgraph()->EmptyFixedArrayConstant()); 370 a.Store(AccessBuilder::ForJSObjectElements(), elements); 371 a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), 372 jsgraph()->Constant(length)); 373 RelaxControls(node); 374 a.FinishAndChange(node); 375 return Changed(node); 376 } 377 } 378 UNREACHABLE(); 379} 380 381Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) { 382 DCHECK_EQ(IrOpcode::kJSCreateGeneratorObject, node->opcode()); 383 Node* const closure = NodeProperties::GetValueInput(node, 0); 384 Node* const receiver = NodeProperties::GetValueInput(node, 1); 385 Node* const context = NodeProperties::GetContextInput(node); 386 Type const closure_type = NodeProperties::GetType(closure); 387 Node* effect = NodeProperties::GetEffectInput(node); 388 Node* const control = NodeProperties::GetControlInput(node); 389 if (closure_type.IsHeapConstant()) { 390 DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction()); 391 JSFunctionRef js_function = 392 closure_type.AsHeapConstant()->Ref().AsJSFunction(); 393 if (!js_function.has_initial_map(dependencies())) return NoChange(); 394 395 SlackTrackingPrediction slack_tracking_prediction = 396 dependencies()->DependOnInitialMapInstanceSizePrediction(js_function); 397 398 MapRef initial_map = js_function.initial_map(dependencies()); 399 DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE || 400 initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE); 401 402 // Allocate a register file. 403 SharedFunctionInfoRef shared = js_function.shared(); 404 DCHECK(shared.HasBytecodeArray()); 405 int parameter_count_no_receiver = 406 shared.internal_formal_parameter_count_without_receiver(); 407 int length = parameter_count_no_receiver + 408 shared.GetBytecodeArray().register_count(); 409 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 410 AllocationBuilder ab(jsgraph(), effect, control); 411 if (!ab.CanAllocateArray(length, fixed_array_map)) { 412 return NoChange(); 413 } 414 ab.AllocateArray(length, fixed_array_map); 415 for (int i = 0; i < length; ++i) { 416 ab.Store(AccessBuilder::ForFixedArraySlot(i), 417 jsgraph()->UndefinedConstant()); 418 } 419 Node* parameters_and_registers = effect = ab.Finish(); 420 421 // Emit code to allocate the JS[Async]GeneratorObject instance. 422 AllocationBuilder a(jsgraph(), effect, control); 423 a.Allocate(slack_tracking_prediction.instance_size()); 424 Node* undefined = jsgraph()->UndefinedConstant(); 425 a.Store(AccessBuilder::ForMap(), initial_map); 426 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 427 jsgraph()->EmptyFixedArrayConstant()); 428 a.Store(AccessBuilder::ForJSObjectElements(), 429 jsgraph()->EmptyFixedArrayConstant()); 430 a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context); 431 a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure); 432 a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver); 433 a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(), undefined); 434 a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(), 435 jsgraph()->Constant(JSGeneratorObject::kNext)); 436 a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(), 437 jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting)); 438 a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(), 439 parameters_and_registers); 440 441 if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) { 442 a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined); 443 a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(), 444 jsgraph()->ZeroConstant()); 445 } 446 447 // Handle in-object properties, too. 448 for (int i = 0; i < slack_tracking_prediction.inobject_property_count(); 449 ++i) { 450 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), 451 undefined); 452 } 453 a.FinishAndChange(node); 454 return Changed(node); 455 } 456 return NoChange(); 457} 458 459// Constructs an array with a variable {length} when no upper bound 460// is known for the capacity. 461Reduction JSCreateLowering::ReduceNewArray( 462 Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind, 463 AllocationType allocation, 464 const SlackTrackingPrediction& slack_tracking_prediction) { 465 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); 466 Node* effect = NodeProperties::GetEffectInput(node); 467 Node* control = NodeProperties::GetControlInput(node); 468 469 // Constructing an Array via new Array(N) where N is an unsigned 470 // integer, always creates a holey backing store. 471 base::Optional<MapRef> maybe_initial_map = 472 initial_map.AsElementsKind(GetHoleyElementsKind(elements_kind)); 473 if (!maybe_initial_map.has_value()) return NoChange(); 474 initial_map = maybe_initial_map.value(); 475 476 // Because CheckBounds performs implicit conversion from string to number, an 477 // additional CheckNumber is required to behave correctly for calls with a 478 // single string argument. 479 length = effect = graph()->NewNode( 480 simplified()->CheckNumber(FeedbackSource{}), length, effect, control); 481 482 // Check that the {limit} is an unsigned integer in the valid range. 483 // This has to be kept in sync with src/runtime/runtime-array.cc, 484 // where this limit is protected. 485 length = effect = graph()->NewNode( 486 simplified()->CheckBounds(FeedbackSource()), length, 487 jsgraph()->Constant(JSArray::kInitialMaxFastElementArray), effect, 488 control); 489 490 // Construct elements and properties for the resulting JSArray. 491 Node* elements = effect = 492 graph()->NewNode(IsDoubleElementsKind(initial_map.elements_kind()) 493 ? simplified()->NewDoubleElements(allocation) 494 : simplified()->NewSmiOrObjectElements(allocation), 495 length, effect, control); 496 497 // Perform the allocation of the actual JSArray object. 498 AllocationBuilder a(jsgraph(), effect, control); 499 a.Allocate(slack_tracking_prediction.instance_size(), allocation); 500 a.Store(AccessBuilder::ForMap(), initial_map); 501 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 502 jsgraph()->EmptyFixedArrayConstant()); 503 a.Store(AccessBuilder::ForJSObjectElements(), elements); 504 a.Store(AccessBuilder::ForJSArrayLength(initial_map.elements_kind()), length); 505 for (int i = 0; i < slack_tracking_prediction.inobject_property_count(); 506 ++i) { 507 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), 508 jsgraph()->UndefinedConstant()); 509 } 510 RelaxControls(node); 511 a.FinishAndChange(node); 512 return Changed(node); 513} 514 515// Constructs an array with a variable {length} when an actual 516// upper bound is known for the {capacity}. 517Reduction JSCreateLowering::ReduceNewArray( 518 Node* node, Node* length, int capacity, MapRef initial_map, 519 ElementsKind elements_kind, AllocationType allocation, 520 const SlackTrackingPrediction& slack_tracking_prediction) { 521 DCHECK(node->opcode() == IrOpcode::kJSCreateArray || 522 node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray); 523 DCHECK(NodeProperties::GetType(length).Is(Type::Number())); 524 Node* effect = NodeProperties::GetEffectInput(node); 525 Node* control = NodeProperties::GetControlInput(node); 526 527 // Determine the appropriate elements kind. 528 if (NodeProperties::GetType(length).Max() > 0.0) { 529 elements_kind = GetHoleyElementsKind(elements_kind); 530 } 531 532 base::Optional<MapRef> maybe_initial_map = 533 initial_map.AsElementsKind(elements_kind); 534 if (!maybe_initial_map.has_value()) return NoChange(); 535 initial_map = maybe_initial_map.value(); 536 537 DCHECK(IsFastElementsKind(elements_kind)); 538 539 // Setup elements and properties. 540 Node* elements; 541 if (capacity == 0) { 542 elements = jsgraph()->EmptyFixedArrayConstant(); 543 } else { 544 elements = effect = 545 AllocateElements(effect, control, elements_kind, capacity, allocation); 546 } 547 548 // Perform the allocation of the actual JSArray object. 549 AllocationBuilder a(jsgraph(), effect, control); 550 a.Allocate(slack_tracking_prediction.instance_size(), allocation); 551 a.Store(AccessBuilder::ForMap(), initial_map); 552 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 553 jsgraph()->EmptyFixedArrayConstant()); 554 a.Store(AccessBuilder::ForJSObjectElements(), elements); 555 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); 556 for (int i = 0; i < slack_tracking_prediction.inobject_property_count(); 557 ++i) { 558 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), 559 jsgraph()->UndefinedConstant()); 560 } 561 RelaxControls(node); 562 a.FinishAndChange(node); 563 return Changed(node); 564} 565 566Reduction JSCreateLowering::ReduceNewArray( 567 Node* node, std::vector<Node*> values, MapRef initial_map, 568 ElementsKind elements_kind, AllocationType allocation, 569 const SlackTrackingPrediction& slack_tracking_prediction) { 570 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); 571 Node* effect = NodeProperties::GetEffectInput(node); 572 Node* control = NodeProperties::GetControlInput(node); 573 574 // Determine the appropriate elements kind. 575 DCHECK(IsFastElementsKind(elements_kind)); 576 577 base::Optional<MapRef> maybe_initial_map = 578 initial_map.AsElementsKind(elements_kind); 579 if (!maybe_initial_map.has_value()) return NoChange(); 580 initial_map = maybe_initial_map.value(); 581 582 // Check {values} based on the {elements_kind}. These checks are guarded 583 // by the {elements_kind} feedback on the {site}, so it's safe to just 584 // deoptimize in this case. 585 if (IsSmiElementsKind(elements_kind)) { 586 for (auto& value : values) { 587 if (!NodeProperties::GetType(value).Is(Type::SignedSmall())) { 588 value = effect = graph()->NewNode( 589 simplified()->CheckSmi(FeedbackSource()), value, effect, control); 590 } 591 } 592 } else if (IsDoubleElementsKind(elements_kind)) { 593 for (auto& value : values) { 594 if (!NodeProperties::GetType(value).Is(Type::Number())) { 595 value = effect = 596 graph()->NewNode(simplified()->CheckNumber(FeedbackSource()), value, 597 effect, control); 598 } 599 // Make sure we do not store signaling NaNs into double arrays. 600 value = graph()->NewNode(simplified()->NumberSilenceNaN(), value); 601 } 602 } 603 604 // Setup elements, properties and length. 605 Node* elements = effect = 606 AllocateElements(effect, control, elements_kind, values, allocation); 607 Node* length = jsgraph()->Constant(static_cast<int>(values.size())); 608 609 // Perform the allocation of the actual JSArray object. 610 AllocationBuilder a(jsgraph(), effect, control); 611 a.Allocate(slack_tracking_prediction.instance_size(), allocation); 612 a.Store(AccessBuilder::ForMap(), initial_map); 613 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 614 jsgraph()->EmptyFixedArrayConstant()); 615 a.Store(AccessBuilder::ForJSObjectElements(), elements); 616 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); 617 for (int i = 0; i < slack_tracking_prediction.inobject_property_count(); 618 ++i) { 619 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), 620 jsgraph()->UndefinedConstant()); 621 } 622 RelaxControls(node); 623 a.FinishAndChange(node); 624 return Changed(node); 625} 626 627Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { 628 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); 629 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); 630 int const arity = static_cast<int>(p.arity()); 631 base::Optional<AllocationSiteRef> site_ref = p.site(broker()); 632 AllocationType allocation = AllocationType::kYoung; 633 634 base::Optional<MapRef> initial_map = 635 NodeProperties::GetJSCreateMap(broker(), node); 636 if (!initial_map.has_value()) return NoChange(); 637 638 Node* new_target = NodeProperties::GetValueInput(node, 1); 639 JSFunctionRef original_constructor = 640 HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction(); 641 SlackTrackingPrediction slack_tracking_prediction = 642 dependencies()->DependOnInitialMapInstanceSizePrediction( 643 original_constructor); 644 645 // Tells whether we are protected by either the {site} or a 646 // protector cell to do certain speculative optimizations. 647 bool can_inline_call = false; 648 649 // Check if we have a feedback {site} on the {node}. 650 ElementsKind elements_kind = initial_map->elements_kind(); 651 if (site_ref) { 652 elements_kind = site_ref->GetElementsKind(); 653 can_inline_call = site_ref->CanInlineCall(); 654 allocation = dependencies()->DependOnPretenureMode(*site_ref); 655 dependencies()->DependOnElementsKind(*site_ref); 656 } else { 657 PropertyCellRef array_constructor_protector = 658 MakeRef(broker(), factory()->array_constructor_protector()); 659 array_constructor_protector.CacheAsProtector(); 660 can_inline_call = array_constructor_protector.value().AsSmi() == 661 Protectors::kProtectorValid; 662 } 663 664 if (arity == 0) { 665 Node* length = jsgraph()->ZeroConstant(); 666 int capacity = JSArray::kPreallocatedArrayElements; 667 return ReduceNewArray(node, length, capacity, *initial_map, elements_kind, 668 allocation, slack_tracking_prediction); 669 } else if (arity == 1) { 670 Node* length = NodeProperties::GetValueInput(node, 2); 671 Type length_type = NodeProperties::GetType(length); 672 if (!length_type.Maybe(Type::Number())) { 673 // Handle the single argument case, where we know that the value 674 // cannot be a valid Array length. 675 elements_kind = GetMoreGeneralElementsKind( 676 elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS 677 : PACKED_ELEMENTS); 678 return ReduceNewArray(node, std::vector<Node*>{length}, *initial_map, 679 elements_kind, allocation, 680 slack_tracking_prediction); 681 } 682 if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 && 683 length_type.Max() <= kElementLoopUnrollLimit && 684 length_type.Min() == length_type.Max()) { 685 int capacity = static_cast<int>(length_type.Max()); 686 // Replace length with a constant in order to protect against a potential 687 // typer bug leading to length > capacity. 688 length = jsgraph()->Constant(capacity); 689 return ReduceNewArray(node, length, capacity, *initial_map, elements_kind, 690 allocation, slack_tracking_prediction); 691 } 692 if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) { 693 return ReduceNewArray(node, length, *initial_map, elements_kind, 694 allocation, slack_tracking_prediction); 695 } 696 } else if (arity <= JSArray::kInitialMaxFastElementArray) { 697 // Gather the values to store into the newly created array. 698 bool values_all_smis = true, values_all_numbers = true, 699 values_any_nonnumber = false; 700 std::vector<Node*> values; 701 values.reserve(p.arity()); 702 for (int i = 0; i < arity; ++i) { 703 Node* value = NodeProperties::GetValueInput(node, 2 + i); 704 Type value_type = NodeProperties::GetType(value); 705 if (!value_type.Is(Type::SignedSmall())) { 706 values_all_smis = false; 707 } 708 if (!value_type.Is(Type::Number())) { 709 values_all_numbers = false; 710 } 711 if (!value_type.Maybe(Type::Number())) { 712 values_any_nonnumber = true; 713 } 714 values.push_back(value); 715 } 716 717 // Try to figure out the ideal elements kind statically. 718 if (values_all_smis) { 719 // Smis can be stored with any elements kind. 720 } else if (values_all_numbers) { 721 elements_kind = GetMoreGeneralElementsKind( 722 elements_kind, IsHoleyElementsKind(elements_kind) 723 ? HOLEY_DOUBLE_ELEMENTS 724 : PACKED_DOUBLE_ELEMENTS); 725 } else if (values_any_nonnumber) { 726 elements_kind = GetMoreGeneralElementsKind( 727 elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS 728 : PACKED_ELEMENTS); 729 } else if (!can_inline_call) { 730 // We have some crazy combination of types for the {values} where 731 // there's no clear decision on the elements kind statically. And 732 // we don't have a protection against deoptimization loops for the 733 // checks that are introduced in the call to ReduceNewArray, so 734 // we cannot inline this invocation of the Array constructor here. 735 return NoChange(); 736 } 737 return ReduceNewArray(node, values, *initial_map, elements_kind, allocation, 738 slack_tracking_prediction); 739 } 740 return NoChange(); 741} 742 743Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) { 744 DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, node->opcode()); 745 CreateArrayIteratorParameters const& p = 746 CreateArrayIteratorParametersOf(node->op()); 747 Node* iterated_object = NodeProperties::GetValueInput(node, 0); 748 Node* effect = NodeProperties::GetEffectInput(node); 749 Node* control = NodeProperties::GetControlInput(node); 750 751 // Create the JSArrayIterator result. 752 AllocationBuilder a(jsgraph(), effect, control); 753 a.Allocate(JSArrayIterator::kHeaderSize, AllocationType::kYoung, 754 Type::OtherObject()); 755 a.Store(AccessBuilder::ForMap(), 756 native_context().initial_array_iterator_map()); 757 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 758 jsgraph()->EmptyFixedArrayConstant()); 759 a.Store(AccessBuilder::ForJSObjectElements(), 760 jsgraph()->EmptyFixedArrayConstant()); 761 a.Store(AccessBuilder::ForJSArrayIteratorIteratedObject(), iterated_object); 762 a.Store(AccessBuilder::ForJSArrayIteratorNextIndex(), 763 jsgraph()->ZeroConstant()); 764 a.Store(AccessBuilder::ForJSArrayIteratorKind(), 765 jsgraph()->Constant(static_cast<int>(p.kind()))); 766 RelaxControls(node); 767 a.FinishAndChange(node); 768 return Changed(node); 769} 770 771Reduction JSCreateLowering::ReduceJSCreateAsyncFunctionObject(Node* node) { 772 DCHECK_EQ(IrOpcode::kJSCreateAsyncFunctionObject, node->opcode()); 773 int const register_count = RegisterCountOf(node->op()); 774 Node* closure = NodeProperties::GetValueInput(node, 0); 775 Node* receiver = NodeProperties::GetValueInput(node, 1); 776 Node* promise = NodeProperties::GetValueInput(node, 2); 777 Node* context = NodeProperties::GetContextInput(node); 778 Node* effect = NodeProperties::GetEffectInput(node); 779 Node* control = NodeProperties::GetControlInput(node); 780 781 // Create the register file. 782 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 783 AllocationBuilder ab(jsgraph(), effect, control); 784 CHECK(ab.CanAllocateArray(register_count, fixed_array_map)); 785 ab.AllocateArray(register_count, fixed_array_map); 786 for (int i = 0; i < register_count; ++i) { 787 ab.Store(AccessBuilder::ForFixedArraySlot(i), 788 jsgraph()->UndefinedConstant()); 789 } 790 Node* parameters_and_registers = effect = ab.Finish(); 791 792 // Create the JSAsyncFunctionObject result. 793 AllocationBuilder a(jsgraph(), effect, control); 794 a.Allocate(JSAsyncFunctionObject::kHeaderSize); 795 a.Store(AccessBuilder::ForMap(), 796 native_context().async_function_object_map()); 797 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 798 jsgraph()->EmptyFixedArrayConstant()); 799 a.Store(AccessBuilder::ForJSObjectElements(), 800 jsgraph()->EmptyFixedArrayConstant()); 801 a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context); 802 a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure); 803 a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver); 804 a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(), 805 jsgraph()->UndefinedConstant()); 806 a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(), 807 jsgraph()->Constant(JSGeneratorObject::kNext)); 808 a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(), 809 jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting)); 810 a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(), 811 parameters_and_registers); 812 a.Store(AccessBuilder::ForJSAsyncFunctionObjectPromise(), promise); 813 a.FinishAndChange(node); 814 return Changed(node); 815} 816 817namespace { 818 819MapRef MapForCollectionIterationKind(const NativeContextRef& native_context, 820 CollectionKind collection_kind, 821 IterationKind iteration_kind) { 822 switch (collection_kind) { 823 case CollectionKind::kSet: 824 switch (iteration_kind) { 825 case IterationKind::kKeys: 826 UNREACHABLE(); 827 case IterationKind::kValues: 828 return native_context.set_value_iterator_map(); 829 case IterationKind::kEntries: 830 return native_context.set_key_value_iterator_map(); 831 } 832 break; 833 case CollectionKind::kMap: 834 switch (iteration_kind) { 835 case IterationKind::kKeys: 836 return native_context.map_key_iterator_map(); 837 case IterationKind::kValues: 838 return native_context.map_value_iterator_map(); 839 case IterationKind::kEntries: 840 return native_context.map_key_value_iterator_map(); 841 } 842 break; 843 } 844 UNREACHABLE(); 845} 846 847} // namespace 848 849Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) { 850 DCHECK_EQ(IrOpcode::kJSCreateCollectionIterator, node->opcode()); 851 CreateCollectionIteratorParameters const& p = 852 CreateCollectionIteratorParametersOf(node->op()); 853 Node* iterated_object = NodeProperties::GetValueInput(node, 0); 854 Node* effect = NodeProperties::GetEffectInput(node); 855 Node* control = NodeProperties::GetControlInput(node); 856 857 // Load the OrderedHashTable from the {receiver}. 858 Node* table = effect = graph()->NewNode( 859 simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), 860 iterated_object, effect, control); 861 862 // Create the JSCollectionIterator result. 863 AllocationBuilder a(jsgraph(), effect, control); 864 a.Allocate(JSCollectionIterator::kHeaderSize, AllocationType::kYoung, 865 Type::OtherObject()); 866 a.Store(AccessBuilder::ForMap(), 867 MapForCollectionIterationKind(native_context(), p.collection_kind(), 868 p.iteration_kind())); 869 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 870 jsgraph()->EmptyFixedArrayConstant()); 871 a.Store(AccessBuilder::ForJSObjectElements(), 872 jsgraph()->EmptyFixedArrayConstant()); 873 a.Store(AccessBuilder::ForJSCollectionIteratorTable(), table); 874 a.Store(AccessBuilder::ForJSCollectionIteratorIndex(), 875 jsgraph()->ZeroConstant()); 876 RelaxControls(node); 877 a.FinishAndChange(node); 878 return Changed(node); 879} 880 881Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) { 882 DCHECK_EQ(IrOpcode::kJSCreateBoundFunction, node->opcode()); 883 CreateBoundFunctionParameters const& p = 884 CreateBoundFunctionParametersOf(node->op()); 885 int const arity = static_cast<int>(p.arity()); 886 MapRef const map = p.map(broker()); 887 Node* bound_target_function = NodeProperties::GetValueInput(node, 0); 888 Node* bound_this = NodeProperties::GetValueInput(node, 1); 889 Node* effect = NodeProperties::GetEffectInput(node); 890 Node* control = NodeProperties::GetControlInput(node); 891 892 // Create the [[BoundArguments]] for the result. 893 Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant(); 894 if (arity > 0) { 895 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 896 AllocationBuilder ab(jsgraph(), effect, control); 897 CHECK(ab.CanAllocateArray(arity, fixed_array_map)); 898 ab.AllocateArray(arity, fixed_array_map); 899 for (int i = 0; i < arity; ++i) { 900 ab.Store(AccessBuilder::ForFixedArraySlot(i), 901 NodeProperties::GetValueInput(node, 2 + i)); 902 } 903 bound_arguments = effect = ab.Finish(); 904 } 905 906 // Create the JSBoundFunction result. 907 AllocationBuilder a(jsgraph(), effect, control); 908 a.Allocate(JSBoundFunction::kHeaderSize, AllocationType::kYoung, 909 Type::BoundFunction()); 910 a.Store(AccessBuilder::ForMap(), map); 911 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 912 jsgraph()->EmptyFixedArrayConstant()); 913 a.Store(AccessBuilder::ForJSObjectElements(), 914 jsgraph()->EmptyFixedArrayConstant()); 915 a.Store(AccessBuilder::ForJSBoundFunctionBoundTargetFunction(), 916 bound_target_function); 917 a.Store(AccessBuilder::ForJSBoundFunctionBoundThis(), bound_this); 918 a.Store(AccessBuilder::ForJSBoundFunctionBoundArguments(), bound_arguments); 919 RelaxControls(node); 920 a.FinishAndChange(node); 921 return Changed(node); 922} 923 924Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) { 925 JSCreateClosureNode n(node); 926 CreateClosureParameters const& p = n.Parameters(); 927 SharedFunctionInfoRef shared = p.shared_info(broker()); 928 FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker()); 929 HeapObjectRef code = p.code(broker()); 930 Effect effect = n.effect(); 931 Control control = n.control(); 932 Node* context = n.context(); 933 934 // Use inline allocation of closures only for instantiation sites that have 935 // seen more than one instantiation, this simplifies the generated code and 936 // also serves as a heuristic of which allocation sites benefit from it. 937 if (!feedback_cell.map().equals( 938 MakeRef(broker(), factory()->many_closures_cell_map()))) { 939 return NoChange(); 940 } 941 942 // Don't inline anything for class constructors. 943 if (IsClassConstructor(shared.kind())) return NoChange(); 944 945 MapRef function_map = 946 native_context().GetFunctionMapFromIndex(shared.function_map_index()); 947 DCHECK(!function_map.IsInobjectSlackTrackingInProgress()); 948 DCHECK(!function_map.is_dictionary_map()); 949 950 // TODO(turbofan): We should use the pretenure flag from {p} here, 951 // but currently the heuristic in the parser works against us, as 952 // it marks closures like 953 // 954 // args[l] = function(...) { ... } 955 // 956 // for old-space allocation, which doesn't always make sense. For 957 // example in case of the bluebird-parallel benchmark, where this 958 // is a core part of the *promisify* logic (see crbug.com/810132). 959 AllocationType allocation = AllocationType::kYoung; 960 961 // Emit code to allocate the JSFunction instance. 962 STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize); 963 AllocationBuilder a(jsgraph(), effect, control); 964 a.Allocate(function_map.instance_size(), allocation, 965 Type::CallableFunction()); 966 a.Store(AccessBuilder::ForMap(), function_map); 967 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 968 jsgraph()->EmptyFixedArrayConstant()); 969 a.Store(AccessBuilder::ForJSObjectElements(), 970 jsgraph()->EmptyFixedArrayConstant()); 971 a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared); 972 a.Store(AccessBuilder::ForJSFunctionContext(), context); 973 a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell); 974 a.Store(AccessBuilder::ForJSFunctionCode(), code); 975 STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize); 976 if (function_map.has_prototype_slot()) { 977 a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(), 978 jsgraph()->TheHoleConstant()); 979 STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kTaggedSize); 980 } 981 for (int i = 0; i < function_map.GetInObjectProperties(); i++) { 982 a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i), 983 jsgraph()->UndefinedConstant()); 984 } 985 RelaxControls(node); 986 a.FinishAndChange(node); 987 return Changed(node); 988} 989 990Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) { 991 DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode()); 992 Node* value = NodeProperties::GetValueInput(node, 0); 993 Node* done = NodeProperties::GetValueInput(node, 1); 994 Node* effect = NodeProperties::GetEffectInput(node); 995 996 Node* iterator_result_map = 997 jsgraph()->Constant(native_context().iterator_result_map()); 998 999 // Emit code to allocate the JSIteratorResult instance. 1000 AllocationBuilder a(jsgraph(), effect, graph()->start()); 1001 a.Allocate(JSIteratorResult::kSize); 1002 a.Store(AccessBuilder::ForMap(), iterator_result_map); 1003 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1004 jsgraph()->EmptyFixedArrayConstant()); 1005 a.Store(AccessBuilder::ForJSObjectElements(), 1006 jsgraph()->EmptyFixedArrayConstant()); 1007 a.Store(AccessBuilder::ForJSIteratorResultValue(), value); 1008 a.Store(AccessBuilder::ForJSIteratorResultDone(), done); 1009 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize); 1010 a.FinishAndChange(node); 1011 return Changed(node); 1012} 1013 1014Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) { 1015 DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode()); 1016 Node* string = NodeProperties::GetValueInput(node, 0); 1017 Node* effect = NodeProperties::GetEffectInput(node); 1018 1019 Node* map = 1020 jsgraph()->Constant(native_context().initial_string_iterator_map()); 1021 // Allocate new iterator and attach the iterator to this string. 1022 AllocationBuilder a(jsgraph(), effect, graph()->start()); 1023 a.Allocate(JSStringIterator::kHeaderSize, AllocationType::kYoung, 1024 Type::OtherObject()); 1025 a.Store(AccessBuilder::ForMap(), map); 1026 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1027 jsgraph()->EmptyFixedArrayConstant()); 1028 a.Store(AccessBuilder::ForJSObjectElements(), 1029 jsgraph()->EmptyFixedArrayConstant()); 1030 a.Store(AccessBuilder::ForJSStringIteratorString(), string); 1031 a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0)); 1032 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize); 1033 a.FinishAndChange(node); 1034 return Changed(node); 1035} 1036 1037Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) { 1038 DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode()); 1039 Node* key = NodeProperties::GetValueInput(node, 0); 1040 Node* value = NodeProperties::GetValueInput(node, 1); 1041 Node* effect = NodeProperties::GetEffectInput(node); 1042 1043 Node* array_map = 1044 jsgraph()->Constant(native_context().js_array_packed_elements_map()); 1045 Node* length = jsgraph()->Constant(2); 1046 1047 AllocationBuilder aa(jsgraph(), effect, graph()->start()); 1048 aa.AllocateArray(2, MakeRef(broker(), factory()->fixed_array_map())); 1049 aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS), 1050 jsgraph()->ZeroConstant(), key); 1051 aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS), 1052 jsgraph()->OneConstant(), value); 1053 Node* elements = aa.Finish(); 1054 1055 AllocationBuilder a(jsgraph(), elements, graph()->start()); 1056 a.Allocate(JSArray::kHeaderSize); 1057 a.Store(AccessBuilder::ForMap(), array_map); 1058 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1059 jsgraph()->EmptyFixedArrayConstant()); 1060 a.Store(AccessBuilder::ForJSObjectElements(), elements); 1061 a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length); 1062 STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize); 1063 a.FinishAndChange(node); 1064 return Changed(node); 1065} 1066 1067Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) { 1068 DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode()); 1069 Node* effect = NodeProperties::GetEffectInput(node); 1070 1071 MapRef promise_map = 1072 native_context().promise_function().initial_map(dependencies()); 1073 1074 AllocationBuilder a(jsgraph(), effect, graph()->start()); 1075 a.Allocate(promise_map.instance_size()); 1076 a.Store(AccessBuilder::ForMap(), promise_map); 1077 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1078 jsgraph()->EmptyFixedArrayConstant()); 1079 a.Store(AccessBuilder::ForJSObjectElements(), 1080 jsgraph()->EmptyFixedArrayConstant()); 1081 a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kReactionsOrResultOffset), 1082 jsgraph()->ZeroConstant()); 1083 STATIC_ASSERT(v8::Promise::kPending == 0); 1084 a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kFlagsOffset), 1085 jsgraph()->ZeroConstant()); 1086 STATIC_ASSERT(JSPromise::kHeaderSize == 5 * kTaggedSize); 1087 for (int offset = JSPromise::kHeaderSize; 1088 offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) { 1089 a.Store(AccessBuilder::ForJSObjectOffset(offset), 1090 jsgraph()->ZeroConstant()); 1091 } 1092 a.FinishAndChange(node); 1093 return Changed(node); 1094} 1095 1096Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) { 1097 DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray || 1098 node->opcode() == IrOpcode::kJSCreateLiteralObject); 1099 JSCreateLiteralOpNode n(node); 1100 CreateLiteralParameters const& p = n.Parameters(); 1101 Effect effect = n.effect(); 1102 Control control = n.control(); 1103 ProcessedFeedback const& feedback = 1104 broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback()); 1105 if (!feedback.IsInsufficient()) { 1106 AllocationSiteRef site = feedback.AsLiteral().value(); 1107 if (!site.boilerplate().has_value()) return NoChange(); 1108 AllocationType allocation = dependencies()->DependOnPretenureMode(site); 1109 int max_properties = kMaxFastLiteralProperties; 1110 base::Optional<Node*> maybe_value = 1111 TryAllocateFastLiteral(effect, control, *site.boilerplate(), allocation, 1112 kMaxFastLiteralDepth, &max_properties); 1113 if (!maybe_value.has_value()) return NoChange(); 1114 dependencies()->DependOnElementsKinds(site); 1115 Node* value = effect = maybe_value.value(); 1116 ReplaceWithValue(node, value, effect, control); 1117 return Replace(value); 1118 } 1119 return NoChange(); 1120} 1121 1122Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) { 1123 JSCreateEmptyLiteralArrayNode n(node); 1124 FeedbackParameter const& p = n.Parameters(); 1125 ProcessedFeedback const& feedback = 1126 broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback()); 1127 if (!feedback.IsInsufficient()) { 1128 AllocationSiteRef site = feedback.AsLiteral().value(); 1129 DCHECK(!site.PointsToLiteral()); 1130 MapRef initial_map = 1131 native_context().GetInitialJSArrayMap(site.GetElementsKind()); 1132 AllocationType const allocation = 1133 dependencies()->DependOnPretenureMode(site); 1134 dependencies()->DependOnElementsKind(site); 1135 Node* length = jsgraph()->ZeroConstant(); 1136 DCHECK(!initial_map.IsInobjectSlackTrackingInProgress()); 1137 SlackTrackingPrediction slack_tracking_prediction( 1138 initial_map, initial_map.instance_size()); 1139 return ReduceNewArray(node, length, 0, initial_map, 1140 initial_map.elements_kind(), allocation, 1141 slack_tracking_prediction); 1142 } 1143 return NoChange(); 1144} 1145 1146Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) { 1147 DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralObject, node->opcode()); 1148 Node* effect = NodeProperties::GetEffectInput(node); 1149 Node* control = NodeProperties::GetControlInput(node); 1150 1151 // Retrieve the initial map for the object. 1152 MapRef map = native_context().object_function().initial_map(dependencies()); 1153 DCHECK(!map.is_dictionary_map()); 1154 DCHECK(!map.IsInobjectSlackTrackingInProgress()); 1155 Node* js_object_map = jsgraph()->Constant(map); 1156 1157 // Setup elements and properties. 1158 Node* elements = jsgraph()->EmptyFixedArrayConstant(); 1159 1160 // Perform the allocation of the actual JSArray object. 1161 AllocationBuilder a(jsgraph(), effect, control); 1162 a.Allocate(map.instance_size()); 1163 a.Store(AccessBuilder::ForMap(), js_object_map); 1164 a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1165 jsgraph()->EmptyFixedArrayConstant()); 1166 a.Store(AccessBuilder::ForJSObjectElements(), elements); 1167 for (int i = 0; i < map.GetInObjectProperties(); i++) { 1168 a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i), 1169 jsgraph()->UndefinedConstant()); 1170 } 1171 1172 RelaxControls(node); 1173 a.FinishAndChange(node); 1174 return Changed(node); 1175} 1176 1177Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) { 1178 JSCreateLiteralRegExpNode n(node); 1179 CreateLiteralParameters const& p = n.Parameters(); 1180 Effect effect = n.effect(); 1181 Control control = n.control(); 1182 ProcessedFeedback const& feedback = 1183 broker()->GetFeedbackForRegExpLiteral(p.feedback()); 1184 if (!feedback.IsInsufficient()) { 1185 RegExpBoilerplateDescriptionRef literal = 1186 feedback.AsRegExpLiteral().value(); 1187 Node* value = effect = AllocateLiteralRegExp(effect, control, literal); 1188 ReplaceWithValue(node, value, effect, control); 1189 return Replace(value); 1190 } 1191 return NoChange(); 1192} 1193 1194Reduction JSCreateLowering::ReduceJSGetTemplateObject(Node* node) { 1195 JSGetTemplateObjectNode n(node); 1196 GetTemplateObjectParameters const& parameters = n.Parameters(); 1197 1198 const ProcessedFeedback& feedback = 1199 broker()->GetFeedbackForTemplateObject(parameters.feedback()); 1200 // TODO(v8:7790): Consider not generating JSGetTemplateObject operator 1201 // in the BytecodeGraphBuilder in the first place, if template_object is not 1202 // available. 1203 if (feedback.IsInsufficient()) return NoChange(); 1204 1205 JSArrayRef template_object = feedback.AsTemplateObject().value(); 1206 Node* value = jsgraph()->Constant(template_object); 1207 ReplaceWithValue(node, value); 1208 return Replace(value); 1209} 1210 1211Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) { 1212 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); 1213 const CreateFunctionContextParameters& parameters = 1214 CreateFunctionContextParametersOf(node->op()); 1215 ScopeInfoRef scope_info = parameters.scope_info(broker()); 1216 int slot_count = parameters.slot_count(); 1217 ScopeType scope_type = parameters.scope_type(); 1218 1219 // Use inline allocation for function contexts up to a size limit. 1220 if (slot_count < kFunctionContextAllocationLimit) { 1221 // JSCreateFunctionContext[slot_count < limit]](fun) 1222 Node* effect = NodeProperties::GetEffectInput(node); 1223 Node* control = NodeProperties::GetControlInput(node); 1224 Node* context = NodeProperties::GetContextInput(node); 1225 AllocationBuilder a(jsgraph(), effect, control); 1226 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2); // Ensure fully covered. 1227 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; 1228 switch (scope_type) { 1229 case EVAL_SCOPE: 1230 a.AllocateContext(context_length, native_context().eval_context_map()); 1231 break; 1232 case FUNCTION_SCOPE: 1233 a.AllocateContext(context_length, 1234 native_context().function_context_map()); 1235 break; 1236 default: 1237 UNREACHABLE(); 1238 } 1239 a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), 1240 scope_info); 1241 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1242 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { 1243 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); 1244 } 1245 RelaxControls(node); 1246 a.FinishAndChange(node); 1247 return Changed(node); 1248 } 1249 1250 return NoChange(); 1251} 1252 1253Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) { 1254 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); 1255 ScopeInfoRef scope_info = ScopeInfoOf(broker(), node->op()); 1256 Node* extension = NodeProperties::GetValueInput(node, 0); 1257 Node* effect = NodeProperties::GetEffectInput(node); 1258 Node* control = NodeProperties::GetControlInput(node); 1259 Node* context = NodeProperties::GetContextInput(node); 1260 1261 AllocationBuilder a(jsgraph(), effect, control); 1262 STATIC_ASSERT(Context::MIN_CONTEXT_EXTENDED_SLOTS == 1263 3); // Ensure fully covered. 1264 a.AllocateContext(Context::MIN_CONTEXT_EXTENDED_SLOTS, 1265 native_context().with_context_map()); 1266 a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info); 1267 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1268 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); 1269 RelaxControls(node); 1270 a.FinishAndChange(node); 1271 return Changed(node); 1272} 1273 1274Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) { 1275 DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode()); 1276 ScopeInfoRef scope_info = ScopeInfoOf(broker(), node->op()); 1277 Node* exception = NodeProperties::GetValueInput(node, 0); 1278 Node* effect = NodeProperties::GetEffectInput(node); 1279 Node* control = NodeProperties::GetControlInput(node); 1280 Node* context = NodeProperties::GetContextInput(node); 1281 1282 AllocationBuilder a(jsgraph(), effect, control); 1283 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2); // Ensure fully covered. 1284 a.AllocateContext(Context::MIN_CONTEXT_SLOTS + 1, 1285 native_context().catch_context_map()); 1286 a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info); 1287 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1288 a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX), 1289 exception); 1290 RelaxControls(node); 1291 a.FinishAndChange(node); 1292 return Changed(node); 1293} 1294 1295Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) { 1296 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); 1297 ScopeInfoRef scope_info = ScopeInfoOf(broker(), node->op()); 1298 int const context_length = scope_info.ContextLength(); 1299 1300 // Use inline allocation for block contexts up to a size limit. 1301 if (context_length < kBlockContextAllocationLimit) { 1302 // JSCreateBlockContext[scope[length < limit]](fun) 1303 Node* effect = NodeProperties::GetEffectInput(node); 1304 Node* control = NodeProperties::GetControlInput(node); 1305 Node* context = NodeProperties::GetContextInput(node); 1306 1307 AllocationBuilder a(jsgraph(), effect, control); 1308 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2); // Ensure fully covered. 1309 a.AllocateContext(context_length, native_context().block_context_map()); 1310 a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), 1311 scope_info); 1312 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); 1313 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { 1314 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); 1315 } 1316 RelaxControls(node); 1317 a.FinishAndChange(node); 1318 return Changed(node); 1319 } 1320 1321 return NoChange(); 1322} 1323 1324namespace { 1325 1326base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker, 1327 HeapObjectRef prototype) { 1328 MapRef standard_map = 1329 broker->target_native_context().object_function().initial_map( 1330 broker->dependencies()); 1331 if (prototype.equals(standard_map.prototype())) { 1332 return standard_map; 1333 } 1334 if (prototype.map().oddball_type() == OddballType::kNull) { 1335 return broker->target_native_context() 1336 .slow_object_with_null_prototype_map(); 1337 } 1338 if (prototype.IsJSObject()) { 1339 return prototype.AsJSObject().GetObjectCreateMap(); 1340 } 1341 return base::Optional<MapRef>(); 1342} 1343 1344} // namespace 1345 1346Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) { 1347 DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode()); 1348 Node* effect = NodeProperties::GetEffectInput(node); 1349 Node* control = NodeProperties::GetControlInput(node); 1350 Node* prototype = NodeProperties::GetValueInput(node, 0); 1351 Type prototype_type = NodeProperties::GetType(prototype); 1352 if (!prototype_type.IsHeapConstant()) return NoChange(); 1353 1354 HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref(); 1355 auto maybe_instance_map = GetObjectCreateMap(broker(), prototype_const); 1356 if (!maybe_instance_map) return NoChange(); 1357 MapRef instance_map = maybe_instance_map.value(); 1358 1359 Node* properties = jsgraph()->EmptyFixedArrayConstant(); 1360 if (instance_map.is_dictionary_map()) { 1361 DCHECK_EQ(prototype_const.map().oddball_type(), OddballType::kNull); 1362 // Allocate an empty NameDictionary as backing store for the properties. 1363 MapRef map = MakeRef(broker(), factory()->name_dictionary_map()); 1364 int capacity = 1365 NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity); 1366 DCHECK(base::bits::IsPowerOfTwo(capacity)); 1367 int length = NameDictionary::EntryToIndex(InternalIndex(capacity)); 1368 int size = NameDictionary::SizeFor(length); 1369 1370 AllocationBuilder a(jsgraph(), effect, control); 1371 a.Allocate(size, AllocationType::kYoung, Type::Any()); 1372 a.Store(AccessBuilder::ForMap(), map); 1373 // Initialize FixedArray fields. 1374 a.Store(AccessBuilder::ForFixedArrayLength(), 1375 jsgraph()->SmiConstant(length)); 1376 // Initialize HashTable fields. 1377 a.Store(AccessBuilder::ForHashTableBaseNumberOfElements(), 1378 jsgraph()->SmiConstant(0)); 1379 a.Store(AccessBuilder::ForHashTableBaseNumberOfDeletedElement(), 1380 jsgraph()->SmiConstant(0)); 1381 a.Store(AccessBuilder::ForHashTableBaseCapacity(), 1382 jsgraph()->SmiConstant(capacity)); 1383 // Initialize Dictionary fields. 1384 a.Store(AccessBuilder::ForDictionaryNextEnumerationIndex(), 1385 jsgraph()->SmiConstant(PropertyDetails::kInitialIndex)); 1386 a.Store(AccessBuilder::ForDictionaryObjectHashIndex(), 1387 jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel)); 1388 // Initialize the Properties fields. 1389 Node* undefined = jsgraph()->UndefinedConstant(); 1390 STATIC_ASSERT(NameDictionary::kElementsStartIndex == 1391 NameDictionary::kObjectHashIndex + 1); 1392 for (int index = NameDictionary::kElementsStartIndex; index < length; 1393 index++) { 1394 a.Store(AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier), 1395 undefined); 1396 } 1397 properties = effect = a.Finish(); 1398 } 1399 1400 int const instance_size = instance_map.instance_size(); 1401 if (instance_size > kMaxRegularHeapObjectSize) return NoChange(); 1402 CHECK(!instance_map.IsInobjectSlackTrackingInProgress()); 1403 1404 // Emit code to allocate the JSObject instance for the given 1405 // {instance_map}. 1406 AllocationBuilder a(jsgraph(), effect, control); 1407 a.Allocate(instance_size, AllocationType::kYoung, Type::Any()); 1408 a.Store(AccessBuilder::ForMap(), instance_map); 1409 a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties); 1410 a.Store(AccessBuilder::ForJSObjectElements(), 1411 jsgraph()->EmptyFixedArrayConstant()); 1412 // Initialize Object fields. 1413 Node* undefined = jsgraph()->UndefinedConstant(); 1414 for (int offset = JSObject::kHeaderSize; offset < instance_size; 1415 offset += kTaggedSize) { 1416 a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier), 1417 undefined); 1418 } 1419 Node* value = effect = a.Finish(); 1420 1421 ReplaceWithValue(node, value, effect, control); 1422 return Replace(value); 1423} 1424 1425// Helper that allocates a FixedArray holding argument values recorded in the 1426// given {frame_state}. Serves as backing store for JSCreateArguments nodes. 1427Node* JSCreateLowering::TryAllocateArguments(Node* effect, Node* control, 1428 FrameState frame_state) { 1429 FrameStateInfo state_info = frame_state.frame_state_info(); 1430 int argument_count = state_info.parameter_count() - 1; // Minus receiver. 1431 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); 1432 1433 // Prepare an iterator over argument values recorded in the frame state. 1434 Node* const parameters = frame_state.parameters(); 1435 StateValuesAccess parameters_access(parameters); 1436 auto parameters_it = parameters_access.begin_without_receiver(); 1437 1438 // Actually allocate the backing store. 1439 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 1440 AllocationBuilder ab(jsgraph(), effect, control); 1441 if (!ab.CanAllocateArray(argument_count, fixed_array_map)) { 1442 return nullptr; 1443 } 1444 ab.AllocateArray(argument_count, fixed_array_map); 1445 for (int i = 0; i < argument_count; ++i, ++parameters_it) { 1446 DCHECK_NOT_NULL(parameters_it.node()); 1447 ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i), 1448 parameters_it.node()); 1449 } 1450 return ab.Finish(); 1451} 1452 1453// Helper that allocates a FixedArray holding argument values recorded in the 1454// given {frame_state}. Serves as backing store for JSCreateArguments nodes. 1455Node* JSCreateLowering::TryAllocateRestArguments(Node* effect, Node* control, 1456 FrameState frame_state, 1457 int start_index) { 1458 FrameStateInfo state_info = frame_state.frame_state_info(); 1459 int argument_count = state_info.parameter_count() - 1; // Minus receiver. 1460 int num_elements = std::max(0, argument_count - start_index); 1461 if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant(); 1462 1463 // Prepare an iterator over argument values recorded in the frame state. 1464 Node* const parameters = frame_state.parameters(); 1465 StateValuesAccess parameters_access(parameters); 1466 auto parameters_it = 1467 parameters_access.begin_without_receiver_and_skip(start_index); 1468 1469 // Actually allocate the backing store. 1470 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 1471 AllocationBuilder ab(jsgraph(), effect, control); 1472 if (!ab.CanAllocateArray(num_elements, fixed_array_map)) { 1473 return nullptr; 1474 } 1475 ab.AllocateArray(num_elements, fixed_array_map); 1476 for (int i = 0; i < num_elements; ++i, ++parameters_it) { 1477 DCHECK_NOT_NULL(parameters_it.node()); 1478 ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i), 1479 parameters_it.node()); 1480 } 1481 return ab.Finish(); 1482} 1483 1484// Helper that allocates a FixedArray serving as a parameter map for values 1485// recorded in the given {frame_state}. Some elements map to slots within the 1486// given {context}. Serves as backing store for JSCreateArguments nodes. 1487Node* JSCreateLowering::TryAllocateAliasedArguments( 1488 Node* effect, Node* control, FrameState frame_state, Node* context, 1489 const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) { 1490 FrameStateInfo state_info = frame_state.frame_state_info(); 1491 int argument_count = state_info.parameter_count() - 1; // Minus receiver. 1492 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); 1493 1494 // If there is no aliasing, the arguments object elements are not special in 1495 // any way, we can just return an unmapped backing store instead. 1496 int parameter_count = 1497 shared.internal_formal_parameter_count_without_receiver(); 1498 if (parameter_count == 0) { 1499 return TryAllocateArguments(effect, control, frame_state); 1500 } 1501 1502 // Calculate number of argument values being aliased/mapped. 1503 int mapped_count = std::min(argument_count, parameter_count); 1504 *has_aliased_arguments = true; 1505 1506 MapRef sloppy_arguments_elements_map = 1507 MakeRef(broker(), factory()->sloppy_arguments_elements_map()); 1508 AllocationBuilder ab(jsgraph(), effect, control); 1509 1510 if (!ab.CanAllocateSloppyArgumentElements(mapped_count, 1511 sloppy_arguments_elements_map)) { 1512 return nullptr; 1513 } 1514 1515 MapRef fixed_array_map = MakeRef(broker(), factory()->fixed_array_map()); 1516 if (!ab.CanAllocateArray(argument_count, fixed_array_map)) { 1517 return nullptr; 1518 } 1519 1520 // Prepare an iterator over argument values recorded in the frame state. 1521 Node* const parameters = frame_state.parameters(); 1522 StateValuesAccess parameters_access(parameters); 1523 auto parameters_it = 1524 parameters_access.begin_without_receiver_and_skip(mapped_count); 1525 1526 // The unmapped argument values recorded in the frame state are stored yet 1527 // another indirection away and then linked into the parameter map below, 1528 // whereas mapped argument values are replaced with a hole instead. 1529 ab.AllocateArray(argument_count, fixed_array_map); 1530 for (int i = 0; i < mapped_count; ++i) { 1531 ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i), 1532 jsgraph()->TheHoleConstant()); 1533 } 1534 for (int i = mapped_count; i < argument_count; ++i, ++parameters_it) { 1535 DCHECK_NOT_NULL(parameters_it.node()); 1536 ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i), 1537 parameters_it.node()); 1538 } 1539 Node* arguments = ab.Finish(); 1540 1541 // Actually allocate the backing store. 1542 AllocationBuilder a(jsgraph(), arguments, control); 1543 a.AllocateSloppyArgumentElements(mapped_count, sloppy_arguments_elements_map); 1544 a.Store(AccessBuilder::ForSloppyArgumentsElementsContext(), context); 1545 a.Store(AccessBuilder::ForSloppyArgumentsElementsArguments(), arguments); 1546 for (int i = 0; i < mapped_count; ++i) { 1547 int idx = shared.context_parameters_start() + parameter_count - 1 - i; 1548 a.Store(AccessBuilder::ForSloppyArgumentsElementsMappedEntry(), 1549 jsgraph()->Constant(i), jsgraph()->Constant(idx)); 1550 } 1551 return a.Finish(); 1552} 1553 1554// Helper that allocates a FixedArray serving as a parameter map for values 1555// unknown at compile-time, the true {arguments_length} and {arguments_frame} 1556// values can only be determined dynamically at run-time and are provided. 1557// Serves as backing store for JSCreateArguments nodes. 1558Node* JSCreateLowering::TryAllocateAliasedArguments( 1559 Node* effect, Node* control, Node* context, Node* arguments_length, 1560 const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) { 1561 // If there is no aliasing, the arguments object elements are not 1562 // special in any way, we can just return an unmapped backing store. 1563 int parameter_count = 1564 shared.internal_formal_parameter_count_without_receiver(); 1565 if (parameter_count == 0) { 1566 return graph()->NewNode( 1567 simplified()->NewArgumentsElements( 1568 CreateArgumentsType::kUnmappedArguments, parameter_count), 1569 arguments_length, effect); 1570 } 1571 1572 int mapped_count = parameter_count; 1573 MapRef sloppy_arguments_elements_map = 1574 MakeRef(broker(), factory()->sloppy_arguments_elements_map()); 1575 1576 { 1577 AllocationBuilder ab(jsgraph(), effect, control); 1578 if (!ab.CanAllocateSloppyArgumentElements(mapped_count, 1579 sloppy_arguments_elements_map)) { 1580 return nullptr; 1581 } 1582 } 1583 1584 // From here on we are going to allocate a mapped (aka. aliased) elements 1585 // backing store. We do not statically know how many arguments exist, but 1586 // dynamically selecting the hole for some of the "mapped" elements allows 1587 // using a static shape for the parameter map. 1588 *has_aliased_arguments = true; 1589 1590 // The unmapped argument values are stored yet another indirection away and 1591 // then linked into the parameter map below, whereas mapped argument values 1592 // (i.e. the first {mapped_count} elements) are replaced with a hole instead. 1593 Node* arguments = effect = 1594 graph()->NewNode(simplified()->NewArgumentsElements( 1595 CreateArgumentsType::kMappedArguments, mapped_count), 1596 arguments_length, effect); 1597 1598 // Actually allocate the backing store. 1599 AllocationBuilder a(jsgraph(), effect, control); 1600 a.AllocateSloppyArgumentElements(mapped_count, sloppy_arguments_elements_map); 1601 a.Store(AccessBuilder::ForSloppyArgumentsElementsContext(), context); 1602 a.Store(AccessBuilder::ForSloppyArgumentsElementsArguments(), arguments); 1603 for (int i = 0; i < mapped_count; ++i) { 1604 int idx = shared.context_parameters_start() + parameter_count - 1 - i; 1605 Node* value = graph()->NewNode( 1606 common()->Select(MachineRepresentation::kTagged), 1607 graph()->NewNode(simplified()->NumberLessThan(), jsgraph()->Constant(i), 1608 arguments_length), 1609 jsgraph()->Constant(idx), jsgraph()->TheHoleConstant()); 1610 a.Store(AccessBuilder::ForSloppyArgumentsElementsMappedEntry(), 1611 jsgraph()->Constant(i), value); 1612 } 1613 return a.Finish(); 1614} 1615 1616Node* JSCreateLowering::AllocateElements(Node* effect, Node* control, 1617 ElementsKind elements_kind, 1618 int capacity, 1619 AllocationType allocation) { 1620 DCHECK_LE(1, capacity); 1621 DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray); 1622 1623 Handle<Map> elements_map = IsDoubleElementsKind(elements_kind) 1624 ? factory()->fixed_double_array_map() 1625 : factory()->fixed_array_map(); 1626 ElementAccess access = IsDoubleElementsKind(elements_kind) 1627 ? AccessBuilder::ForFixedDoubleArrayElement() 1628 : AccessBuilder::ForFixedArrayElement(); 1629 Node* value = jsgraph()->TheHoleConstant(); 1630 1631 // Actually allocate the backing store. 1632 AllocationBuilder a(jsgraph(), effect, control); 1633 a.AllocateArray(capacity, MakeRef(broker(), elements_map), allocation); 1634 for (int i = 0; i < capacity; ++i) { 1635 Node* index = jsgraph()->Constant(i); 1636 a.Store(access, index, value); 1637 } 1638 return a.Finish(); 1639} 1640 1641Node* JSCreateLowering::AllocateElements(Node* effect, Node* control, 1642 ElementsKind elements_kind, 1643 std::vector<Node*> const& values, 1644 AllocationType allocation) { 1645 int const capacity = static_cast<int>(values.size()); 1646 DCHECK_LE(1, capacity); 1647 DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray); 1648 1649 Handle<Map> elements_map = IsDoubleElementsKind(elements_kind) 1650 ? factory()->fixed_double_array_map() 1651 : factory()->fixed_array_map(); 1652 ElementAccess access = IsDoubleElementsKind(elements_kind) 1653 ? AccessBuilder::ForFixedDoubleArrayElement() 1654 : AccessBuilder::ForFixedArrayElement(); 1655 1656 // Actually allocate the backing store. 1657 AllocationBuilder a(jsgraph(), effect, control); 1658 a.AllocateArray(capacity, MakeRef(broker(), elements_map), allocation); 1659 for (int i = 0; i < capacity; ++i) { 1660 Node* index = jsgraph()->Constant(i); 1661 a.Store(access, index, values[i]); 1662 } 1663 return a.Finish(); 1664} 1665 1666base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteral( 1667 Node* effect, Node* control, JSObjectRef boilerplate, 1668 AllocationType allocation, int max_depth, int* max_properties) { 1669 DCHECK_GE(max_depth, 0); 1670 DCHECK_GE(*max_properties, 0); 1671 1672 if (max_depth == 0) return {}; 1673 1674 // Prevent concurrent migrations of boilerplate objects. 1675 JSHeapBroker::BoilerplateMigrationGuardIfNeeded boilerplate_access_guard( 1676 broker()); 1677 1678 // Now that we hold the migration lock, get the current map. 1679 MapRef boilerplate_map = boilerplate.map(); 1680 // Protect against concurrent changes to the boilerplate object by checking 1681 // for an identical value at the end of the compilation. 1682 dependencies()->DependOnObjectSlotValue(boilerplate, HeapObject::kMapOffset, 1683 boilerplate_map); 1684 { 1685 base::Optional<MapRef> current_boilerplate_map = 1686 boilerplate.map_direct_read(); 1687 if (!current_boilerplate_map.has_value() || 1688 !current_boilerplate_map->equals(boilerplate_map)) { 1689 return {}; 1690 } 1691 } 1692 1693 // Bail out if the boilerplate map has been deprecated. The map could of 1694 // course be deprecated at some point after the line below, but it's not a 1695 // correctness issue -- it only means the literal won't be created with the 1696 // most up to date map(s). 1697 if (boilerplate_map.is_deprecated()) return {}; 1698 1699 // We currently only support in-object properties. 1700 if (boilerplate.map().elements_kind() == DICTIONARY_ELEMENTS || 1701 boilerplate.map().is_dictionary_map() || 1702 !boilerplate.raw_properties_or_hash().has_value()) { 1703 return {}; 1704 } 1705 { 1706 ObjectRef properties = *boilerplate.raw_properties_or_hash(); 1707 bool const empty = properties.IsSmi() || 1708 properties.equals(MakeRef<Object>( 1709 broker(), factory()->empty_fixed_array())) || 1710 properties.equals(MakeRef<Object>( 1711 broker(), factory()->empty_property_array())); 1712 if (!empty) return {}; 1713 } 1714 1715 // Compute the in-object properties to store first (might have effects). 1716 ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone()); 1717 inobject_fields.reserve(boilerplate_map.GetInObjectProperties()); 1718 int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors(); 1719 for (InternalIndex i : InternalIndex::Range(boilerplate_nof)) { 1720 PropertyDetails const property_details = 1721 boilerplate_map.GetPropertyDetails(i); 1722 if (property_details.location() != PropertyLocation::kField) continue; 1723 DCHECK_EQ(PropertyKind::kData, property_details.kind()); 1724 if ((*max_properties)-- == 0) return {}; 1725 1726 NameRef property_name = boilerplate_map.GetPropertyKey(i); 1727 FieldIndex index = boilerplate_map.GetFieldIndexFor(i); 1728 ConstFieldInfo const_field_info(boilerplate_map.object()); 1729 FieldAccess access = {kTaggedBase, 1730 index.offset(), 1731 property_name.object(), 1732 MaybeHandle<Map>(), 1733 Type::Any(), 1734 MachineType::AnyTagged(), 1735 kFullWriteBarrier, 1736 const_field_info}; 1737 1738 // Note: the use of RawInobjectPropertyAt (vs. the higher-level 1739 // GetOwnFastDataProperty) here is necessary, since the underlying value 1740 // may be `uninitialized`, which the latter explicitly does not support. 1741 base::Optional<ObjectRef> maybe_boilerplate_value = 1742 boilerplate.RawInobjectPropertyAt(index); 1743 if (!maybe_boilerplate_value.has_value()) return {}; 1744 1745 // Note: We don't need to take a compilation dependency verifying the value 1746 // of `boilerplate_value`, since boilerplate properties are constant after 1747 // initialization modulo map migration. We protect against concurrent map 1748 // migrations (other than elements kind transition, which don't affect us) 1749 // via the boilerplate_migration_access lock. 1750 ObjectRef boilerplate_value = maybe_boilerplate_value.value(); 1751 1752 // Uninitialized fields are marked through the `uninitialized_value` Oddball 1753 // (even for Smi representation!), or in the case of Double representation 1754 // through a HeapNumber containing the hole-NaN. Since Double-to-Tagged 1755 // representation changes are done in-place, we may even encounter these 1756 // HeapNumbers in Tagged representation. 1757 // Note that although we create nodes to write `uninitialized_value` into 1758 // the object, the field should be overwritten immediately with a real 1759 // value, and `uninitialized_value` should never be exposed to JS. 1760 ObjectRef uninitialized_oddball = 1761 MakeRef<HeapObject>(broker(), factory()->uninitialized_value()); 1762 if (boilerplate_value.equals(uninitialized_oddball) || 1763 (boilerplate_value.IsHeapNumber() && 1764 boilerplate_value.AsHeapNumber().value_as_bits() == kHoleNanInt64)) { 1765 access.const_field_info = ConstFieldInfo::None(); 1766 } 1767 1768 Node* value; 1769 if (boilerplate_value.IsJSObject()) { 1770 JSObjectRef boilerplate_object = boilerplate_value.AsJSObject(); 1771 base::Optional<Node*> maybe_value = 1772 TryAllocateFastLiteral(effect, control, boilerplate_object, 1773 allocation, max_depth - 1, max_properties); 1774 if (!maybe_value.has_value()) return {}; 1775 value = effect = maybe_value.value(); 1776 } else if (property_details.representation().IsDouble()) { 1777 double number = boilerplate_value.AsHeapNumber().value(); 1778 // Allocate a mutable HeapNumber box and store the value into it. 1779 AllocationBuilder builder(jsgraph(), effect, control); 1780 builder.Allocate(HeapNumber::kSize, allocation); 1781 builder.Store(AccessBuilder::ForMap(), 1782 MakeRef(broker(), factory()->heap_number_map())); 1783 builder.Store(AccessBuilder::ForHeapNumberValue(), 1784 jsgraph()->Constant(number)); 1785 value = effect = builder.Finish(); 1786 } else { 1787 // It's fine to store the 'uninitialized' Oddball into a Smi field since 1788 // it will get overwritten anyways and the store's MachineType (AnyTagged) 1789 // is compatible with it. 1790 DCHECK_IMPLIES(property_details.representation().IsSmi() && 1791 !boilerplate_value.IsSmi(), 1792 boilerplate_value.equals(uninitialized_oddball)); 1793 value = jsgraph()->Constant(boilerplate_value); 1794 } 1795 inobject_fields.push_back(std::make_pair(access, value)); 1796 } 1797 1798 // Fill slack at the end of the boilerplate object with filler maps. 1799 int const boilerplate_length = boilerplate_map.GetInObjectProperties(); 1800 for (int index = static_cast<int>(inobject_fields.size()); 1801 index < boilerplate_length; ++index) { 1802 DCHECK(!V8_MAP_PACKING_BOOL); 1803 // TODO(wenyuzhao): Fix incorrect MachineType when V8_MAP_PACKING is 1804 // enabled. 1805 FieldAccess access = 1806 AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index); 1807 Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map()); 1808 inobject_fields.push_back(std::make_pair(access, value)); 1809 } 1810 1811 // Setup the elements backing store. 1812 base::Optional<Node*> maybe_elements = TryAllocateFastLiteralElements( 1813 effect, control, boilerplate, allocation, max_depth, max_properties); 1814 if (!maybe_elements.has_value()) return {}; 1815 Node* elements = maybe_elements.value(); 1816 if (elements->op()->EffectOutputCount() > 0) effect = elements; 1817 1818 // Actually allocate and initialize the object. 1819 AllocationBuilder builder(jsgraph(), effect, control); 1820 builder.Allocate(boilerplate_map.instance_size(), allocation, 1821 Type::For(boilerplate_map)); 1822 builder.Store(AccessBuilder::ForMap(), boilerplate_map); 1823 builder.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(), 1824 jsgraph()->EmptyFixedArrayConstant()); 1825 builder.Store(AccessBuilder::ForJSObjectElements(), elements); 1826 if (boilerplate.IsJSArray()) { 1827 JSArrayRef boilerplate_array = boilerplate.AsJSArray(); 1828 builder.Store(AccessBuilder::ForJSArrayLength( 1829 boilerplate_array.map().elements_kind()), 1830 boilerplate_array.GetBoilerplateLength()); 1831 } 1832 for (auto const& inobject_field : inobject_fields) { 1833 builder.Store(inobject_field.first, inobject_field.second); 1834 } 1835 return builder.Finish(); 1836} 1837 1838base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteralElements( 1839 Node* effect, Node* control, JSObjectRef boilerplate, 1840 AllocationType allocation, int max_depth, int* max_properties) { 1841 DCHECK_GT(max_depth, 0); 1842 DCHECK_GE(*max_properties, 0); 1843 1844 base::Optional<FixedArrayBaseRef> maybe_boilerplate_elements = 1845 boilerplate.elements(kRelaxedLoad); 1846 if (!maybe_boilerplate_elements.has_value()) return {}; 1847 FixedArrayBaseRef boilerplate_elements = maybe_boilerplate_elements.value(); 1848 // Protect against concurrent changes to the boilerplate object by checking 1849 // for an identical value at the end of the compilation. 1850 dependencies()->DependOnObjectSlotValue( 1851 boilerplate, JSObject::kElementsOffset, boilerplate_elements); 1852 1853 // Empty or copy-on-write elements just store a constant. 1854 int const elements_length = boilerplate_elements.length(); 1855 MapRef elements_map = boilerplate_elements.map(); 1856 // Protect against concurrent changes to the boilerplate object by checking 1857 // for an identical value at the end of the compilation. 1858 dependencies()->DependOnObjectSlotValue(boilerplate_elements, 1859 HeapObject::kMapOffset, elements_map); 1860 if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) { 1861 if (allocation == AllocationType::kOld && 1862 !boilerplate.IsElementsTenured(boilerplate_elements)) { 1863 return {}; 1864 } 1865 return jsgraph()->Constant(boilerplate_elements); 1866 } 1867 1868 // Compute the elements to store first (might have effects). 1869 ZoneVector<Node*> elements_values(elements_length, zone()); 1870 if (boilerplate_elements.IsFixedDoubleArray()) { 1871 int const size = FixedDoubleArray::SizeFor(boilerplate_elements.length()); 1872 if (size > kMaxRegularHeapObjectSize) return {}; 1873 1874 FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray(); 1875 for (int i = 0; i < elements_length; ++i) { 1876 Float64 value = elements.GetFromImmutableFixedDoubleArray(i); 1877 elements_values[i] = value.is_hole_nan() 1878 ? jsgraph()->TheHoleConstant() 1879 : jsgraph()->Constant(value.get_scalar()); 1880 } 1881 } else { 1882 FixedArrayRef elements = boilerplate_elements.AsFixedArray(); 1883 for (int i = 0; i < elements_length; ++i) { 1884 if ((*max_properties)-- == 0) return {}; 1885 base::Optional<ObjectRef> element_value = elements.TryGet(i); 1886 if (!element_value.has_value()) return {}; 1887 if (element_value->IsJSObject()) { 1888 base::Optional<Node*> object = 1889 TryAllocateFastLiteral(effect, control, element_value->AsJSObject(), 1890 allocation, max_depth - 1, max_properties); 1891 if (!object.has_value()) return {}; 1892 elements_values[i] = effect = *object; 1893 } else { 1894 elements_values[i] = jsgraph()->Constant(*element_value); 1895 } 1896 } 1897 } 1898 1899 // Allocate the backing store array and store the elements. 1900 AllocationBuilder ab(jsgraph(), effect, control); 1901 CHECK(ab.CanAllocateArray(elements_length, elements_map, allocation)); 1902 ab.AllocateArray(elements_length, elements_map, allocation); 1903 ElementAccess const access = boilerplate_elements.IsFixedDoubleArray() 1904 ? AccessBuilder::ForFixedDoubleArrayElement() 1905 : AccessBuilder::ForFixedArrayElement(); 1906 for (int i = 0; i < elements_length; ++i) { 1907 ab.Store(access, jsgraph()->Constant(i), elements_values[i]); 1908 } 1909 return ab.Finish(); 1910} 1911 1912Node* JSCreateLowering::AllocateLiteralRegExp( 1913 Node* effect, Node* control, RegExpBoilerplateDescriptionRef boilerplate) { 1914 MapRef initial_map = 1915 native_context().regexp_function().initial_map(dependencies()); 1916 1917 // Sanity check that JSRegExp object layout hasn't changed. 1918 STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize); 1919 STATIC_ASSERT(JSRegExp::kSourceOffset == JSRegExp::kDataOffset + kTaggedSize); 1920 STATIC_ASSERT(JSRegExp::kFlagsOffset == 1921 JSRegExp::kSourceOffset + kTaggedSize); 1922 STATIC_ASSERT(JSRegExp::kHeaderSize == JSRegExp::kFlagsOffset + kTaggedSize); 1923 STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kHeaderSize); 1924 DCHECK_EQ(JSRegExp::Size(), JSRegExp::kLastIndexOffset + kTaggedSize); 1925 1926 AllocationBuilder builder(jsgraph(), effect, control); 1927 builder.Allocate(JSRegExp::Size(), AllocationType::kYoung, 1928 Type::For(initial_map)); 1929 builder.Store(AccessBuilder::ForMap(), initial_map); 1930 builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), 1931 jsgraph()->EmptyFixedArrayConstant()); 1932 builder.Store(AccessBuilder::ForJSObjectElements(), 1933 jsgraph()->EmptyFixedArrayConstant()); 1934 1935 builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data()); 1936 builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source()); 1937 builder.Store(AccessBuilder::ForJSRegExpFlags(), 1938 jsgraph()->SmiConstant(boilerplate.flags())); 1939 builder.Store(AccessBuilder::ForJSRegExpLastIndex(), 1940 jsgraph()->SmiConstant(JSRegExp::kInitialLastIndexValue)); 1941 1942 return builder.Finish(); 1943} 1944 1945Factory* JSCreateLowering::factory() const { 1946 return jsgraph()->isolate()->factory(); 1947} 1948 1949Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); } 1950 1951CommonOperatorBuilder* JSCreateLowering::common() const { 1952 return jsgraph()->common(); 1953} 1954 1955SimplifiedOperatorBuilder* JSCreateLowering::simplified() const { 1956 return jsgraph()->simplified(); 1957} 1958 1959NativeContextRef JSCreateLowering::native_context() const { 1960 return broker()->target_native_context(); 1961} 1962 1963} // namespace compiler 1964} // namespace internal 1965} // namespace v8 1966