js-create-lowering.cc 81.3 KB
Newer Older
1 2 3 4 5 6
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/js-create-lowering.h"

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 13 14
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#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 20
#include "src/compiler/simplified-operator.h"
#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 28
#include "src/objects/js-promise.h"
#include "src/objects/js-regexp-inl.h"
29
#include "src/objects/objects-inl.h"
30
#include "src/objects/template-objects.h"
31 32 33 34 35 36 37 38

namespace v8 {
namespace internal {
namespace compiler {

namespace {

// Retrieves the frame state holding actual argument values.
39 40 41 42
FrameState GetArgumentsFrameState(FrameState frame_state) {
  FrameState outer_state{NodeProperties::GetFrameStateInput(frame_state)};
  return outer_state.frame_state_info().type() ==
                 FrameStateType::kArgumentsAdaptor
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
             ? outer_state
             : frame_state;
}

// When initializing arrays, we'll unfold the loop if the number of
// elements is known to be of this type.
const int kElementLoopUnrollLimit = 16;

// Limits up to which context allocations are inlined.
const int kFunctionContextAllocationLimit = 16;
const int kBlockContextAllocationLimit = 16;

}  // namespace

Reduction JSCreateLowering::Reduce(Node* node) {
  switch (node->opcode()) {
    case IrOpcode::kJSCreate:
      return ReduceJSCreate(node);
    case IrOpcode::kJSCreateArguments:
      return ReduceJSCreateArguments(node);
    case IrOpcode::kJSCreateArray:
      return ReduceJSCreateArray(node);
65 66
    case IrOpcode::kJSCreateArrayIterator:
      return ReduceJSCreateArrayIterator(node);
67 68
    case IrOpcode::kJSCreateAsyncFunctionObject:
      return ReduceJSCreateAsyncFunctionObject(node);
69 70
    case IrOpcode::kJSCreateBoundFunction:
      return ReduceJSCreateBoundFunction(node);
71 72
    case IrOpcode::kJSCreateClosure:
      return ReduceJSCreateClosure(node);
73 74
    case IrOpcode::kJSCreateCollectionIterator:
      return ReduceJSCreateCollectionIterator(node);
75 76
    case IrOpcode::kJSCreateIterResultObject:
      return ReduceJSCreateIterResultObject(node);
77 78
    case IrOpcode::kJSCreateStringIterator:
      return ReduceJSCreateStringIterator(node);
79 80
    case IrOpcode::kJSCreateKeyValueArray:
      return ReduceJSCreateKeyValueArray(node);
81 82
    case IrOpcode::kJSCreatePromise:
      return ReduceJSCreatePromise(node);
83 84
    case IrOpcode::kJSCreateLiteralArray:
    case IrOpcode::kJSCreateLiteralObject:
85 86 87
      return ReduceJSCreateLiteralArrayOrObject(node);
    case IrOpcode::kJSCreateLiteralRegExp:
      return ReduceJSCreateLiteralRegExp(node);
88 89
    case IrOpcode::kJSGetTemplateObject:
      return ReduceJSGetTemplateObject(node);
90 91
    case IrOpcode::kJSCreateEmptyLiteralArray:
      return ReduceJSCreateEmptyLiteralArray(node);
92 93
    case IrOpcode::kJSCreateEmptyLiteralObject:
      return ReduceJSCreateEmptyLiteralObject(node);
94 95 96 97 98 99 100 101
    case IrOpcode::kJSCreateFunctionContext:
      return ReduceJSCreateFunctionContext(node);
    case IrOpcode::kJSCreateWithContext:
      return ReduceJSCreateWithContext(node);
    case IrOpcode::kJSCreateCatchContext:
      return ReduceJSCreateCatchContext(node);
    case IrOpcode::kJSCreateBlockContext:
      return ReduceJSCreateBlockContext(node);
102 103
    case IrOpcode::kJSCreateGeneratorObject:
      return ReduceJSCreateGeneratorObject(node);
104 105
    case IrOpcode::kJSCreateObject:
      return ReduceJSCreateObject(node);
106 107 108 109 110 111 112 113 114 115
    default:
      break;
  }
  return NoChange();
}

Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
  Node* const new_target = NodeProperties::GetValueInput(node, 1);
  Node* const effect = NodeProperties::GetEffectInput(node);
116
  Node* const control = NodeProperties::GetControlInput(node);
117

118 119 120
  base::Optional<MapRef> initial_map =
      NodeProperties::GetJSCreateMap(broker(), node);
  if (!initial_map.has_value()) return NoChange();
121

122 123
  JSFunctionRef original_constructor =
      HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction();
124 125 126
  SlackTrackingPrediction slack_tracking_prediction =
      dependencies()->DependOnInitialMapInstanceSizePrediction(
          original_constructor);
127 128 129

  // Emit code to allocate the JSObject instance for the
  // {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 135 136
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
137 138
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
139
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(*initial_map, i),
140
            jsgraph()->UndefinedConstant());
141
  }
142 143 144 145

  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
146 147 148 149 150
}

Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
  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(broker(),
155
                               state_info.shared_info().ToHandleChecked());
156 157 158

  // Use the ArgumentsAccessStub for materializing both mapped and unmapped
  // arguments object, but only for non-inlined (i.e. outermost) frames.
159
  if (!frame_state.has_outer_frame_state()) {
160 161
    switch (type) {
      case CreateArgumentsType::kMappedArguments: {
162
        // TODO(turbofan): Duplicate parameters are not handled yet.
163
        if (shared.has_duplicate_parameters()) return NoChange();
164 165 166
        Node* const callee = NodeProperties::GetValueInput(node, 0);
        Node* const context = NodeProperties::GetContextInput(node);
        Node* effect = NodeProperties::GetEffectInput(node);
167
        Node* const arguments_length =
168
            graph()->NewNode(simplified()->ArgumentsLength());
169 170
        // Allocate the elements backing store.
        bool has_aliased_arguments = false;
171 172 173 174 175
        Node* const elements = effect = TryAllocateAliasedArguments(
            effect, control, context, arguments_length, shared,
            &has_aliased_arguments);
        if (elements == nullptr) return NoChange();

176
        // Load the arguments object map.
177 178
        Node* const arguments_map = jsgraph()->Constant(
            has_aliased_arguments
179 180
                ? native_context().fast_aliased_arguments_map()
                : 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 185
        a.Allocate(JSSloppyArgumentsObject::kSize);
        a.Store(AccessBuilder::ForMap(), arguments_map);
186 187
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
                jsgraph()->EmptyFixedArrayConstant());
188 189 190 191 192
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
        a.Store(AccessBuilder::ForArgumentsCallee(), callee);
        RelaxControls(node);
        a.FinishAndChange(node);
193 194
        return Changed(node);
      }
195 196
      case CreateArgumentsType::kUnmappedArguments: {
        Node* effect = NodeProperties::GetEffectInput(node);
197
        Node* const arguments_length =
198
            graph()->NewNode(simplified()->ArgumentsLength());
199 200
        // Allocate the elements backing store.
        Node* const elements = effect =
201 202 203
            graph()->NewNode(simplified()->NewArgumentsElements(
                                 CreateArgumentsType::kUnmappedArguments,
                                 shared.internal_formal_parameter_count()),
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 212
        a.Allocate(JSStrictArgumentsObject::kSize);
        a.Store(AccessBuilder::ForMap(), arguments_map);
213 214
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
                jsgraph()->EmptyFixedArrayConstant());
215 216 217 218 219 220
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
        RelaxControls(node);
        a.FinishAndChange(node);
        return Changed(node);
      }
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(
226
            simplified()->RestLength(shared.internal_formal_parameter_count()));
227
        // Allocate the elements backing store.
228
        Node* const elements = effect =
229 230 231
            graph()->NewNode(simplified()->NewArgumentsElements(
                                 CreateArgumentsType::kRestParameter,
                                 shared.internal_formal_parameter_count()),
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 239
        STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize);
        a.Allocate(JSArray::kHeaderSize);
240
        a.Store(AccessBuilder::ForMap(), jsarray_map);
241 242
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
                jsgraph()->EmptyFixedArrayConstant());
243 244 245 246
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), rest_length);
        RelaxControls(node);
        a.FinishAndChange(node);
247 248
        return Changed(node);
      }
249
    }
250
    UNREACHABLE();
251 252 253
  }
  // Use inline allocation for all mapped arguments objects within inlined
  // (i.e. non-outermost) frames, independent of the object size.
254
  DCHECK_EQ(frame_state.outer_frame_state()->opcode(), IrOpcode::kFrameState);
255 256
  switch (type) {
    case CreateArgumentsType::kMappedArguments: {
257 258 259
      Node* const callee = NodeProperties::GetValueInput(node, 0);
      Node* const context = NodeProperties::GetContextInput(node);
      Node* effect = NodeProperties::GetEffectInput(node);
260
      // TODO(turbofan): Duplicate parameters are not handled yet.
261
      if (shared.has_duplicate_parameters()) return NoChange();
262 263 264
      // Choose the correct frame state and frame state info depending on
      // whether there conceptually is an arguments adaptor frame in the call
      // chain.
265 266
      FrameState args_state = GetArgumentsFrameState(frame_state);
      if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
267 268 269 270 271
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
272
      FrameStateInfo args_state_info = args_state.frame_state_info();
273
      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
274 275
      // Prepare element backing store to be used by arguments object.
      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 283
          has_aliased_arguments ? native_context().fast_aliased_arguments_map()
                                : 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 290
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
              jsgraph()->EmptyFixedArrayConstant());
291 292 293 294 295 296
      a.Store(AccessBuilder::ForJSObjectElements(), elements);
      a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
      a.Store(AccessBuilder::ForArgumentsCallee(), callee);
      RelaxControls(node);
      a.FinishAndChange(node);
      return Changed(node);
297 298
    }
    case CreateArgumentsType::kUnmappedArguments: {
299 300 301 302 303 304
      // Use inline allocation for all unmapped arguments objects within inlined
      // (i.e. non-outermost) frames, independent of the object size.
      Node* effect = NodeProperties::GetEffectInput(node);
      // Choose the correct frame state and frame state info depending on
      // whether there conceptually is an arguments adaptor frame in the call
      // chain.
305 306
      FrameState args_state = GetArgumentsFrameState(frame_state);
      if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
307 308 309 310 311
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
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 316
      Node* const elements = TryAllocateArguments(effect, control, args_state);
      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 327
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
              jsgraph()->EmptyFixedArrayConstant());
328 329 330 331 332
      a.Store(AccessBuilder::ForJSObjectElements(), elements);
      a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
      RelaxControls(node);
      a.FinishAndChange(node);
      return Changed(node);
333 334
    }
    case CreateArgumentsType::kRestParameter: {
335
      int start_index = shared.internal_formal_parameter_count();
336 337 338 339 340 341
      // Use inline allocation for all unmapped arguments objects within inlined
      // (i.e. non-outermost) frames, independent of the object size.
      Node* effect = NodeProperties::GetEffectInput(node);
      // Choose the correct frame state and frame state info depending on
      // whether there conceptually is an arguments adaptor frame in the call
      // chain.
342 343
      FrameState args_state = GetArgumentsFrameState(frame_state);
      if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
344 345 346 347 348
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
349
      FrameStateInfo args_state_info = args_state.frame_state_info();
350 351
      // Prepare element backing store to be used by the rest array.
      Node* const elements =
352 353
          TryAllocateRestArguments(effect, control, args_state, start_index);
      if (elements == nullptr) return NoChange();
354
      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
355
      // Load the JSArray object map.
356 357
      Node* const jsarray_map =
          jsgraph()->Constant(native_context().js_array_packed_elements_map());
358
      // Actually allocate and initialize the jsarray.
359
      AllocationBuilder a(jsgraph(), effect, control);
360 361 362 363

      // -1 to minus receiver
      int argument_count = args_state_info.parameter_count() - 1;
      int length = std::max(0, argument_count - start_index);
364 365
      STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize);
      a.Allocate(JSArray::kHeaderSize);
366
      a.Store(AccessBuilder::ForMap(), jsarray_map);
367 368
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
              jsgraph()->EmptyFixedArrayConstant());
369
      a.Store(AccessBuilder::ForJSObjectElements(), elements);
370
      a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
371 372 373 374 375 376
              jsgraph()->Constant(length));
      RelaxControls(node);
      a.FinishAndChange(node);
      return Changed(node);
    }
  }
377
  UNREACHABLE();
378 379
}

380 381 382 383 384
Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateGeneratorObject, node->opcode());
  Node* const closure = NodeProperties::GetValueInput(node, 0);
  Node* const receiver = NodeProperties::GetValueInput(node, 1);
  Node* const context = NodeProperties::GetContextInput(node);
385
  Type const closure_type = NodeProperties::GetType(closure);
386 387
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* const control = NodeProperties::GetControlInput(node);
388
  if (closure_type.IsHeapConstant()) {
389 390 391
    DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction());
    JSFunctionRef js_function =
        closure_type.AsHeapConstant()->Ref().AsJSFunction();
392
    if (!js_function.has_initial_map()) return NoChange();
393

394 395
    SlackTrackingPrediction slack_tracking_prediction =
        dependencies()->DependOnInitialMapInstanceSizePrediction(js_function);
396

397
    MapRef initial_map = js_function.initial_map();
398 399
    DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE ||
           initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
400

401
    // Allocate a register file.
402
    SharedFunctionInfoRef shared = js_function.shared();
403 404
    DCHECK(shared.HasBytecodeArray());
    int parameter_count_no_receiver = shared.internal_formal_parameter_count();
405 406 407
    int length = parameter_count_no_receiver +
                 shared.GetBytecodeArray().register_count();
    MapRef fixed_array_map(broker(), factory()->fixed_array_map());
408
    AllocationBuilder ab(jsgraph(), effect, control);
409 410 411 412 413
    if (!ab.CanAllocateArray(length, fixed_array_map)) {
      return NoChange();
    }
    ab.AllocateArray(length, fixed_array_map);
    for (int i = 0; i < length; ++i) {
414 415 416
      ab.Store(AccessBuilder::ForFixedArraySlot(i),
               jsgraph()->UndefinedConstant());
    }
417
    Node* parameters_and_registers = effect = ab.Finish();
418

419
    // Emit code to allocate the JS[Async]GeneratorObject instance.
420
    AllocationBuilder a(jsgraph(), effect, control);
421
    a.Allocate(slack_tracking_prediction.instance_size());
422 423
    Node* undefined = jsgraph()->UndefinedConstant();
    a.Store(AccessBuilder::ForMap(), initial_map);
424 425 426 427
    a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
            jsgraph()->EmptyFixedArrayConstant());
    a.Store(AccessBuilder::ForJSObjectElements(),
            jsgraph()->EmptyFixedArrayConstant());
428 429 430 431 432 433 434 435
    a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
    a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
    a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver);
    a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(), undefined);
    a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(),
            jsgraph()->Constant(JSGeneratorObject::kNext));
    a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
            jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
436 437
    a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
            parameters_and_registers);
438

439
    if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
440
      a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined);
441 442
      a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(),
              jsgraph()->ZeroConstant());
443 444 445
    }

    // Handle in-object properties, too.
446 447
    for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
         ++i) {
448 449
      a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
              undefined);
450 451 452 453 454 455 456
    }
    a.FinishAndChange(node);
    return Changed(node);
  }
  return NoChange();
}

457 458
// Constructs an array with a variable {length} when no upper bound
// is known for the capacity.
459
Reduction JSCreateLowering::ReduceNewArray(
460
    Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind,
461
    AllocationType allocation,
462
    const SlackTrackingPrediction& slack_tracking_prediction) {
463 464 465 466 467 468
  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Constructing an Array via new Array(N) where N is an unsigned
  // integer, always creates a holey backing store.
469
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
470 471
      initial_map,
      initial_map.AsElementsKind(GetHoleyElementsKind(elements_kind)));
472

473 474 475 476 477 478
  // Because CheckBounds performs implicit conversion from string to number, an
  // additional CheckNumber is required to behave correctly for calls with a
  // single string argument.
  length = effect = graph()->NewNode(
      simplified()->CheckNumber(FeedbackSource{}), length, effect, control);

479 480 481 482
  // Check that the {limit} is an unsigned integer in the valid range.
  // This has to be kept in sync with src/runtime/runtime-array.cc,
  // where this limit is protected.
  length = effect = graph()->NewNode(
483
      simplified()->CheckBounds(FeedbackSource()), length,
484 485 486 487
      jsgraph()->Constant(JSArray::kInitialMaxFastElementArray), effect,
      control);

  // Construct elements and properties for the resulting JSArray.
488
  Node* elements = effect =
489
      graph()->NewNode(IsDoubleElementsKind(initial_map.elements_kind())
490 491
                           ? simplified()->NewDoubleElements(allocation)
                           : simplified()->NewSmiOrObjectElements(allocation),
492
                       length, effect, control);
493 494

  // Perform the allocation of the actual JSArray object.
495
  AllocationBuilder a(jsgraph(), effect, control);
496
  a.Allocate(slack_tracking_prediction.instance_size(), allocation);
497
  a.Store(AccessBuilder::ForMap(), initial_map);
498 499
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
500
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
501
  a.Store(AccessBuilder::ForJSArrayLength(initial_map.elements_kind()), length);
502 503
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
504
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
505 506 507 508 509 510 511 512 513
            jsgraph()->UndefinedConstant());
  }
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

// Constructs an array with a variable {length} when an actual
// upper bound is known for the {capacity}.
514 515
Reduction JSCreateLowering::ReduceNewArray(
    Node* node, Node* length, int capacity, MapRef initial_map,
516
    ElementsKind elements_kind, AllocationType allocation,
517
    const SlackTrackingPrediction& slack_tracking_prediction) {
518 519
  DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
         node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
520
  DCHECK(NodeProperties::GetType(length).Is(Type::Number()));
521 522 523
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

524
  // Determine the appropriate elements kind.
525
  if (NodeProperties::GetType(length).Max() > 0.0) {
526 527
    elements_kind = GetHoleyElementsKind(elements_kind);
  }
528 529
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
      initial_map, initial_map.AsElementsKind(elements_kind));
530
  DCHECK(IsFastElementsKind(elements_kind));
531 532 533 534 535 536 537

  // Setup elements and properties.
  Node* elements;
  if (capacity == 0) {
    elements = jsgraph()->EmptyFixedArrayConstant();
  } else {
    elements = effect =
538
        AllocateElements(effect, control, elements_kind, capacity, allocation);
539 540 541
  }

  // Perform the allocation of the actual JSArray object.
542
  AllocationBuilder a(jsgraph(), effect, control);
543
  a.Allocate(slack_tracking_prediction.instance_size(), allocation);
544
  a.Store(AccessBuilder::ForMap(), initial_map);
545 546
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
547 548
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
549 550
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
551
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
552 553
            jsgraph()->UndefinedConstant());
  }
554 555 556 557 558
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

559 560
Reduction JSCreateLowering::ReduceNewArray(
    Node* node, std::vector<Node*> values, MapRef initial_map,
561
    ElementsKind elements_kind, AllocationType allocation,
562
    const SlackTrackingPrediction& slack_tracking_prediction) {
563 564 565 566
  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

567
  // Determine the appropriate elements kind.
568
  DCHECK(IsFastElementsKind(elements_kind));
569 570
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
      initial_map, initial_map.AsElementsKind(elements_kind));
571 572 573 574

  // Check {values} based on the {elements_kind}. These checks are guarded
  // by the {elements_kind} feedback on the {site}, so it's safe to just
  // deoptimize in this case.
575
  if (IsSmiElementsKind(elements_kind)) {
576
    for (auto& value : values) {
577
      if (!NodeProperties::GetType(value).Is(Type::SignedSmall())) {
578
        value = effect = graph()->NewNode(
579
            simplified()->CheckSmi(FeedbackSource()), value, effect, control);
580 581
      }
    }
582
  } else if (IsDoubleElementsKind(elements_kind)) {
583
    for (auto& value : values) {
584
      if (!NodeProperties::GetType(value).Is(Type::Number())) {
585
        value = effect =
586
            graph()->NewNode(simplified()->CheckNumber(FeedbackSource()), value,
587
                             effect, control);
588 589 590 591 592 593 594 595
      }
      // Make sure we do not store signaling NaNs into double arrays.
      value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
    }
  }

  // Setup elements, properties and length.
  Node* elements = effect =
596
      AllocateElements(effect, control, elements_kind, values, allocation);
597 598 599
  Node* length = jsgraph()->Constant(static_cast<int>(values.size()));

  // Perform the allocation of the actual JSArray object.
600
  AllocationBuilder a(jsgraph(), effect, control);
601
  a.Allocate(slack_tracking_prediction.instance_size(), allocation);
602
  a.Store(AccessBuilder::ForMap(), initial_map);
603 604
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
605 606
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
607 608
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
609
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
610 611
            jsgraph()->UndefinedConstant());
  }
612 613 614 615 616
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

617 618 619
Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
620
  int const arity = static_cast<int>(p.arity());
621 622 623 624
  base::Optional<AllocationSiteRef> site_ref;
  {
    Handle<AllocationSite> site;
    if (p.site().ToHandle(&site)) {
625
      site_ref = AllocationSiteRef(broker(), site);
626
    }
627
  }
628
  AllocationType allocation = AllocationType::kYoung;
629 630 631 632 633

  base::Optional<MapRef> initial_map =
      NodeProperties::GetJSCreateMap(broker(), node);
  if (!initial_map.has_value()) return NoChange();

634
  Node* new_target = NodeProperties::GetValueInput(node, 1);
635 636 637 638 639
  JSFunctionRef original_constructor =
      HeapObjectMatcher(new_target).Ref(broker()).AsJSFunction();
  SlackTrackingPrediction slack_tracking_prediction =
      dependencies()->DependOnInitialMapInstanceSizePrediction(
          original_constructor);
640

641 642 643 644 645 646 647 648 649 650 651 652
  // Tells whether we are protected by either the {site} or a
  // protector cell to do certain speculative optimizations.
  bool can_inline_call = false;

  // Check if we have a feedback {site} on the {node}.
  ElementsKind elements_kind = initial_map->elements_kind();
  if (site_ref) {
    elements_kind = site_ref->GetElementsKind();
    can_inline_call = site_ref->CanInlineCall();
    allocation = dependencies()->DependOnPretenureMode(*site_ref);
    dependencies()->DependOnElementsKind(*site_ref);
  } else {
653
    PropertyCellRef array_constructor_protector(
654
        broker(), factory()->array_constructor_protector());
655
    array_constructor_protector.SerializeAsProtector();
656 657
    can_inline_call = array_constructor_protector.value().AsSmi() ==
                      Protectors::kProtectorValid;
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
  }

  if (arity == 0) {
    Node* length = jsgraph()->ZeroConstant();
    int capacity = JSArray::kPreallocatedArrayElements;
    return ReduceNewArray(node, length, capacity, *initial_map, elements_kind,
                          allocation, slack_tracking_prediction);
  } else if (arity == 1) {
    Node* length = NodeProperties::GetValueInput(node, 2);
    Type length_type = NodeProperties::GetType(length);
    if (!length_type.Maybe(Type::Number())) {
      // Handle the single argument case, where we know that the value
      // cannot be a valid Array length.
      elements_kind = GetMoreGeneralElementsKind(
          elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
                                                            : PACKED_ELEMENTS);
      return ReduceNewArray(node, std::vector<Node*>{length}, *initial_map,
                            elements_kind, allocation,
                            slack_tracking_prediction);
    }
    if (length_type.Is(Type::SignedSmall()) && length_type.Min() >= 0 &&
        length_type.Max() <= kElementLoopUnrollLimit &&
        length_type.Min() == length_type.Max()) {
      int capacity = static_cast<int>(length_type.Max());
682 683 684
      // Replace length with a constant in order to protect against a potential
      // typer bug leading to length > capacity.
      length = jsgraph()->Constant(capacity);
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
      return ReduceNewArray(node, length, capacity, *initial_map, elements_kind,
                            allocation, slack_tracking_prediction);
    }
    if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
      return ReduceNewArray(node, length, *initial_map, elements_kind,
                            allocation, slack_tracking_prediction);
    }
  } else if (arity <= JSArray::kInitialMaxFastElementArray) {
    // Gather the values to store into the newly created array.
    bool values_all_smis = true, values_all_numbers = true,
         values_any_nonnumber = false;
    std::vector<Node*> values;
    values.reserve(p.arity());
    for (int i = 0; i < arity; ++i) {
      Node* value = NodeProperties::GetValueInput(node, 2 + i);
      Type value_type = NodeProperties::GetType(value);
      if (!value_type.Is(Type::SignedSmall())) {
        values_all_smis = false;
      }
      if (!value_type.Is(Type::Number())) {
        values_all_numbers = false;
706
      }
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
      if (!value_type.Maybe(Type::Number())) {
        values_any_nonnumber = true;
      }
      values.push_back(value);
    }

    // Try to figure out the ideal elements kind statically.
    if (values_all_smis) {
      // Smis can be stored with any elements kind.
    } else if (values_all_numbers) {
      elements_kind = GetMoreGeneralElementsKind(
          elements_kind, IsHoleyElementsKind(elements_kind)
                             ? HOLEY_DOUBLE_ELEMENTS
                             : PACKED_DOUBLE_ELEMENTS);
    } else if (values_any_nonnumber) {
      elements_kind = GetMoreGeneralElementsKind(
          elements_kind, IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
                                                            : PACKED_ELEMENTS);
    } else if (!can_inline_call) {
      // We have some crazy combination of types for the {values} where
      // there's no clear decision on the elements kind statically. And
      // we don't have a protection against deoptimization loops for the
      // checks that are introduced in the call to ReduceNewArray, so
      // we cannot inline this invocation of the Array constructor here.
      return NoChange();
732
    }
733 734
    return ReduceNewArray(node, values, *initial_map, elements_kind, allocation,
                          slack_tracking_prediction);
735
  }
736
  return NoChange();
737 738
}

739 740 741 742 743 744 745 746 747
Reduction JSCreateLowering::ReduceJSCreateArrayIterator(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateArrayIterator, node->opcode());
  CreateArrayIteratorParameters const& p =
      CreateArrayIteratorParametersOf(node->op());
  Node* iterated_object = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Create the JSArrayIterator result.
748
  AllocationBuilder a(jsgraph(), effect, control);
749
  a.Allocate(JSArrayIterator::kHeaderSize, AllocationType::kYoung,
750
             Type::OtherObject());
751
  a.Store(AccessBuilder::ForMap(),
752
          native_context().initial_array_iterator_map());
753
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
754 755 756 757 758 759 760 761 762 763 764 765 766
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSArrayIteratorIteratedObject(), iterated_object);
  a.Store(AccessBuilder::ForJSArrayIteratorNextIndex(),
          jsgraph()->ZeroConstant());
  a.Store(AccessBuilder::ForJSArrayIteratorKind(),
          jsgraph()->Constant(static_cast<int>(p.kind())));
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

767 768 769 770 771 772 773 774 775 776 777
Reduction JSCreateLowering::ReduceJSCreateAsyncFunctionObject(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateAsyncFunctionObject, node->opcode());
  int const register_count = RegisterCountOf(node->op());
  Node* closure = NodeProperties::GetValueInput(node, 0);
  Node* receiver = NodeProperties::GetValueInput(node, 1);
  Node* promise = NodeProperties::GetValueInput(node, 2);
  Node* context = NodeProperties::GetContextInput(node);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Create the register file.
778
  MapRef fixed_array_map(broker(), factory()->fixed_array_map());
779
  AllocationBuilder ab(jsgraph(), effect, control);
780 781 782 783
  if (!ab.CanAllocateArray(register_count, fixed_array_map)) {
    return NoChange();
  }
  ab.AllocateArray(register_count, fixed_array_map);
784 785 786 787 788 789 790 791
  for (int i = 0; i < register_count; ++i) {
    ab.Store(AccessBuilder::ForFixedArraySlot(i),
             jsgraph()->UndefinedConstant());
  }
  Node* parameters_and_registers = effect = ab.Finish();

  // Create the JSAsyncFunctionObject result.
  AllocationBuilder a(jsgraph(), effect, control);
792
  a.Allocate(JSAsyncFunctionObject::kHeaderSize);
793 794
  a.Store(AccessBuilder::ForMap(),
          native_context().async_function_object_map());
795 796 797 798
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
  a.Store(AccessBuilder::ForJSGeneratorObjectContext(), context);
  a.Store(AccessBuilder::ForJSGeneratorObjectFunction(), closure);
  a.Store(AccessBuilder::ForJSGeneratorObjectReceiver(), receiver);
  a.Store(AccessBuilder::ForJSGeneratorObjectInputOrDebugPos(),
          jsgraph()->UndefinedConstant());
  a.Store(AccessBuilder::ForJSGeneratorObjectResumeMode(),
          jsgraph()->Constant(JSGeneratorObject::kNext));
  a.Store(AccessBuilder::ForJSGeneratorObjectContinuation(),
          jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting));
  a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
          parameters_and_registers);
  a.Store(AccessBuilder::ForJSAsyncFunctionObjectPromise(), promise);
  a.FinishAndChange(node);
  return Changed(node);
}

815 816
namespace {

817 818 819
MapRef MapForCollectionIterationKind(const NativeContextRef& native_context,
                                     CollectionKind collection_kind,
                                     IterationKind iteration_kind) {
820 821 822 823 824 825
  switch (collection_kind) {
    case CollectionKind::kSet:
      switch (iteration_kind) {
        case IterationKind::kKeys:
          UNREACHABLE();
        case IterationKind::kValues:
826
          return native_context.set_value_iterator_map();
827
        case IterationKind::kEntries:
828
          return native_context.set_key_value_iterator_map();
829 830 831 832 833
      }
      break;
    case CollectionKind::kMap:
      switch (iteration_kind) {
        case IterationKind::kKeys:
834
          return native_context.map_key_iterator_map();
835
        case IterationKind::kValues:
836
          return native_context.map_value_iterator_map();
837
        case IterationKind::kEntries:
838
          return native_context.map_key_value_iterator_map();
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
      }
      break;
  }
  UNREACHABLE();
}

}  // namespace

Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateCollectionIterator, node->opcode());
  CreateCollectionIteratorParameters const& p =
      CreateCollectionIteratorParametersOf(node->op());
  Node* iterated_object = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Load the OrderedHashTable from the {receiver}.
  Node* table = effect = graph()->NewNode(
      simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
      iterated_object, effect, control);

860
  // Create the JSCollectionIterator result.
861
  AllocationBuilder a(jsgraph(), effect, control);
862
  a.Allocate(JSCollectionIterator::kHeaderSize, AllocationType::kYoung,
863
             Type::OtherObject());
864
  a.Store(AccessBuilder::ForMap(),
865 866
          MapForCollectionIterationKind(native_context(), p.collection_kind(),
                                        p.iteration_kind()));
867
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
868 869 870 871 872 873 874 875 876 877 878
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSCollectionIteratorTable(), table);
  a.Store(AccessBuilder::ForJSCollectionIteratorIndex(),
          jsgraph()->ZeroConstant());
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

879 880 881 882 883
Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateBoundFunction, node->opcode());
  CreateBoundFunctionParameters const& p =
      CreateBoundFunctionParametersOf(node->op());
  int const arity = static_cast<int>(p.arity());
884
  MapRef const map(broker(), p.map());
885 886 887 888 889 890 891 892
  Node* bound_target_function = NodeProperties::GetValueInput(node, 0);
  Node* bound_this = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Create the [[BoundArguments]] for the result.
  Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant();
  if (arity > 0) {
893 894 895 896 897 898
    MapRef fixed_array_map(broker(), factory()->fixed_array_map());
    AllocationBuilder ab(jsgraph(), effect, control);
    if (!ab.CanAllocateArray(arity, fixed_array_map)) {
      return NoChange();
    }
    ab.AllocateArray(arity, fixed_array_map);
899
    for (int i = 0; i < arity; ++i) {
900 901
      ab.Store(AccessBuilder::ForFixedArraySlot(i),
               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 913 914 915 916 917 918 919 920 921 922 923
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSBoundFunctionBoundTargetFunction(),
          bound_target_function);
  a.Store(AccessBuilder::ForJSBoundFunctionBoundThis(), bound_this);
  a.Store(AccessBuilder::ForJSBoundFunctionBoundArguments(), bound_arguments);
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

924
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
925 926
  JSCreateClosureNode n(node);
  CreateClosureParameters const& p = n.Parameters();
927
  SharedFunctionInfoRef shared(broker(), p.shared_info());
928
  FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker());
929
  HeapObjectRef code(broker(), p.code());
930 931 932
  Effect effect = n.effect();
  Control control = n.control();
  Node* context = n.context();
933 934 935 936

  // Use inline allocation of closures only for instantiation sites that have
  // seen more than one instantiation, this simplifies the generated code and
  // also serves as a heuristic of which allocation sites benefit from it.
937
  if (!feedback_cell.map().equals(
938
          MapRef(broker(), factory()->many_closures_cell_map()))) {
939
    return NoChange();
940 941
  }

942
  MapRef function_map =
943
      native_context().GetFunctionMapFromIndex(shared.function_map_index());
944 945
  DCHECK(!function_map.IsInobjectSlackTrackingInProgress());
  DCHECK(!function_map.is_dictionary_map());
946

947 948 949 950 951 952 953 954 955
  // TODO(turbofan): We should use the pretenure flag from {p} here,
  // but currently the heuristic in the parser works against us, as
  // it marks closures like
  //
  //   args[l] = function(...) { ... }
  //
  // for old-space allocation, which doesn't always make sense. For
  // example in case of the bluebird-parallel benchmark, where this
  // is a core part of the *promisify* logic (see crbug.com/810132).
956
  AllocationType allocation = AllocationType::kYoung;
957

958
  // Emit code to allocate the JSFunction instance.
959
  STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize);
960
  AllocationBuilder a(jsgraph(), effect, control);
961
  a.Allocate(function_map.instance_size(), allocation, Type::Function());
962
  a.Store(AccessBuilder::ForMap(), function_map);
963
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
964 965 966 967 968
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
  a.Store(AccessBuilder::ForJSFunctionContext(), context);
969
  a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell);
970
  a.Store(AccessBuilder::ForJSFunctionCode(), code);
971
  STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize);
972
  if (function_map.has_prototype_slot()) {
973 974
    a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(),
            jsgraph()->TheHoleConstant());
975
    STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kTaggedSize);
976
  }
977
  for (int i = 0; i < function_map.GetInObjectProperties(); i++) {
978 979 980 981 982 983
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i),
            jsgraph()->UndefinedConstant());
  }
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
984 985
}

986 987 988 989 990 991
Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
  Node* value = NodeProperties::GetValueInput(node, 0);
  Node* done = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);

992
  Node* iterator_result_map =
993
      jsgraph()->Constant(native_context().iterator_result_map());
994 995

  // Emit code to allocate the JSIteratorResult instance.
996
  AllocationBuilder a(jsgraph(), effect, graph()->start());
997 998
  a.Allocate(JSIteratorResult::kSize);
  a.Store(AccessBuilder::ForMap(), iterator_result_map);
999
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
1000 1001 1002 1003 1004
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
  a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
1005
  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize);
1006 1007 1008 1009
  a.FinishAndChange(node);
  return Changed(node);
}

1010 1011 1012 1013 1014
Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
  Node* string = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);

1015 1016
  Node* map =
      jsgraph()->Constant(native_context().initial_string_iterator_map());
1017
  // Allocate new iterator and attach the iterator to this string.
1018
  AllocationBuilder a(jsgraph(), effect, graph()->start());
1019
  a.Allocate(JSStringIterator::kHeaderSize, AllocationType::kYoung,
1020
             Type::OtherObject());
1021
  a.Store(AccessBuilder::ForMap(), map);
1022
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
1023 1024 1025 1026 1027
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSStringIteratorString(), string);
  a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0));
1028
  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kTaggedSize);
1029 1030 1031 1032
  a.FinishAndChange(node);
  return Changed(node);
}

1033 1034 1035 1036 1037 1038
Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
  Node* key = NodeProperties::GetValueInput(node, 0);
  Node* value = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);

1039
  Node* array_map =
1040
      jsgraph()->Constant(native_context().js_array_packed_elements_map());
1041 1042
  Node* length = jsgraph()->Constant(2);

1043
  AllocationBuilder aa(jsgraph(), effect, graph()->start());
1044
  aa.AllocateArray(2, MapRef(broker(), factory()->fixed_array_map()));
1045
  aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1046
           jsgraph()->ZeroConstant(), key);
1047
  aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1048
           jsgraph()->OneConstant(), value);
1049 1050
  Node* elements = aa.Finish();

1051
  AllocationBuilder a(jsgraph(), elements, graph()->start());
1052
  a.Allocate(JSArray::kHeaderSize);
1053
  a.Store(AccessBuilder::ForMap(), array_map);
1054 1055
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
1056
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
1057
  a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length);
1058
  STATIC_ASSERT(JSArray::kHeaderSize == 4 * kTaggedSize);
1059 1060 1061 1062
  a.FinishAndChange(node);
  return Changed(node);
}

1063 1064 1065 1066
Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);

1067
  MapRef promise_map = native_context().promise_function().initial_map();
1068

1069
  AllocationBuilder a(jsgraph(), effect, graph()->start());
1070
  a.Allocate(promise_map.instance_size());
1071
  a.Store(AccessBuilder::ForMap(), promise_map);
1072
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
1073 1074 1075
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
1076 1077
  a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kReactionsOrResultOffset),
          jsgraph()->ZeroConstant());
1078 1079 1080
  STATIC_ASSERT(v8::Promise::kPending == 0);
  a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kFlagsOffset),
          jsgraph()->ZeroConstant());
1081 1082
  STATIC_ASSERT(JSPromise::kHeaderSize == 5 * kTaggedSize);
  for (int offset = JSPromise::kHeaderSize;
1083 1084 1085
       offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
    a.Store(AccessBuilder::ForJSObjectOffset(offset),
            jsgraph()->ZeroConstant());
1086 1087 1088 1089 1090
  }
  a.FinishAndChange(node);
  return Changed(node);
}

1091
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
1092 1093
  DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
         node->opcode() == IrOpcode::kJSCreateLiteralObject);
1094 1095 1096 1097
  JSCreateLiteralOpNode n(node);
  CreateLiteralParameters const& p = n.Parameters();
  Effect effect = n.effect();
  Control control = n.control();
1098 1099 1100 1101
  ProcessedFeedback const& feedback =
      broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback());
  if (!feedback.IsInsufficient()) {
    AllocationSiteRef site = feedback.AsLiteral().value();
1102
    if (site.IsFastLiteral()) {
1103
      AllocationType allocation = AllocationType::kYoung;
1104
      if (FLAG_allocation_site_pretenuring) {
1105
        allocation = dependencies()->DependOnPretenureMode(site);
1106
      }
1107
      dependencies()->DependOnElementsKinds(site);
1108
      JSObjectRef boilerplate = site.boilerplate().value();
1109
      Node* value = effect =
1110
          AllocateFastLiteral(effect, control, boilerplate, allocation);
1111 1112
      ReplaceWithValue(node, value, effect, control);
      return Replace(value);
1113 1114
    }
  }
1115

1116 1117
  return NoChange();
}
1118

1119
Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
1120 1121
  JSCreateEmptyLiteralArrayNode n(node);
  FeedbackParameter const& p = n.Parameters();
1122 1123 1124 1125
  ProcessedFeedback const& feedback =
      broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback());
  if (!feedback.IsInsufficient()) {
    AllocationSiteRef site = feedback.AsLiteral().value();
1126 1127
    DCHECK(!site.PointsToLiteral());
    MapRef initial_map =
1128
        native_context().GetInitialJSArrayMap(site.GetElementsKind());
1129 1130
    AllocationType const allocation =
        dependencies()->DependOnPretenureMode(site);
1131
    dependencies()->DependOnElementsKind(site);
1132
    Node* length = jsgraph()->ZeroConstant();
1133 1134 1135
    DCHECK(!initial_map.IsInobjectSlackTrackingInProgress());
    SlackTrackingPrediction slack_tracking_prediction(
        initial_map, initial_map.instance_size());
1136
    return ReduceNewArray(node, length, 0, initial_map,
1137
                          initial_map.elements_kind(), allocation,
1138
                          slack_tracking_prediction);
1139 1140 1141 1142
  }
  return NoChange();
}

1143
Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
1144 1145 1146 1147 1148
  DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralObject, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Retrieve the initial map for the object.
1149
  MapRef map = native_context().object_function().initial_map();
1150 1151 1152
  DCHECK(!map.is_dictionary_map());
  DCHECK(!map.IsInobjectSlackTrackingInProgress());
  Node* js_object_map = jsgraph()->Constant(map);
1153 1154 1155 1156 1157

  // Setup elements and properties.
  Node* elements = jsgraph()->EmptyFixedArrayConstant();

  // Perform the allocation of the actual JSArray object.
1158
  AllocationBuilder a(jsgraph(), effect, control);
1159
  a.Allocate(map.instance_size());
1160
  a.Store(AccessBuilder::ForMap(), js_object_map);
1161 1162
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
          jsgraph()->EmptyFixedArrayConstant());
1163
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
1164 1165
  for (int i = 0; i < map.GetInObjectProperties(); i++) {
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
1166 1167 1168 1169 1170 1171 1172 1173
            jsgraph()->UndefinedConstant());
  }

  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

1174
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
1175 1176 1177 1178
  JSCreateLiteralRegExpNode n(node);
  CreateLiteralParameters const& p = n.Parameters();
  Effect effect = n.effect();
  Control control = n.control();
1179 1180 1181
  ProcessedFeedback const& feedback =
      broker()->GetFeedbackForRegExpLiteral(p.feedback());
  if (!feedback.IsInsufficient()) {
1182 1183
    RegExpBoilerplateDescriptionRef literal =
        feedback.AsRegExpLiteral().value();
1184
    Node* value = effect = AllocateLiteralRegExp(effect, control, literal);
1185 1186
    ReplaceWithValue(node, value, effect, control);
    return Replace(value);
1187 1188 1189 1190
  }
  return NoChange();
}

1191
Reduction JSCreateLowering::ReduceJSGetTemplateObject(Node* node) {
1192 1193
  JSGetTemplateObjectNode n(node);
  GetTemplateObjectParameters const& parameters = n.Parameters();
1194 1195 1196 1197 1198 1199 1200 1201 1202

  const ProcessedFeedback& feedback =
      broker()->GetFeedbackForTemplateObject(parameters.feedback());
  // TODO(v8:7790): Consider not generating JSGetTemplateObject operator
  // in the BytecodeGraphBuilder in the first place, if template_object is not
  // available.
  if (feedback.IsInsufficient()) return NoChange();

  JSArrayRef template_object = feedback.AsTemplateObject().value();
1203 1204 1205 1206 1207
  Node* value = jsgraph()->Constant(template_object);
  ReplaceWithValue(node, value);
  return Replace(value);
}

1208 1209
Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
1210 1211
  const CreateFunctionContextParameters& parameters =
      CreateFunctionContextParametersOf(node->op());
1212
  ScopeInfoRef scope_info(broker(), parameters.scope_info());
1213 1214
  int slot_count = parameters.slot_count();
  ScopeType scope_type = parameters.scope_type();
1215 1216 1217 1218 1219 1220 1221

  // Use inline allocation for function contexts up to a size limit.
  if (slot_count < kFunctionContextAllocationLimit) {
    // JSCreateFunctionContext[slot_count < limit]](fun)
    Node* effect = NodeProperties::GetEffectInput(node);
    Node* control = NodeProperties::GetControlInput(node);
    Node* context = NodeProperties::GetContextInput(node);
1222
    AllocationBuilder a(jsgraph(), effect, control);
1223
    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2);  // Ensure fully covered.
1224
    int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
1225 1226
    switch (scope_type) {
      case EVAL_SCOPE:
1227
        a.AllocateContext(context_length, native_context().eval_context_map());
1228 1229
        break;
      case FUNCTION_SCOPE:
1230 1231
        a.AllocateContext(context_length,
                          native_context().function_context_map());
1232 1233 1234 1235
        break;
      default:
        UNREACHABLE();
    }
1236 1237
    a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
            scope_info);
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
    for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
      a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
    }
    RelaxControls(node);
    a.FinishAndChange(node);
    return Changed(node);
  }

  return NoChange();
}

Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
1252
  ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1253
  Node* extension = NodeProperties::GetValueInput(node, 0);
1254 1255 1256
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* context = NodeProperties::GetContextInput(node);
1257

1258
  AllocationBuilder a(jsgraph(), effect, control);
1259 1260 1261
  STATIC_ASSERT(Context::MIN_CONTEXT_EXTENDED_SLOTS ==
                3);  // Ensure fully covered.
  a.AllocateContext(Context::MIN_CONTEXT_EXTENDED_SLOTS,
1262
                    native_context().with_context_map());
1263
  a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1264
  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1265
  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1266 1267 1268 1269 1270 1271 1272
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
1273
  ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1274 1275 1276 1277
  Node* exception = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* context = NodeProperties::GetContextInput(node);
1278

1279
  AllocationBuilder a(jsgraph(), effect, control);
1280
  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2);  // Ensure fully covered.
1281
  a.AllocateContext(Context::MIN_CONTEXT_SLOTS + 1,
1282
                    native_context().catch_context_map());
1283
  a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
  a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
          exception);
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
1294
  ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1295
  int const context_length = scope_info.ContextLength();
1296 1297 1298 1299 1300 1301 1302

  // Use inline allocation for block contexts up to a size limit.
  if (context_length < kBlockContextAllocationLimit) {
    // JSCreateBlockContext[scope[length < limit]](fun)
    Node* effect = NodeProperties::GetEffectInput(node);
    Node* control = NodeProperties::GetControlInput(node);
    Node* context = NodeProperties::GetContextInput(node);
1303

1304
    AllocationBuilder a(jsgraph(), effect, control);
1305
    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 2);  // Ensure fully covered.
1306
    a.AllocateContext(context_length, native_context().block_context_map());
1307 1308
    a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
            scope_info);
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
    for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
      a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
    }
    RelaxControls(node);
    a.FinishAndChange(node);
    return Changed(node);
  }

  return NoChange();
}

1321 1322 1323 1324
namespace {
base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
                                          HeapObjectRef prototype) {
  MapRef standard_map =
1325
      broker->target_native_context().object_function().initial_map();
1326 1327 1328
  if (prototype.equals(standard_map.prototype())) {
    return standard_map;
  }
1329
  if (prototype.map().oddball_type() == OddballType::kNull) {
1330 1331
    return broker->target_native_context()
        .slow_object_with_null_prototype_map();
1332 1333 1334 1335 1336 1337 1338 1339
  }
  if (prototype.IsJSObject()) {
    return prototype.AsJSObject().GetObjectCreateMap();
  }
  return base::Optional<MapRef>();
}
}  // namespace

1340 1341 1342 1343 1344
Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateObject, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* prototype = NodeProperties::GetValueInput(node, 0);
1345 1346
  Type prototype_type = NodeProperties::GetType(prototype);
  if (!prototype_type.IsHeapConstant()) return NoChange();
1347

1348
  HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
1349
  auto maybe_instance_map = GetObjectCreateMap(broker(), prototype_const);
1350 1351
  if (!maybe_instance_map) return NoChange();
  MapRef instance_map = maybe_instance_map.value();
1352

1353
  Node* properties = jsgraph()->EmptyFixedArrayConstant();
1354
  if (instance_map.is_dictionary_map()) {
1355
    DCHECK_EQ(prototype_const.map().oddball_type(), OddballType::kNull);
1356
    // Allocate an empty NameDictionary as backing store for the properties.
1357
    MapRef map(broker(), factory()->name_dictionary_map());
1358 1359 1360
    int capacity =
        NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
    DCHECK(base::bits::IsPowerOfTwo(capacity));
1361
    int length = NameDictionary::EntryToIndex(InternalIndex(capacity));
1362 1363
    int size = NameDictionary::SizeFor(length);

1364
    AllocationBuilder a(jsgraph(), effect, control);
1365
    a.Allocate(size, AllocationType::kYoung, Type::Any());
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
    a.Store(AccessBuilder::ForMap(), map);
    // Initialize FixedArray fields.
    a.Store(AccessBuilder::ForFixedArrayLength(),
            jsgraph()->SmiConstant(length));
    // Initialize HashTable fields.
    a.Store(AccessBuilder::ForHashTableBaseNumberOfElements(),
            jsgraph()->SmiConstant(0));
    a.Store(AccessBuilder::ForHashTableBaseNumberOfDeletedElement(),
            jsgraph()->SmiConstant(0));
    a.Store(AccessBuilder::ForHashTableBaseCapacity(),
            jsgraph()->SmiConstant(capacity));
    // Initialize Dictionary fields.
    a.Store(AccessBuilder::ForDictionaryNextEnumerationIndex(),
            jsgraph()->SmiConstant(PropertyDetails::kInitialIndex));
    a.Store(AccessBuilder::ForDictionaryObjectHashIndex(),
            jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
    // Initialize the Properties fields.
    Node* undefined = jsgraph()->UndefinedConstant();
    STATIC_ASSERT(NameDictionary::kElementsStartIndex ==
                  NameDictionary::kObjectHashIndex + 1);
    for (int index = NameDictionary::kElementsStartIndex; index < length;
         index++) {
      a.Store(AccessBuilder::ForFixedArraySlot(index, kNoWriteBarrier),
              undefined);
    }
    properties = effect = a.Finish();
  }

1394
  int const instance_size = instance_map.instance_size();
1395
  if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
1396
  CHECK(!instance_map.IsInobjectSlackTrackingInProgress());
1397 1398 1399

  // Emit code to allocate the JSObject instance for the given
  // {instance_map}.
1400
  AllocationBuilder a(jsgraph(), effect, control);
1401
  a.Allocate(instance_size, AllocationType::kYoung, Type::Any());
1402 1403 1404 1405 1406 1407 1408
  a.Store(AccessBuilder::ForMap(), instance_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  // Initialize Object fields.
  Node* undefined = jsgraph()->UndefinedConstant();
  for (int offset = JSObject::kHeaderSize; offset < instance_size;
1409
       offset += kTaggedSize) {
1410 1411 1412 1413 1414 1415 1416 1417 1418
    a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier),
            undefined);
  }
  Node* value = effect = a.Finish();

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

1419 1420
// Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
1421 1422
Node* JSCreateLowering::TryAllocateArguments(Node* effect, Node* control,
                                             FrameState frame_state) {
1423
  FrameStateInfo state_info = frame_state.frame_state_info();
1424 1425 1426 1427
  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
  if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();

  // Prepare an iterator over argument values recorded in the frame state.
1428
  Node* const parameters = frame_state.parameters();
1429
  StateValuesAccess parameters_access(parameters);
1430
  auto parameters_it = parameters_access.begin_without_receiver();
1431 1432

  // Actually allocate the backing store.
1433 1434 1435 1436 1437 1438
  MapRef fixed_array_map(broker(), factory()->fixed_array_map());
  AllocationBuilder ab(jsgraph(), effect, control);
  if (!ab.CanAllocateArray(argument_count, fixed_array_map)) {
    return nullptr;
  }
  ab.AllocateArray(argument_count, fixed_array_map);
1439
  for (int i = 0; i < argument_count; ++i, ++parameters_it) {
1440
    DCHECK_NOT_NULL(parameters_it.node());
1441 1442
    ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
             parameters_it.node());
1443
  }
1444
  return ab.Finish();
1445 1446 1447 1448
}

// Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
1449 1450 1451
Node* JSCreateLowering::TryAllocateRestArguments(Node* effect, Node* control,
                                                 FrameState frame_state,
                                                 int start_index) {
1452
  FrameStateInfo state_info = frame_state.frame_state_info();
1453 1454 1455 1456 1457
  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
  int num_elements = std::max(0, argument_count - start_index);
  if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();

  // Prepare an iterator over argument values recorded in the frame state.
1458
  Node* const parameters = frame_state.parameters();
1459
  StateValuesAccess parameters_access(parameters);
1460 1461
  auto parameters_it =
      parameters_access.begin_without_receiver_and_skip(start_index);
1462 1463

  // Actually allocate the backing store.
1464 1465 1466 1467 1468 1469
  MapRef fixed_array_map(broker(), factory()->fixed_array_map());
  AllocationBuilder ab(jsgraph(), effect, control);
  if (!ab.CanAllocateArray(num_elements, fixed_array_map)) {
    return nullptr;
  }
  ab.AllocateArray(num_elements, fixed_array_map);
1470
  for (int i = 0; i < num_elements; ++i, ++parameters_it) {
1471
    DCHECK_NOT_NULL(parameters_it.node());
1472 1473
    ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
             parameters_it.node());
1474
  }
1475
  return ab.Finish();
1476 1477 1478 1479 1480
}

// Helper that allocates a FixedArray serving as a parameter map for values
// recorded in the given {frame_state}. Some elements map to slots within the
// given {context}. Serves as backing store for JSCreateArguments nodes.
1481
Node* JSCreateLowering::TryAllocateAliasedArguments(
1482
    Node* effect, Node* control, FrameState frame_state, Node* context,
1483
    const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
1484
  FrameStateInfo state_info = frame_state.frame_state_info();
1485 1486 1487 1488 1489
  int argument_count = state_info.parameter_count() - 1;  // Minus receiver.
  if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();

  // If there is no aliasing, the arguments object elements are not special in
  // any way, we can just return an unmapped backing store instead.
1490
  int parameter_count = shared.internal_formal_parameter_count();
1491
  if (parameter_count == 0) {
1492
    return TryAllocateArguments(effect, control, frame_state);
1493 1494 1495
  }

  // Calculate number of argument values being aliased/mapped.
1496
  int mapped_count = std::min(argument_count, parameter_count);
1497 1498
  *has_aliased_arguments = true;

1499 1500
  MapRef sloppy_arguments_elements_map(
      broker(), factory()->sloppy_arguments_elements_map());
1501
  if (!AllocationBuilder::CanAllocateSloppyArgumentElements(
1502 1503 1504 1505 1506 1507 1508 1509 1510
          mapped_count, sloppy_arguments_elements_map)) {
    return nullptr;
  }

  MapRef fixed_array_map(broker(), factory()->fixed_array_map());
  if (!AllocationBuilder::CanAllocateArray(argument_count, fixed_array_map)) {
    return nullptr;
  }

1511
  // Prepare an iterator over argument values recorded in the frame state.
1512
  Node* const parameters = frame_state.parameters();
1513
  StateValuesAccess parameters_access(parameters);
1514 1515
  auto parameters_it =
      parameters_access.begin_without_receiver_and_skip(mapped_count);
1516 1517 1518 1519

  // The unmapped argument values recorded in the frame state are stored yet
  // another indirection away and then linked into the parameter map below,
  // whereas mapped argument values are replaced with a hole instead.
1520
  AllocationBuilder ab(jsgraph(), effect, control);
1521
  ab.AllocateArray(argument_count, fixed_array_map);
1522
  for (int i = 0; i < mapped_count; ++i) {
1523
    ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1524
             jsgraph()->TheHoleConstant());
1525
  }
1526
  for (int i = mapped_count; i < argument_count; ++i, ++parameters_it) {
1527
    DCHECK_NOT_NULL(parameters_it.node());
1528
    ab.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
1529
             parameters_it.node());
1530
  }
1531
  Node* arguments = ab.Finish();
1532 1533

  // Actually allocate the backing store.
1534
  AllocationBuilder a(jsgraph(), arguments, control);
1535
  a.AllocateSloppyArgumentElements(mapped_count, sloppy_arguments_elements_map);
1536 1537
  a.Store(AccessBuilder::ForSloppyArgumentsElementsContext(), context);
  a.Store(AccessBuilder::ForSloppyArgumentsElementsArguments(), arguments);
1538
  for (int i = 0; i < mapped_count; ++i) {
1539
    int idx = shared.context_header_size() + parameter_count - 1 - i;
1540 1541
    a.Store(AccessBuilder::ForSloppyArgumentsElementsMappedEntry(),
            jsgraph()->Constant(i), jsgraph()->Constant(idx));
1542 1543 1544 1545
  }
  return a.Finish();
}

1546 1547 1548 1549
// Helper that allocates a FixedArray serving as a parameter map for values
// unknown at compile-time, the true {arguments_length} and {arguments_frame}
// values can only be determined dynamically at run-time and are provided.
// Serves as backing store for JSCreateArguments nodes.
1550
Node* JSCreateLowering::TryAllocateAliasedArguments(
1551 1552
    Node* effect, Node* control, Node* context, Node* arguments_length,
    const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
1553 1554
  // If there is no aliasing, the arguments object elements are not
  // special in any way, we can just return an unmapped backing store.
1555
  int parameter_count = shared.internal_formal_parameter_count();
1556
  if (parameter_count == 0) {
1557 1558 1559
    return graph()->NewNode(
        simplified()->NewArgumentsElements(
            CreateArgumentsType::kUnmappedArguments, parameter_count),
1560
        arguments_length, effect);
1561 1562
  }

1563 1564 1565
  int mapped_count = parameter_count;
  MapRef sloppy_arguments_elements_map(
      broker(), factory()->sloppy_arguments_elements_map());
1566
  if (!AllocationBuilder::CanAllocateSloppyArgumentElements(
1567 1568 1569 1570
          mapped_count, sloppy_arguments_elements_map)) {
    return nullptr;
  }

1571 1572 1573 1574 1575 1576 1577 1578 1579
  // From here on we are going to allocate a mapped (aka. aliased) elements
  // backing store. We do not statically know how many arguments exist, but
  // dynamically selecting the hole for some of the "mapped" elements allows
  // using a static shape for the parameter map.
  *has_aliased_arguments = true;

  // The unmapped argument values are stored yet another indirection away and
  // then linked into the parameter map below, whereas mapped argument values
  // (i.e. the first {mapped_count} elements) are replaced with a hole instead.
1580
  Node* arguments = effect =
1581 1582
      graph()->NewNode(simplified()->NewArgumentsElements(
                           CreateArgumentsType::kMappedArguments, mapped_count),
1583
                       arguments_length, effect);
1584 1585

  // Actually allocate the backing store.
1586
  AllocationBuilder a(jsgraph(), effect, control);
1587
  a.AllocateSloppyArgumentElements(mapped_count, sloppy_arguments_elements_map);
1588 1589
  a.Store(AccessBuilder::ForSloppyArgumentsElementsContext(), context);
  a.Store(AccessBuilder::ForSloppyArgumentsElementsArguments(), arguments);
1590
  for (int i = 0; i < mapped_count; ++i) {
1591
    int idx = shared.context_header_size() + parameter_count - 1 - i;
1592 1593 1594 1595
    Node* value = graph()->NewNode(
        common()->Select(MachineRepresentation::kTagged),
        graph()->NewNode(simplified()->NumberLessThan(), jsgraph()->Constant(i),
                         arguments_length),
1596
        jsgraph()->Constant(idx), jsgraph()->TheHoleConstant());
1597 1598
    a.Store(AccessBuilder::ForSloppyArgumentsElementsMappedEntry(),
            jsgraph()->Constant(i), value);
1599 1600 1601 1602
  }
  return a.Finish();
}

1603 1604 1605
Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
                                         ElementsKind elements_kind,
                                         int capacity,
1606
                                         AllocationType allocation) {
1607 1608 1609
  DCHECK_LE(1, capacity);
  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);

1610
  Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1611 1612
                                 ? factory()->fixed_double_array_map()
                                 : factory()->fixed_array_map();
1613
  ElementAccess access = IsDoubleElementsKind(elements_kind)
1614 1615
                             ? AccessBuilder::ForFixedDoubleArrayElement()
                             : AccessBuilder::ForFixedArrayElement();
1616
  Node* value = jsgraph()->TheHoleConstant();
1617 1618

  // Actually allocate the backing store.
1619
  AllocationBuilder a(jsgraph(), effect, control);
1620
  a.AllocateArray(capacity, MapRef(broker(), elements_map), allocation);
1621 1622 1623 1624 1625 1626 1627
  for (int i = 0; i < capacity; ++i) {
    Node* index = jsgraph()->Constant(i);
    a.Store(access, index, value);
  }
  return a.Finish();
}

1628 1629 1630
Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
                                         ElementsKind elements_kind,
                                         std::vector<Node*> const& values,
1631
                                         AllocationType allocation) {
1632 1633 1634 1635
  int const capacity = static_cast<int>(values.size());
  DCHECK_LE(1, capacity);
  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);

1636
  Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1637 1638
                                 ? factory()->fixed_double_array_map()
                                 : factory()->fixed_array_map();
1639
  ElementAccess access = IsDoubleElementsKind(elements_kind)
1640 1641 1642 1643
                             ? AccessBuilder::ForFixedDoubleArrayElement()
                             : AccessBuilder::ForFixedArrayElement();

  // Actually allocate the backing store.
1644
  AllocationBuilder a(jsgraph(), effect, control);
1645
  a.AllocateArray(capacity, MapRef(broker(), elements_map), allocation);
1646 1647 1648 1649 1650 1651 1652
  for (int i = 0; i < capacity; ++i) {
    Node* index = jsgraph()->Constant(i);
    a.Store(access, index, values[i]);
  }
  return a.Finish();
}

1653
Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
1654
                                            JSObjectRef boilerplate,
1655
                                            AllocationType allocation) {
1656
  // Compute the in-object properties to store first (might have effects).
1657
  MapRef boilerplate_map = boilerplate.map();
1658
  ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
1659 1660
  inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
  int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
1661
  for (InternalIndex i : InternalIndex::Range(boilerplate_nof)) {
1662
    PropertyDetails const property_details =
1663
        boilerplate_map.GetPropertyDetails(i);
1664 1665
    if (property_details.location() != kField) continue;
    DCHECK_EQ(kData, property_details.kind());
1666
    NameRef property_name = boilerplate_map.GetPropertyKey(i);
1667
    FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
1668
    ConstFieldInfo const_field_info(boilerplate_map.object());
1669 1670 1671 1672 1673
    FieldAccess access = {kTaggedBase,
                          index.offset(),
                          property_name.object(),
                          MaybeHandle<Map>(),
                          Type::Any(),
1674
                          MachineType::AnyTagged(),
1675 1676
                          kFullWriteBarrier,
                          LoadSensitivity::kUnsafe,
1677
                          const_field_info};
1678 1679 1680 1681 1682 1683 1684 1685
    ObjectRef boilerplate_value = boilerplate.RawFastPropertyAt(index);
    bool is_uninitialized =
        boilerplate_value.IsHeapObject() &&
        boilerplate_value.AsHeapObject().map().oddball_type() ==
            OddballType::kUninitialized;
    if (is_uninitialized) {
      access.const_field_info = ConstFieldInfo::None();
    }
1686
    Node* value;
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
    if (boilerplate_value.IsJSObject()) {
      JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
      value = effect =
          AllocateFastLiteral(effect, control, boilerplate_object, allocation);
    } else if (property_details.representation().IsDouble()) {
      double number = boilerplate_value.AsHeapNumber().value();
      // Allocate a mutable HeapNumber box and store the value into it.
      AllocationBuilder builder(jsgraph(), effect, control);
      builder.Allocate(HeapNumber::kSize, allocation);
      builder.Store(AccessBuilder::ForMap(),
                    MapRef(broker(), factory()->heap_number_map()));
      builder.Store(AccessBuilder::ForHeapNumberValue(),
                    jsgraph()->Constant(number));
      value = effect = builder.Finish();
    } else if (property_details.representation().IsSmi()) {
      // Ensure that value is stored as smi.
      value = is_uninitialized ? jsgraph()->ZeroConstant()
                               : jsgraph()->Constant(boilerplate_value.AsSmi());
1705
    } else {
1706
      value = jsgraph()->Constant(boilerplate_value);
1707 1708 1709 1710 1711
    }
    inobject_fields.push_back(std::make_pair(access, value));
  }

  // Fill slack at the end of the boilerplate object with filler maps.
1712
  int const boilerplate_length = boilerplate_map.GetInObjectProperties();
1713 1714
  for (int index = static_cast<int>(inobject_fields.size());
       index < boilerplate_length; ++index) {
1715 1716
    FieldAccess access =
        AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
1717 1718 1719 1720
    Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
    inobject_fields.push_back(std::make_pair(access, value));
  }

1721
  // Setup the elements backing store.
1722
  Node* elements =
1723
      AllocateFastLiteralElements(effect, control, boilerplate, allocation);
1724 1725
  if (elements->op()->EffectOutputCount() > 0) effect = elements;

1726
  // Actually allocate and initialize the object.
1727
  AllocationBuilder builder(jsgraph(), effect, control);
1728
  builder.Allocate(boilerplate_map.instance_size(), allocation,
1729
                   Type::For(boilerplate_map));
1730
  builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1731 1732
  builder.Store(AccessBuilder::ForJSObjectPropertiesOrHashKnownPointer(),
                jsgraph()->EmptyFixedArrayConstant());
1733
  builder.Store(AccessBuilder::ForJSObjectElements(), elements);
1734
  if (boilerplate.IsJSArray()) {
1735
    JSArrayRef boilerplate_array = boilerplate.AsJSArray();
1736
    builder.Store(
1737
        AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
1738
        boilerplate_array.GetBoilerplateLength());
1739
  }
1740
  for (auto const& inobject_field : inobject_fields) {
1741 1742 1743 1744 1745
    builder.Store(inobject_field.first, inobject_field.second);
  }
  return builder.Finish();
}

1746 1747
Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
                                                    JSObjectRef boilerplate,
1748
                                                    AllocationType allocation) {
1749
  FixedArrayBaseRef boilerplate_elements = boilerplate.elements().value();
1750 1751

  // Empty or copy-on-write elements just store a constant.
1752
  int const elements_length = boilerplate_elements.length();
1753 1754
  MapRef elements_map = boilerplate_elements.map();
  if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
1755
    if (allocation == AllocationType::kOld) {
1756
      boilerplate.EnsureElementsTenured();
1757
      boilerplate_elements = boilerplate.elements().value();
1758
    }
1759
    return jsgraph()->HeapConstant(boilerplate_elements.object());
1760 1761 1762 1763
  }

  // Compute the elements to store first (might have effects).
  ZoneVector<Node*> elements_values(elements_length, zone());
1764 1765
  if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
    FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
1766
    for (int i = 0; i < elements_length; ++i) {
1767 1768
      Float64 value = elements.get(i);
      if (value.is_hole_nan()) {
1769
        elements_values[i] = jsgraph()->TheHoleConstant();
1770
      } else {
1771
        elements_values[i] = jsgraph()->Constant(value.get_scalar());
1772 1773 1774
      }
    }
  } else {
1775
    FixedArrayRef elements = boilerplate_elements.AsFixedArray();
1776
    for (int i = 0; i < elements_length; ++i) {
1777 1778 1779
      ObjectRef element_value = elements.get(i);
      if (element_value.IsJSObject()) {
        elements_values[i] = effect = AllocateFastLiteral(
1780
            effect, control, element_value.AsJSObject(), allocation);
1781
      } else {
1782
        elements_values[i] = jsgraph()->Constant(element_value);
1783 1784 1785 1786 1787
      }
    }
  }

  // Allocate the backing store array and store the elements.
1788 1789 1790
  AllocationBuilder ab(jsgraph(), effect, control);
  CHECK(ab.CanAllocateArray(elements_length, elements_map, allocation));
  ab.AllocateArray(elements_length, elements_map, allocation);
1791
  ElementAccess const access =
1792
      (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
1793 1794 1795
          ? AccessBuilder::ForFixedDoubleArrayElement()
          : AccessBuilder::ForFixedArrayElement();
  for (int i = 0; i < elements_length; ++i) {
1796
    ab.Store(access, jsgraph()->Constant(i), elements_values[i]);
1797
  }
1798
  return ab.Finish();
1799 1800
}

1801 1802 1803
Node* JSCreateLowering::AllocateLiteralRegExp(
    Node* effect, Node* control, RegExpBoilerplateDescriptionRef boilerplate) {
  MapRef initial_map = native_context().regexp_function().initial_map();
1804 1805

  // Sanity check that JSRegExp object layout hasn't changed.
1806
  STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize);
1807
  STATIC_ASSERT(JSRegExp::kSourceOffset == JSRegExp::kDataOffset + kTaggedSize);
1808
  STATIC_ASSERT(JSRegExp::kFlagsOffset ==
1809
                JSRegExp::kSourceOffset + kTaggedSize);
1810 1811
  STATIC_ASSERT(JSRegExp::kHeaderSize == JSRegExp::kFlagsOffset + kTaggedSize);
  STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kHeaderSize);
1812
  DCHECK_EQ(JSRegExp::Size(), JSRegExp::kLastIndexOffset + kTaggedSize);
1813

1814
  AllocationBuilder builder(jsgraph(), effect, control);
1815 1816 1817
  builder.Allocate(JSRegExp::Size(), AllocationType::kYoung,
                   Type::For(initial_map));
  builder.Store(AccessBuilder::ForMap(), initial_map);
1818
  builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1819 1820 1821
                jsgraph()->EmptyFixedArrayConstant());
  builder.Store(AccessBuilder::ForJSObjectElements(),
                jsgraph()->EmptyFixedArrayConstant());
1822 1823 1824

  builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data());
  builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source());
1825 1826
  builder.Store(AccessBuilder::ForJSRegExpFlags(),
                jsgraph()->SmiConstant(boilerplate.flags()));
1827
  builder.Store(AccessBuilder::ForJSRegExpLastIndex(),
1828
                jsgraph()->SmiConstant(JSRegExp::kInitialLastIndexValue));
1829 1830 1831 1832

  return builder.Finish();
}

1833 1834 1835
Factory* JSCreateLowering::factory() const {
  return jsgraph()->isolate()->factory();
}
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846

Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }

CommonOperatorBuilder* JSCreateLowering::common() const {
  return jsgraph()->common();
}

SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
  return jsgraph()->simplified();
}

1847
NativeContextRef JSCreateLowering::native_context() const {
1848
  return broker()->target_native_context();
1849 1850
}

1851 1852 1853
}  // namespace compiler
}  // namespace internal
}  // namespace v8