js-create-lowering.cc 81.7 KB
Newer Older
1 2 3 4 5 6 7 8
// 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"

#include "src/code-factory.h"
#include "src/compiler/access-builder.h"
9
#include "src/compiler/allocation-builder.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/objects-inl.h"
22
#include "src/objects/arguments.h"
23
#include "src/objects/hash-table-inl.h"
24
#include "src/objects/js-generator.h"
25 26
#include "src/objects/js-promise.h"
#include "src/objects/js-regexp-inl.h"
27 28 29 30 31 32 33 34 35

namespace v8 {
namespace internal {
namespace compiler {

namespace {

// Retrieves the frame state holding actual argument values.
Node* GetArgumentsFrameState(Node* frame_state) {
36
  Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state);
37
  FrameStateInfo outer_state_info = FrameStateInfoOf(outer_state->op());
38 39 40 41 42
  return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
             ? outer_state
             : frame_state;
}

43 44
// Checks whether allocation using the given target and new.target can be
// inlined.
45
bool IsAllocationInlineable(const JSFunctionRef& target,
46
                            const JSFunctionRef& new_target) {
47 48
  CHECK_IMPLIES(new_target.has_initial_map(),
                !new_target.initial_map().is_dictionary_map());
49
  return new_target.has_initial_map() &&
50
         new_target.initial_map().constructor_or_backpointer().equals(target);
51 52 53 54 55 56 57 58 59 60 61 62 63
}

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

Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
  Node* const target = NodeProperties::GetValueInput(node, 0);
120
  Type const target_type = NodeProperties::GetType(target);
121
  Node* const new_target = NodeProperties::GetValueInput(node, 1);
122
  Type const new_target_type = NodeProperties::GetType(new_target);
123
  Node* const effect = NodeProperties::GetEffectInput(node);
124
  Node* const control = NodeProperties::GetControlInput(node);
125
  // Extract constructor and original constructor function.
126 127 128 129 130
  if (!target_type.IsHeapConstant() || !new_target_type.IsHeapConstant() ||
      !target_type.AsHeapConstant()->Ref().IsJSFunction() ||
      !new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
    return NoChange();
  }
131

132 133
  JSFunctionRef constructor =
      target_type.AsHeapConstant()->Ref().AsJSFunction();
134
  if (!constructor.map().is_constructor()) return NoChange();
135 136
  JSFunctionRef original_constructor =
      new_target_type.AsHeapConstant()->Ref().AsJSFunction();
137
  if (!original_constructor.map().is_constructor()) return NoChange();
138 139

  // Check if we can inline the allocation.
140
  if (!IsAllocationInlineable(constructor, original_constructor)) {
141 142
    return NoChange();
  }
143

144 145 146 147
  SlackTrackingPrediction slack_tracking_prediction =
      dependencies()->DependOnInitialMapInstanceSizePrediction(
          original_constructor);
  MapRef initial_map = original_constructor.initial_map();
148 149 150

  // Emit code to allocate the JSObject instance for the
  // {original_constructor}.
151
  AllocationBuilder a(jsgraph(), effect, control);
152
  a.Allocate(slack_tracking_prediction.instance_size());
153 154 155 156 157
  a.Store(AccessBuilder::ForMap(), initial_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
158 159
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
160
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
161
            jsgraph()->UndefinedConstant());
162
  }
163 164 165 166

  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
167 168 169 170 171
}

Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
  CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
172
  Node* const frame_state = NodeProperties::GetFrameStateInput(node);
173
  Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
174
  Node* const control = graph()->start();
175
  FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
176
  SharedFunctionInfoRef shared(broker(),
177
                               state_info.shared_info().ToHandleChecked());
178 179 180 181

  // Use the ArgumentsAccessStub for materializing both mapped and unmapped
  // arguments object, but only for non-inlined (i.e. outermost) frames.
  if (outer_state->opcode() != IrOpcode::kFrameState) {
182 183
    switch (type) {
      case CreateArgumentsType::kMappedArguments: {
184
        // TODO(mstarzinger): Duplicate parameters are not handled yet.
185
        if (shared.has_duplicate_parameters()) return NoChange();
186 187 188 189 190 191 192
        Node* const callee = NodeProperties::GetValueInput(node, 0);
        Node* const context = NodeProperties::GetContextInput(node);
        Node* effect = NodeProperties::GetEffectInput(node);
        Node* const arguments_frame =
            graph()->NewNode(simplified()->ArgumentsFrame());
        Node* const arguments_length = graph()->NewNode(
            simplified()->ArgumentsLength(
193
                shared.internal_formal_parameter_count(), false),
194 195 196 197 198 199 200
            arguments_frame);
        // Allocate the elements backing store.
        bool has_aliased_arguments = false;
        Node* const elements = effect = AllocateAliasedArguments(
            effect, control, context, arguments_frame, arguments_length, shared,
            &has_aliased_arguments);
        // Load the arguments object map.
201 202
        Node* const arguments_map = jsgraph()->Constant(
            has_aliased_arguments
203 204
                ? native_context().fast_aliased_arguments_map()
                : native_context().sloppy_arguments_map());
205
        // Actually allocate and initialize the arguments object.
206
        AllocationBuilder a(jsgraph(), effect, control);
207 208 209 210 211 212 213 214 215 216
        Node* properties = jsgraph()->EmptyFixedArrayConstant();
        STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
        a.Allocate(JSSloppyArgumentsObject::kSize);
        a.Store(AccessBuilder::ForMap(), arguments_map);
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
        a.Store(AccessBuilder::ForArgumentsCallee(), callee);
        RelaxControls(node);
        a.FinishAndChange(node);
217 218
        return Changed(node);
      }
219 220 221 222 223 224
      case CreateArgumentsType::kUnmappedArguments: {
        Node* effect = NodeProperties::GetEffectInput(node);
        Node* const arguments_frame =
            graph()->NewNode(simplified()->ArgumentsFrame());
        Node* const arguments_length = graph()->NewNode(
            simplified()->ArgumentsLength(
225
                shared.internal_formal_parameter_count(), false),
226 227 228
            arguments_frame);
        // Allocate the elements backing store.
        Node* const elements = effect =
229
            graph()->NewNode(simplified()->NewArgumentsElements(0),
230 231
                             arguments_frame, arguments_length, effect);
        // Load the arguments object map.
232
        Node* const arguments_map =
233
            jsgraph()->Constant(native_context().strict_arguments_map());
234
        // Actually allocate and initialize the arguments object.
235
        AllocationBuilder a(jsgraph(), effect, control);
236 237 238 239 240 241 242 243 244 245 246
        Node* properties = jsgraph()->EmptyFixedArrayConstant();
        STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
        a.Allocate(JSStrictArgumentsObject::kSize);
        a.Store(AccessBuilder::ForMap(), arguments_map);
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForArgumentsLength(), arguments_length);
        RelaxControls(node);
        a.FinishAndChange(node);
        return Changed(node);
      }
247
      case CreateArgumentsType::kRestParameter: {
248 249 250 251
        Node* effect = NodeProperties::GetEffectInput(node);
        Node* const arguments_frame =
            graph()->NewNode(simplified()->ArgumentsFrame());
        Node* const rest_length = graph()->NewNode(
252
            simplified()->ArgumentsLength(
253
                shared.internal_formal_parameter_count(), true),
254
            arguments_frame);
255 256 257
        // Allocate the elements backing store. Since NewArgumentsElements
        // copies from the end of the arguments adapter frame, this is a suffix
        // of the actual arguments.
258
        Node* const elements = effect =
259
            graph()->NewNode(simplified()->NewArgumentsElements(0),
260 261
                             arguments_frame, rest_length, effect);
        // Load the JSArray object map.
262
        Node* const jsarray_map = jsgraph()->Constant(
263
            native_context().js_array_packed_elements_map());
264
        // Actually allocate and initialize the jsarray.
265
        AllocationBuilder a(jsgraph(), effect, control);
266 267 268 269 270 271 272 273 274
        Node* properties = jsgraph()->EmptyFixedArrayConstant();
        STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
        a.Allocate(JSArray::kSize);
        a.Store(AccessBuilder::ForMap(), jsarray_map);
        a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
        a.Store(AccessBuilder::ForJSObjectElements(), elements);
        a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), rest_length);
        RelaxControls(node);
        a.FinishAndChange(node);
275 276
        return Changed(node);
      }
277
    }
278
    UNREACHABLE();
279 280 281 282 283 284 285 286
  } else if (outer_state->opcode() == IrOpcode::kFrameState) {
    // Use inline allocation for all mapped arguments objects within inlined
    // (i.e. non-outermost) frames, independent of the object size.
    if (type == CreateArgumentsType::kMappedArguments) {
      Node* const callee = NodeProperties::GetValueInput(node, 0);
      Node* const context = NodeProperties::GetContextInput(node);
      Node* effect = NodeProperties::GetEffectInput(node);
      // TODO(mstarzinger): Duplicate parameters are not handled yet.
287
      if (shared.has_duplicate_parameters()) return NoChange();
288 289 290 291
      // Choose the correct frame state and frame state info depending on
      // whether there conceptually is an arguments adaptor frame in the call
      // chain.
      Node* const args_state = GetArgumentsFrameState(frame_state);
292 293 294 295 296 297 298
      if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
          IrOpcode::kDeadValue) {
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
299
      FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
300 301 302 303 304
      // Prepare element backing store to be used by arguments object.
      bool has_aliased_arguments = false;
      Node* const elements = AllocateAliasedArguments(
          effect, control, args_state, context, shared, &has_aliased_arguments);
      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
305
      // Load the arguments object map.
306
      Node* const arguments_map = jsgraph()->Constant(
307 308
          has_aliased_arguments ? native_context().fast_aliased_arguments_map()
                                : native_context().sloppy_arguments_map());
309
      // Actually allocate and initialize the arguments object.
310
      AllocationBuilder a(jsgraph(), effect, control);
311 312
      Node* properties = jsgraph()->EmptyFixedArrayConstant();
      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
313 314
      STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
      a.Allocate(JSSloppyArgumentsObject::kSize);
315
      a.Store(AccessBuilder::ForMap(), arguments_map);
316
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
317 318 319 320 321 322 323 324 325 326 327 328 329 330
      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);
    } else if (type == CreateArgumentsType::kUnmappedArguments) {
      // 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.
      Node* const args_state = GetArgumentsFrameState(frame_state);
331 332 333 334 335 336 337
      if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
          IrOpcode::kDeadValue) {
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
338
      FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
339 340 341
      // Prepare element backing store to be used by arguments object.
      Node* const elements = AllocateArguments(effect, control, args_state);
      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
342
      // Load the arguments object map.
343
      Node* const arguments_map =
344
          jsgraph()->Constant(native_context().strict_arguments_map());
345
      // Actually allocate and initialize the arguments object.
346
      AllocationBuilder a(jsgraph(), effect, control);
347 348
      Node* properties = jsgraph()->EmptyFixedArrayConstant();
      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
349 350
      STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
      a.Allocate(JSStrictArgumentsObject::kSize);
351
      a.Store(AccessBuilder::ForMap(), arguments_map);
352
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
353 354 355 356 357 358
      a.Store(AccessBuilder::ForJSObjectElements(), elements);
      a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
      RelaxControls(node);
      a.FinishAndChange(node);
      return Changed(node);
    } else if (type == CreateArgumentsType::kRestParameter) {
359
      int start_index = shared.internal_formal_parameter_count();
360 361 362 363 364 365 366
      // 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.
      Node* const args_state = GetArgumentsFrameState(frame_state);
367 368 369 370 371 372 373
      if (args_state->InputAt(kFrameStateParametersInput)->opcode() ==
          IrOpcode::kDeadValue) {
        // This protects against an incompletely propagated DeadValue node.
        // If the FrameState has a DeadValue input, then this node will be
        // pruned anyway.
        return NoChange();
      }
374
      FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op());
375 376 377 378
      // Prepare element backing store to be used by the rest array.
      Node* const elements =
          AllocateRestArguments(effect, control, args_state, start_index);
      effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
379
      // Load the JSArray object map.
380 381
      Node* const jsarray_map =
          jsgraph()->Constant(native_context().js_array_packed_elements_map());
382
      // Actually allocate and initialize the jsarray.
383
      AllocationBuilder a(jsgraph(), effect, control);
384 385 386 387 388 389 390
      Node* properties = jsgraph()->EmptyFixedArrayConstant();

      // -1 to minus receiver
      int argument_count = args_state_info.parameter_count() - 1;
      int length = std::max(0, argument_count - start_index);
      STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
      a.Allocate(JSArray::kSize);
391
      a.Store(AccessBuilder::ForMap(), jsarray_map);
392
      a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
393
      a.Store(AccessBuilder::ForJSObjectElements(), elements);
394
      a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS),
395 396 397 398 399 400 401 402 403 404
              jsgraph()->Constant(length));
      RelaxControls(node);
      a.FinishAndChange(node);
      return Changed(node);
    }
  }

  return NoChange();
}

405 406 407 408 409
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);
410
  Type const closure_type = NodeProperties::GetType(closure);
411 412
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* const control = NodeProperties::GetControlInput(node);
413
  if (closure_type.IsHeapConstant()) {
414 415 416
    DCHECK(closure_type.AsHeapConstant()->Ref().IsJSFunction());
    JSFunctionRef js_function =
        closure_type.AsHeapConstant()->Ref().AsJSFunction();
417
    if (!js_function.has_initial_map()) return NoChange();
418

419 420
    SlackTrackingPrediction slack_tracking_prediction =
        dependencies()->DependOnInitialMapInstanceSizePrediction(js_function);
421

422
    MapRef initial_map = js_function.initial_map();
423 424
    DCHECK(initial_map.instance_type() == JS_GENERATOR_OBJECT_TYPE ||
           initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
425

426
    // Allocate a register file.
427
    SharedFunctionInfoRef shared = js_function.shared();
428 429
    DCHECK(shared.HasBytecodeArray());
    int parameter_count_no_receiver = shared.internal_formal_parameter_count();
430 431
    int size = parameter_count_no_receiver +
               shared.GetBytecodeArray().register_count();
432
    AllocationBuilder ab(jsgraph(), effect, control);
433 434 435 436 437
    ab.AllocateArray(size, factory()->fixed_array_map());
    for (int i = 0; i < size; ++i) {
      ab.Store(AccessBuilder::ForFixedArraySlot(i),
               jsgraph()->UndefinedConstant());
    }
438
    Node* parameters_and_registers = effect = ab.Finish();
439

440
    // Emit code to allocate the JS[Async]GeneratorObject instance.
441
    AllocationBuilder a(jsgraph(), effect, control);
442
    a.Allocate(slack_tracking_prediction.instance_size());
443 444 445
    Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
    Node* undefined = jsgraph()->UndefinedConstant();
    a.Store(AccessBuilder::ForMap(), initial_map);
446
    a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
447 448 449 450 451 452 453 454 455
    a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
    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));
456 457
    a.Store(AccessBuilder::ForJSGeneratorObjectParametersAndRegisters(),
            parameters_and_registers);
458

459
    if (initial_map.instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE) {
460
      a.Store(AccessBuilder::ForJSAsyncGeneratorObjectQueue(), undefined);
461 462
      a.Store(AccessBuilder::ForJSAsyncGeneratorObjectIsAwaiting(),
              jsgraph()->ZeroConstant());
463 464 465
    }

    // Handle in-object properties, too.
466 467
    for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
         ++i) {
468 469
      a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
              undefined);
470 471 472 473 474 475 476
    }
    a.FinishAndChange(node);
    return Changed(node);
  }
  return NoChange();
}

477 478
// Constructs an array with a variable {length} when no upper bound
// is known for the capacity.
479
Reduction JSCreateLowering::ReduceNewArray(
480 481
    Node* node, Node* length, MapRef initial_map, ElementsKind elements_kind,
    PretenureFlag pretenure,
482
    const SlackTrackingPrediction& slack_tracking_prediction) {
483 484 485 486 487 488
  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.
489
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
490 491
      initial_map,
      initial_map.AsElementsKind(GetHoleyElementsKind(elements_kind)));
492 493 494 495 496

  // 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(
497
      simplified()->CheckBounds(VectorSlotPair()), length,
498 499 500 501
      jsgraph()->Constant(JSArray::kInitialMaxFastElementArray), effect,
      control);

  // Construct elements and properties for the resulting JSArray.
502
  Node* elements = effect =
503
      graph()->NewNode(IsDoubleElementsKind(initial_map.elements_kind())
504 505 506
                           ? simplified()->NewDoubleElements(pretenure)
                           : simplified()->NewSmiOrObjectElements(pretenure),
                       length, effect, control);
507 508 509
  Node* properties = jsgraph()->EmptyFixedArrayConstant();

  // Perform the allocation of the actual JSArray object.
510
  AllocationBuilder a(jsgraph(), effect, control);
511
  a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
512 513 514
  a.Store(AccessBuilder::ForMap(), initial_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
515
  a.Store(AccessBuilder::ForJSArrayLength(initial_map.elements_kind()), length);
516 517
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
518
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
519 520 521 522 523 524 525 526 527
            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}.
528 529
Reduction JSCreateLowering::ReduceNewArray(
    Node* node, Node* length, int capacity, MapRef initial_map,
530
    ElementsKind elements_kind, PretenureFlag pretenure,
531
    const SlackTrackingPrediction& slack_tracking_prediction) {
532 533
  DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
         node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
534 535 536
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

537
  // Determine the appropriate elements kind.
538
  if (NodeProperties::GetType(length).Max() > 0.0) {
539 540
    elements_kind = GetHoleyElementsKind(elements_kind);
  }
541 542
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
      initial_map, initial_map.AsElementsKind(elements_kind));
543
  DCHECK(IsFastElementsKind(elements_kind));
544 545 546 547 548 549 550 551 552 553 554 555

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

  // Perform the allocation of the actual JSArray object.
556
  AllocationBuilder a(jsgraph(), effect, control);
557
  a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
558
  a.Store(AccessBuilder::ForMap(), initial_map);
559
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
560 561
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
562 563
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
564
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
565 566
            jsgraph()->UndefinedConstant());
  }
567 568 569 570 571
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

572 573
Reduction JSCreateLowering::ReduceNewArray(
    Node* node, std::vector<Node*> values, MapRef initial_map,
574
    ElementsKind elements_kind, PretenureFlag pretenure,
575
    const SlackTrackingPrediction& slack_tracking_prediction) {
576 577 578 579
  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

580
  // Determine the appropriate elements kind.
581
  DCHECK(IsFastElementsKind(elements_kind));
582 583
  ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(
      initial_map, initial_map.AsElementsKind(elements_kind));
584 585 586 587

  // 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.
588
  if (IsSmiElementsKind(elements_kind)) {
589
    for (auto& value : values) {
590
      if (!NodeProperties::GetType(value).Is(Type::SignedSmall())) {
591 592
        value = effect = graph()->NewNode(
            simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
593 594
      }
    }
595
  } else if (IsDoubleElementsKind(elements_kind)) {
596
    for (auto& value : values) {
597
      if (!NodeProperties::GetType(value).Is(Type::Number())) {
598 599 600
        value = effect =
            graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
                             effect, control);
601 602 603 604 605 606 607 608 609 610 611 612 613
      }
      // 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 =
      AllocateElements(effect, control, elements_kind, values, pretenure);
  Node* properties = jsgraph()->EmptyFixedArrayConstant();
  Node* length = jsgraph()->Constant(static_cast<int>(values.size()));

  // Perform the allocation of the actual JSArray object.
614
  AllocationBuilder a(jsgraph(), effect, control);
615
  a.Allocate(slack_tracking_prediction.instance_size(), pretenure);
616
  a.Store(AccessBuilder::ForMap(), initial_map);
617
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
618 619
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
620 621
  for (int i = 0; i < slack_tracking_prediction.inobject_property_count();
       ++i) {
622
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
623 624
            jsgraph()->UndefinedConstant());
  }
625 626 627 628 629
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

630 631 632
Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
633
  int const arity = static_cast<int>(p.arity());
634 635 636 637
  base::Optional<AllocationSiteRef> site_ref;
  {
    Handle<AllocationSite> site;
    if (p.site().ToHandle(&site)) {
638
      site_ref = AllocationSiteRef(broker(), site);
639
    }
640
  }
641
  PretenureFlag pretenure = NOT_TENURED;
642
  JSFunctionRef constructor = native_context().array_function();
643 644
  Node* target = NodeProperties::GetValueInput(node, 0);
  Node* new_target = NodeProperties::GetValueInput(node, 1);
645 646 647
  Type new_target_type = (target == new_target)
                             ? Type::HeapConstant(constructor, zone())
                             : NodeProperties::GetType(new_target);
648

649
  // Extract original constructor function.
650
  if (new_target_type.IsHeapConstant() &&
651 652 653
      new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
    JSFunctionRef original_constructor =
        new_target_type.AsHeapConstant()->Ref().AsJSFunction();
654 655
    DCHECK(constructor.map().is_constructor());
    DCHECK(original_constructor.map().is_constructor());
656 657

    // Check if we can inline the allocation.
658
    if (IsAllocationInlineable(constructor, original_constructor)) {
659 660 661 662
      SlackTrackingPrediction slack_tracking_prediction =
          dependencies()->DependOnInitialMapInstanceSizePrediction(
              original_constructor);
      MapRef initial_map = original_constructor.initial_map();
663

664 665 666 667
      // Tells whether we are protected by either the {site} or a
      // protector cell to do certain speculative optimizations.
      bool can_inline_call = false;

668
      // Check if we have a feedback {site} on the {node}.
669
      ElementsKind elements_kind = initial_map.elements_kind();
670
      if (site_ref) {
671
        elements_kind = site_ref->GetElementsKind();
672 673 674
        can_inline_call = site_ref->CanInlineCall();
        pretenure = dependencies()->DependOnPretenureMode(*site_ref);
        dependencies()->DependOnElementsKind(*site_ref);
675
      } else {
676 677 678 679
        CellRef array_constructor_protector(
            broker(), factory()->array_constructor_protector());
        can_inline_call = array_constructor_protector.value().AsSmi() ==
                          Isolate::kProtectorValid;
680
      }
681

682
      if (arity == 0) {
683 684
        Node* length = jsgraph()->ZeroConstant();
        int capacity = JSArray::kPreallocatedArrayElements;
685 686
        return ReduceNewArray(node, length, capacity, initial_map,
                              elements_kind, pretenure,
687
                              slack_tracking_prediction);
688
      } else if (arity == 1) {
689
        Node* length = NodeProperties::GetValueInput(node, 2);
690
        Type length_type = NodeProperties::GetType(length);
691
        if (!length_type.Maybe(Type::Number())) {
692 693
          // Handle the single argument case, where we know that the value
          // cannot be a valid Array length.
694 695 696 697
          elements_kind = GetMoreGeneralElementsKind(
              elements_kind, IsHoleyElementsKind(elements_kind)
                                 ? HOLEY_ELEMENTS
                                 : PACKED_ELEMENTS);
698
          return ReduceNewArray(node, std::vector<Node*>{length}, initial_map,
699 700
                                elements_kind, pretenure,
                                slack_tracking_prediction);
701
        }
702 703 704 705
        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());
706 707
          return ReduceNewArray(node, length, capacity, initial_map,
                                elements_kind, pretenure,
708
                                slack_tracking_prediction);
709
        }
710
        if (length_type.Maybe(Type::UnsignedSmall()) && can_inline_call) {
711 712
          return ReduceNewArray(node, length, initial_map, elements_kind,
                                pretenure, slack_tracking_prediction);
713
        }
714 715 716 717
      } 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;
718 719
        std::vector<Node*> values;
        values.reserve(p.arity());
720 721
        for (int i = 0; i < arity; ++i) {
          Node* value = NodeProperties::GetValueInput(node, 2 + i);
722
          Type value_type = NodeProperties::GetType(value);
723
          if (!value_type.Is(Type::SignedSmall())) {
724 725
            values_all_smis = false;
          }
726
          if (!value_type.Is(Type::Number())) {
727 728
            values_all_numbers = false;
          }
729
          if (!value_type.Maybe(Type::Number())) {
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
            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);
748
        } else if (!can_inline_call) {
749 750 751 752 753 754
          // 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();
755
        }
756 757
        return ReduceNewArray(node, values, initial_map, elements_kind,
                              pretenure, slack_tracking_prediction);
758 759 760
      }
    }
  }
761
  return NoChange();
762 763
}

764 765 766 767 768 769 770 771 772
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.
773
  AllocationBuilder a(jsgraph(), effect, control);
774 775
  a.Allocate(JSArrayIterator::kSize, NOT_TENURED, Type::OtherObject());
  a.Store(AccessBuilder::ForMap(),
776
          native_context().initial_array_iterator_map());
777 778 779 780 781 782 783 784 785 786 787 788 789 790
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          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);
}

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
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.
  AllocationBuilder ab(jsgraph(), effect, control);
  ab.AllocateArray(register_count, factory()->fixed_array_map());
  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);
  a.Allocate(JSAsyncFunctionObject::kSize);
  Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
  a.Store(AccessBuilder::ForMap(),
          native_context().async_function_object_map());
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), empty_fixed_array);
  a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
  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);
}

834 835
namespace {

836 837 838
MapRef MapForCollectionIterationKind(const NativeContextRef& native_context,
                                     CollectionKind collection_kind,
                                     IterationKind iteration_kind) {
839 840 841 842 843 844
  switch (collection_kind) {
    case CollectionKind::kSet:
      switch (iteration_kind) {
        case IterationKind::kKeys:
          UNREACHABLE();
        case IterationKind::kValues:
845
          return native_context.set_value_iterator_map();
846
        case IterationKind::kEntries:
847
          return native_context.set_key_value_iterator_map();
848 849 850 851 852
      }
      break;
    case CollectionKind::kMap:
      switch (iteration_kind) {
        case IterationKind::kKeys:
853
          return native_context.map_key_iterator_map();
854
        case IterationKind::kValues:
855
          return native_context.map_value_iterator_map();
856
        case IterationKind::kEntries:
857
          return native_context.map_key_value_iterator_map();
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
      }
      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);

  // Create the JSArrayIterator result.
880
  AllocationBuilder a(jsgraph(), effect, control);
881
  a.Allocate(JSCollectionIterator::kSize, NOT_TENURED, Type::OtherObject());
882
  a.Store(AccessBuilder::ForMap(),
883 884
          MapForCollectionIterationKind(native_context(), p.collection_kind(),
                                        p.iteration_kind()));
885 886 887 888 889 890 891 892 893 894 895 896
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          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);
}

897 898 899 900 901
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());
902
  MapRef const map(broker(), p.map());
903 904 905 906 907 908 909 910
  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) {
911
    AllocationBuilder a(jsgraph(), effect, control);
912 913 914 915 916 917 918 919 920
    a.AllocateArray(arity, factory()->fixed_array_map());
    for (int i = 0; i < arity; ++i) {
      a.Store(AccessBuilder::ForFixedArraySlot(i),
              NodeProperties::GetValueInput(node, 2 + i));
    }
    bound_arguments = effect = a.Finish();
  }

  // Create the JSBoundFunction result.
921
  AllocationBuilder a(jsgraph(), effect, control);
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
  a.Allocate(JSBoundFunction::kSize, NOT_TENURED, Type::BoundFunction());
  a.Store(AccessBuilder::ForMap(), map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          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);
}

937 938 939
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
  CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
940 941 942
  SharedFunctionInfoRef shared(broker(), p.shared_info());
  HeapObjectRef feedback_cell(broker(), p.feedback_cell());
  HeapObjectRef code(broker(), p.code());
943 944 945 946 947 948 949
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* context = NodeProperties::GetContextInput(node);

  // 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.
950
  if (!feedback_cell.map().equals(
951
          MapRef(broker(), factory()->many_closures_cell_map()))) {
952
    return NoChange();
953 954
  }

955
  MapRef function_map =
956
      native_context().GetFunctionMapFromIndex(shared.function_map_index());
957 958
  DCHECK(!function_map.IsInobjectSlackTrackingInProgress());
  DCHECK(!function_map.is_dictionary_map());
959

960 961 962 963 964 965 966 967 968 969 970
  // 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).
  PretenureFlag pretenure = NOT_TENURED;

971 972
  // Emit code to allocate the JSFunction instance.
  STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
973
  AllocationBuilder a(jsgraph(), effect, control);
974
  a.Allocate(function_map.instance_size(), pretenure, Type::Function());
975 976 977 978 979 980 981
  a.Store(AccessBuilder::ForMap(), function_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
  a.Store(AccessBuilder::ForJSFunctionContext(), context);
982
  a.Store(AccessBuilder::ForJSFunctionFeedbackCell(), feedback_cell);
983
  a.Store(AccessBuilder::ForJSFunctionCode(), code);
984
  STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kPointerSize);
985
  if (function_map.has_prototype_slot()) {
986 987 988 989
    a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(),
            jsgraph()->TheHoleConstant());
    STATIC_ASSERT(JSFunction::kSizeWithPrototype == 8 * kPointerSize);
  }
990
  for (int i = 0; i < function_map.GetInObjectProperties(); i++) {
991 992 993 994 995 996
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(function_map, i),
            jsgraph()->UndefinedConstant());
  }
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
997 998
}

999 1000 1001 1002 1003 1004
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);

1005
  Node* iterator_result_map =
1006
      jsgraph()->Constant(native_context().iterator_result_map());
1007 1008

  // Emit code to allocate the JSIteratorResult instance.
1009
  AllocationBuilder a(jsgraph(), effect, graph()->start());
1010 1011
  a.Allocate(JSIteratorResult::kSize);
  a.Store(AccessBuilder::ForMap(), iterator_result_map);
1012
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSIteratorResultValue(), value);
  a.Store(AccessBuilder::ForJSIteratorResultDone(), done);
  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
  a.FinishAndChange(node);
  return Changed(node);
}

1023 1024 1025 1026 1027
Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
  Node* string = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);

1028 1029
  Node* map =
      jsgraph()->Constant(native_context().initial_string_iterator_map());
1030
  // Allocate new iterator and attach the iterator to this string.
1031
  AllocationBuilder a(jsgraph(), effect, graph()->start());
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
  a.Allocate(JSStringIterator::kSize, NOT_TENURED, Type::OtherObject());
  a.Store(AccessBuilder::ForMap(), map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSStringIteratorString(), string);
  a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0));
  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
  a.FinishAndChange(node);
  return Changed(node);
}

1045 1046 1047 1048 1049 1050
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);

1051
  Node* array_map =
1052
      jsgraph()->Constant(native_context().js_array_packed_elements_map());
1053 1054 1055
  Node* properties = jsgraph()->EmptyFixedArrayConstant();
  Node* length = jsgraph()->Constant(2);

1056
  AllocationBuilder aa(jsgraph(), effect, graph()->start());
1057
  aa.AllocateArray(2, factory()->fixed_array_map());
1058
  aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1059
           jsgraph()->ZeroConstant(), key);
1060
  aa.Store(AccessBuilder::ForFixedArrayElement(PACKED_ELEMENTS),
1061
           jsgraph()->OneConstant(), value);
1062 1063
  Node* elements = aa.Finish();

1064
  AllocationBuilder a(jsgraph(), elements, graph()->start());
1065 1066
  a.Allocate(JSArray::kSize);
  a.Store(AccessBuilder::ForMap(), array_map);
1067
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1068
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
1069
  a.Store(AccessBuilder::ForJSArrayLength(PACKED_ELEMENTS), length);
1070 1071 1072 1073 1074
  STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
  a.FinishAndChange(node);
  return Changed(node);
}

1075 1076 1077 1078
Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreatePromise, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);

1079
  MapRef promise_map = native_context().promise_function().initial_map();
1080

1081
  AllocationBuilder a(jsgraph(), effect, graph()->start());
1082
  a.Allocate(promise_map.instance_size());
1083 1084 1085 1086 1087
  a.Store(AccessBuilder::ForMap(), promise_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
          jsgraph()->EmptyFixedArrayConstant());
  a.Store(AccessBuilder::ForJSObjectElements(),
          jsgraph()->EmptyFixedArrayConstant());
1088 1089
  a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kReactionsOrResultOffset),
          jsgraph()->ZeroConstant());
1090 1091 1092
  STATIC_ASSERT(v8::Promise::kPending == 0);
  a.Store(AccessBuilder::ForJSObjectOffset(JSPromise::kFlagsOffset),
          jsgraph()->ZeroConstant());
1093
  STATIC_ASSERT(JSPromise::kSize == 5 * kPointerSize);
1094 1095 1096 1097 1098 1099 1100 1101 1102
  for (int i = 0; i < v8::Promise::kEmbedderFieldCount; ++i) {
    a.Store(
        AccessBuilder::ForJSObjectOffset(JSPromise::kSize + i * kPointerSize),
        jsgraph()->ZeroConstant());
  }
  a.FinishAndChange(node);
  return Changed(node);
}

1103
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
1104 1105 1106 1107 1108 1109
  DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
         node->opcode() == IrOpcode::kJSCreateLiteralObject);
  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

1110
  FeedbackVectorRef feedback_vector(broker(), p.feedback().vector());
1111
  ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1112 1113
  if (feedback.IsAllocationSite()) {
    AllocationSiteRef site = feedback.AsAllocationSite();
1114
    if (site.IsFastLiteral()) {
1115 1116
      PretenureFlag pretenure = NOT_TENURED;
      if (FLAG_allocation_site_pretenuring) {
1117
        pretenure = dependencies()->DependOnPretenureMode(site);
1118
      }
1119
      dependencies()->DependOnElementsKinds(site);
1120
      JSObjectRef boilerplate = site.boilerplate().value();
1121
      Node* value = effect =
1122
          AllocateFastLiteral(effect, control, boilerplate, pretenure);
1123 1124
      ReplaceWithValue(node, value, effect, control);
      return Replace(value);
1125 1126
    }
  }
1127 1128
  return NoChange();
}
1129

1130
Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
1131 1132
  DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralArray, node->opcode());
  FeedbackParameter const& p = FeedbackParameterOf(node->op());
1133
  FeedbackVectorRef fv(broker(), p.feedback().vector());
1134 1135 1136 1137 1138
  ObjectRef feedback = fv.get(p.feedback().slot());
  if (feedback.IsAllocationSite()) {
    AllocationSiteRef site = feedback.AsAllocationSite();
    DCHECK(!site.PointsToLiteral());
    MapRef initial_map =
1139
        native_context().GetInitialJSArrayMap(site.GetElementsKind());
1140 1141
    PretenureFlag const pretenure = dependencies()->DependOnPretenureMode(site);
    dependencies()->DependOnElementsKind(site);
1142
    Node* length = jsgraph()->ZeroConstant();
1143 1144 1145
    DCHECK(!initial_map.IsInobjectSlackTrackingInProgress());
    SlackTrackingPrediction slack_tracking_prediction(
        initial_map, initial_map.instance_size());
1146 1147
    return ReduceNewArray(node, length, 0, initial_map,
                          initial_map.elements_kind(), pretenure,
1148
                          slack_tracking_prediction);
1149 1150 1151 1152
  }
  return NoChange();
}

1153
Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
1154 1155 1156 1157 1158
  DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralObject, node->opcode());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Retrieve the initial map for the object.
1159
  MapRef map = native_context().object_function().initial_map();
1160 1161 1162
  DCHECK(!map.is_dictionary_map());
  DCHECK(!map.IsInobjectSlackTrackingInProgress());
  Node* js_object_map = jsgraph()->Constant(map);
1163 1164 1165 1166 1167 1168

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

  // Perform the allocation of the actual JSArray object.
1169
  AllocationBuilder a(jsgraph(), effect, control);
1170
  a.Allocate(map.instance_size());
1171 1172 1173
  a.Store(AccessBuilder::ForMap(), js_object_map);
  a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
  a.Store(AccessBuilder::ForJSObjectElements(), elements);
1174 1175
  for (int i = 0; i < map.GetInObjectProperties(); i++) {
    a.Store(AccessBuilder::ForJSObjectInObjectProperty(map, i),
1176 1177 1178 1179 1180 1181 1182 1183
            jsgraph()->UndefinedConstant());
  }

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

1184
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
1185
  DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
1186 1187 1188 1189
  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

1190
  FeedbackVectorRef feedback_vector(broker(), p.feedback().vector());
1191
  ObjectRef feedback = feedback_vector.get(p.feedback().slot());
1192 1193
  if (feedback.IsJSRegExp()) {
    JSRegExpRef boilerplate = feedback.AsJSRegExp();
1194 1195 1196
    Node* value = effect = AllocateLiteralRegExp(effect, control, boilerplate);
    ReplaceWithValue(node, value, effect, control);
    return Replace(value);
1197 1198 1199 1200
  }
  return NoChange();
}

1201 1202
Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
1203 1204
  const CreateFunctionContextParameters& parameters =
      CreateFunctionContextParametersOf(node->op());
1205
  ScopeInfoRef scope_info(broker(), parameters.scope_info());
1206 1207
  int slot_count = parameters.slot_count();
  ScopeType scope_type = parameters.scope_type();
1208 1209 1210 1211 1212 1213 1214 1215

  // 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);
    Node* extension = jsgraph()->TheHoleConstant();
1216
    AllocationBuilder a(jsgraph(), effect, control);
1217 1218
    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
    int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
    Handle<Map> map;
    switch (scope_type) {
      case EVAL_SCOPE:
        map = factory()->eval_context_map();
        break;
      case FUNCTION_SCOPE:
        map = factory()->function_context_map();
        break;
      default:
        UNREACHABLE();
    }
1230
    a.AllocateContext(context_length, map);
1231 1232
    a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
            scope_info);
1233 1234 1235
    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1236
            jsgraph()->Constant(native_context()));
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
    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());
1250
  ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1251
  Node* extension = NodeProperties::GetValueInput(node, 0);
1252 1253 1254
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* context = NodeProperties::GetContextInput(node);
1255

1256
  AllocationBuilder a(jsgraph(), effect, control);
1257
  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1258
  a.AllocateContext(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
1259
  a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1260
  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1261
  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1262
  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1263
          jsgraph()->Constant(native_context()));
1264 1265 1266 1267 1268 1269 1270
  RelaxControls(node);
  a.FinishAndChange(node);
  return Changed(node);
}

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

1278
  AllocationBuilder a(jsgraph(), effect, control);
1279
  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1280 1281
  a.AllocateContext(Context::MIN_CONTEXT_SLOTS + 1,
                    factory()->catch_context_map());
1282
  a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX), scope_info);
1283
  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
1284
  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
1285
  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1286
          jsgraph()->Constant(native_context()));
1287 1288 1289 1290 1291 1292 1293 1294 1295
  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());
1296
  ScopeInfoRef scope_info(broker(), ScopeInfoOf(node->op()));
1297
  int const context_length = scope_info.ContextLength();
1298 1299 1300 1301 1302 1303 1304

  // 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);
1305
    Node* extension = jsgraph()->TheHoleConstant();
1306

1307
    AllocationBuilder a(jsgraph(), effect, control);
1308
    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
1309
    a.AllocateContext(context_length, factory()->block_context_map());
1310 1311
    a.Store(AccessBuilder::ForContextSlot(Context::SCOPE_INFO_INDEX),
            scope_info);
1312 1313 1314
    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
1315
            jsgraph()->Constant(native_context()));
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
    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();
}

1327 1328 1329 1330 1331 1332 1333 1334
namespace {
base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
                                          HeapObjectRef prototype) {
  MapRef standard_map =
      broker->native_context().object_function().initial_map();
  if (prototype.equals(standard_map.prototype())) {
    return standard_map;
  }
1335
  if (prototype.map().oddball_type() == OddballType::kNull) {
1336 1337 1338 1339 1340 1341 1342 1343 1344
    return broker->native_context().slow_object_with_null_prototype_map();
  }
  if (prototype.IsJSObject()) {
    return prototype.AsJSObject().GetObjectCreateMap();
  }
  return base::Optional<MapRef>();
}
}  // namespace

1345 1346 1347 1348 1349
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);
1350 1351
  Type prototype_type = NodeProperties::GetType(prototype);
  if (!prototype_type.IsHeapConstant()) return NoChange();
1352

1353
  HeapObjectRef prototype_const = prototype_type.AsHeapConstant()->Ref();
1354
  auto maybe_instance_map = GetObjectCreateMap(broker(), prototype_const);
1355 1356
  if (!maybe_instance_map) return NoChange();
  MapRef instance_map = maybe_instance_map.value();
1357

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

1369
    AllocationBuilder a(jsgraph(), effect, control);
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
    a.Allocate(size, NOT_TENURED, Type::Any());
    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();
  }

1399
  int const instance_size = instance_map.instance_size();
1400
  if (instance_size > kMaxRegularHeapObjectSize) return NoChange();
1401
  CHECK(!instance_map.IsInobjectSlackTrackingInProgress());
1402 1403 1404

  // Emit code to allocate the JSObject instance for the given
  // {instance_map}.
1405
  AllocationBuilder a(jsgraph(), effect, control);
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
  a.Allocate(instance_size, NOT_TENURED, Type::Any());
  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;
       offset += kPointerSize) {
    a.Store(AccessBuilder::ForJSObjectOffset(offset, kNoWriteBarrier),
            undefined);
  }
  Node* value = effect = a.Finish();

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

1424 1425 1426 1427
// Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
                                          Node* frame_state) {
1428
  FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1429 1430 1431 1432 1433 1434 1435 1436 1437
  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.
  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
  StateValuesAccess parameters_access(parameters);
  auto parameters_it = ++parameters_access.begin();

  // Actually allocate the backing store.
1438
  AllocationBuilder a(jsgraph(), effect, control);
1439 1440
  a.AllocateArray(argument_count, factory()->fixed_array_map());
  for (int i = 0; i < argument_count; ++i, ++parameters_it) {
1441
    DCHECK_NOT_NULL((*parameters_it).node);
1442 1443
    a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
            (*parameters_it).node);
1444 1445 1446 1447 1448 1449 1450 1451 1452
  }
  return a.Finish();
}

// Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
                                              Node* frame_state,
                                              int start_index) {
1453
  FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
  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.
  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
  StateValuesAccess parameters_access(parameters);
  auto parameters_it = ++parameters_access.begin();

  // Skip unused arguments.
  for (int i = 0; i < start_index; i++) {
    ++parameters_it;
  }

  // Actually allocate the backing store.
1469
  AllocationBuilder a(jsgraph(), effect, control);
1470 1471
  a.AllocateArray(num_elements, factory()->fixed_array_map());
  for (int i = 0; i < num_elements; ++i, ++parameters_it) {
1472
    DCHECK_NOT_NULL((*parameters_it).node);
1473 1474
    a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
            (*parameters_it).node);
1475 1476 1477 1478 1479 1480 1481 1482 1483
  }
  return a.Finish();
}

// 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.
Node* JSCreateLowering::AllocateAliasedArguments(
    Node* effect, Node* control, Node* frame_state, Node* context,
1484
    const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
1485
  FrameStateInfo state_info = FrameStateInfoOf(frame_state->op());
1486 1487 1488 1489 1490
  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.
1491
  int parameter_count = shared.internal_formal_parameter_count();
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
  if (parameter_count == 0) {
    return AllocateArguments(effect, control, frame_state);
  }

  // Calculate number of argument values being aliased/mapped.
  int mapped_count = Min(argument_count, parameter_count);
  *has_aliased_arguments = true;

  // Prepare an iterator over argument values recorded in the frame state.
  Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
  StateValuesAccess parameters_access(parameters);
1503
  auto parameters_it = ++parameters_access.begin();
1504 1505 1506 1507

  // 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.
1508
  AllocationBuilder aa(jsgraph(), effect, control);
1509
  aa.AllocateArray(argument_count, factory()->fixed_array_map());
1510
  for (int i = 0; i < mapped_count; ++i, ++parameters_it) {
1511 1512
    aa.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
             jsgraph()->TheHoleConstant());
1513
  }
1514 1515
  for (int i = mapped_count; i < argument_count; ++i, ++parameters_it) {
    DCHECK_NOT_NULL((*parameters_it).node);
1516 1517
    aa.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i),
             (*parameters_it).node);
1518 1519 1520 1521
  }
  Node* arguments = aa.Finish();

  // Actually allocate the backing store.
1522
  AllocationBuilder a(jsgraph(), arguments, control);
1523
  a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1524 1525 1526 1527
  a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(0),
          context);
  a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(1),
          arguments);
1528 1529
  for (int i = 0; i < mapped_count; ++i) {
    int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
1530 1531
    a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i + 2),
            jsgraph()->Constant(idx));
1532 1533 1534 1535
  }
  return a.Finish();
}

1536 1537 1538 1539 1540 1541
// 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.
Node* JSCreateLowering::AllocateAliasedArguments(
    Node* effect, Node* control, Node* context, Node* arguments_frame,
1542
    Node* arguments_length, const SharedFunctionInfoRef& shared,
1543 1544 1545
    bool* has_aliased_arguments) {
  // If there is no aliasing, the arguments object elements are not
  // special in any way, we can just return an unmapped backing store.
1546
  int parameter_count = shared.internal_formal_parameter_count();
1547
  if (parameter_count == 0) {
1548
    return graph()->NewNode(simplified()->NewArgumentsElements(0),
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
                            arguments_frame, arguments_length, effect);
  }

  // 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.
  int mapped_count = parameter_count;
  *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.
  Node* arguments =
1563
      graph()->NewNode(simplified()->NewArgumentsElements(mapped_count),
1564 1565 1566
                       arguments_frame, arguments_length, effect);

  // Actually allocate the backing store.
1567
  AllocationBuilder a(jsgraph(), arguments, control);
1568
  a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
1569 1570 1571 1572
  a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(0),
          context);
  a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(1),
          arguments);
1573 1574 1575 1576 1577 1578 1579
  for (int i = 0; i < mapped_count; ++i) {
    int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
    Node* value = graph()->NewNode(
        common()->Select(MachineRepresentation::kTagged),
        graph()->NewNode(simplified()->NumberLessThan(), jsgraph()->Constant(i),
                         arguments_length),
        jsgraph()->Constant(idx), jsgraph()->TheHoleConstant());
1580 1581
    a.Store(AccessBuilder::ForFixedArrayElement(), jsgraph()->Constant(i + 2),
            value);
1582 1583 1584 1585
  }
  return a.Finish();
}

1586 1587 1588 1589 1590 1591 1592
Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
                                         ElementsKind elements_kind,
                                         int capacity,
                                         PretenureFlag pretenure) {
  DCHECK_LE(1, capacity);
  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);

1593
  Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1594 1595
                                 ? factory()->fixed_double_array_map()
                                 : factory()->fixed_array_map();
1596
  ElementAccess access = IsDoubleElementsKind(elements_kind)
1597 1598
                             ? AccessBuilder::ForFixedDoubleArrayElement()
                             : AccessBuilder::ForFixedArrayElement();
1599
  Node* value = jsgraph()->TheHoleConstant();
1600 1601

  // Actually allocate the backing store.
1602
  AllocationBuilder a(jsgraph(), effect, control);
1603 1604 1605 1606 1607 1608 1609 1610
  a.AllocateArray(capacity, elements_map, pretenure);
  for (int i = 0; i < capacity; ++i) {
    Node* index = jsgraph()->Constant(i);
    a.Store(access, index, value);
  }
  return a.Finish();
}

1611 1612 1613 1614 1615 1616 1617 1618
Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
                                         ElementsKind elements_kind,
                                         std::vector<Node*> const& values,
                                         PretenureFlag pretenure) {
  int const capacity = static_cast<int>(values.size());
  DCHECK_LE(1, capacity);
  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);

1619
  Handle<Map> elements_map = IsDoubleElementsKind(elements_kind)
1620 1621
                                 ? factory()->fixed_double_array_map()
                                 : factory()->fixed_array_map();
1622
  ElementAccess access = IsDoubleElementsKind(elements_kind)
1623 1624 1625 1626
                             ? AccessBuilder::ForFixedDoubleArrayElement()
                             : AccessBuilder::ForFixedArrayElement();

  // Actually allocate the backing store.
1627
  AllocationBuilder a(jsgraph(), effect, control);
1628 1629 1630 1631 1632 1633 1634 1635
  a.AllocateArray(capacity, elements_map, pretenure);
  for (int i = 0; i < capacity; ++i) {
    Node* index = jsgraph()->Constant(i);
    a.Store(access, index, values[i]);
  }
  return a.Finish();
}

1636
Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
1637
                                            JSObjectRef boilerplate,
1638
                                            PretenureFlag pretenure) {
1639 1640 1641 1642
  // Setup the properties backing store.
  Node* properties = jsgraph()->EmptyFixedArrayConstant();

  // Compute the in-object properties to store first (might have effects).
1643
  MapRef boilerplate_map = boilerplate.map();
1644
  ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
1645 1646
  inobject_fields.reserve(boilerplate_map.GetInObjectProperties());
  int const boilerplate_nof = boilerplate_map.NumberOfOwnDescriptors();
1647 1648
  for (int i = 0; i < boilerplate_nof; ++i) {
    PropertyDetails const property_details =
1649
        boilerplate_map.GetPropertyDetails(i);
1650 1651
    if (property_details.location() != kField) continue;
    DCHECK_EQ(kData, property_details.kind());
1652
    NameRef property_name = boilerplate_map.GetPropertyKey(i);
1653 1654
    FieldIndex index = boilerplate_map.GetFieldIndexFor(i);
    FieldAccess access = {
1655
        kTaggedBase,        index.offset(), property_name.object(),
1656 1657
        MaybeHandle<Map>(), Type::Any(),    MachineType::AnyTagged(),
        kFullWriteBarrier};
1658
    Node* value;
1659
    if (boilerplate_map.IsUnboxedDoubleField(i)) {
1660 1661
      access.machine_type = MachineType::Float64();
      access.type = Type::Number();
1662
      value = jsgraph()->Constant(boilerplate.RawFastDoublePropertyAt(index));
1663
    } else {
1664
      ObjectRef boilerplate_value = boilerplate.RawFastPropertyAt(index);
1665 1666
      if (boilerplate_value.IsJSObject()) {
        JSObjectRef boilerplate_object = boilerplate_value.AsJSObject();
1667 1668
        value = effect =
            AllocateFastLiteral(effect, control, boilerplate_object, pretenure);
1669
      } else if (property_details.representation().IsDouble()) {
1670
        double number = boilerplate_value.AsMutableHeapNumber().value();
1671
        // Allocate a mutable HeapNumber box and store the value into it.
1672
        AllocationBuilder builder(jsgraph(), effect, control);
1673 1674 1675 1676 1677 1678
        builder.Allocate(HeapNumber::kSize, pretenure);
        builder.Store(AccessBuilder::ForMap(),
                      factory()->mutable_heap_number_map());
        builder.Store(AccessBuilder::ForHeapNumberValue(),
                      jsgraph()->Constant(number));
        value = effect = builder.Finish();
1679 1680
      } else if (property_details.representation().IsSmi()) {
        // Ensure that value is stored as smi.
1681 1682 1683 1684 1685
        bool is_uninitialized =
            boilerplate_value.IsHeapObject() &&
            boilerplate_value.AsHeapObject().map().oddball_type() ==
                OddballType::kUninitialized;
        value = is_uninitialized
1686
                    ? jsgraph()->ZeroConstant()
1687
                    : jsgraph()->Constant(boilerplate_value.AsSmi());
1688
      } else {
1689
        value = jsgraph()->Constant(boilerplate_value);
1690 1691 1692 1693 1694 1695
      }
    }
    inobject_fields.push_back(std::make_pair(access, value));
  }

  // Fill slack at the end of the boilerplate object with filler maps.
1696
  int const boilerplate_length = boilerplate_map.GetInObjectProperties();
1697 1698
  for (int index = static_cast<int>(inobject_fields.size());
       index < boilerplate_length; ++index) {
1699 1700
    FieldAccess access =
        AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
1701 1702 1703 1704
    Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
    inobject_fields.push_back(std::make_pair(access, value));
  }

1705
  // Setup the elements backing store.
1706 1707
  Node* elements =
      AllocateFastLiteralElements(effect, control, boilerplate, pretenure);
1708 1709
  if (elements->op()->EffectOutputCount() > 0) effect = elements;

1710
  // Actually allocate and initialize the object.
1711
  AllocationBuilder builder(jsgraph(), effect, control);
1712
  builder.Allocate(boilerplate_map.instance_size(), pretenure,
1713
                   Type::For(boilerplate_map));
1714
  builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1715
  builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
1716
  builder.Store(AccessBuilder::ForJSObjectElements(), elements);
1717
  if (boilerplate.IsJSArray()) {
1718
    JSArrayRef boilerplate_array = boilerplate.AsJSArray();
1719
    builder.Store(
1720
        AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),
1721
        boilerplate_array.length());
1722
  }
1723
  for (auto const& inobject_field : inobject_fields) {
1724 1725 1726 1727 1728
    builder.Store(inobject_field.first, inobject_field.second);
  }
  return builder.Finish();
}

1729 1730 1731
Node* JSCreateLowering::AllocateFastLiteralElements(Node* effect, Node* control,
                                                    JSObjectRef boilerplate,
                                                    PretenureFlag pretenure) {
1732
  FixedArrayBaseRef boilerplate_elements = boilerplate.elements();
1733 1734

  // Empty or copy-on-write elements just store a constant.
1735
  int const elements_length = boilerplate_elements.length();
1736 1737
  MapRef elements_map = boilerplate_elements.map();
  if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
1738
    if (pretenure == TENURED) {
1739 1740
      boilerplate.EnsureElementsTenured();
      boilerplate_elements = boilerplate.elements();
1741
    }
1742
    return jsgraph()->HeapConstant(boilerplate_elements.object());
1743 1744 1745 1746
  }

  // Compute the elements to store first (might have effects).
  ZoneVector<Node*> elements_values(elements_length, zone());
1747 1748
  if (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
    FixedDoubleArrayRef elements = boilerplate_elements.AsFixedDoubleArray();
1749
    for (int i = 0; i < elements_length; ++i) {
1750
      if (elements.is_the_hole(i)) {
1751
        elements_values[i] = jsgraph()->TheHoleConstant();
1752
      } else {
1753
        elements_values[i] = jsgraph()->Constant(elements.get_scalar(i));
1754 1755 1756
      }
    }
  } else {
1757
    FixedArrayRef elements = boilerplate_elements.AsFixedArray();
1758
    for (int i = 0; i < elements_length; ++i) {
1759 1760 1761 1762
      ObjectRef element_value = elements.get(i);
      if (element_value.IsJSObject()) {
        elements_values[i] = effect = AllocateFastLiteral(
            effect, control, element_value.AsJSObject(), pretenure);
1763
      } else {
1764
        elements_values[i] = jsgraph()->Constant(element_value);
1765 1766 1767 1768 1769
      }
    }
  }

  // Allocate the backing store array and store the elements.
1770
  AllocationBuilder builder(jsgraph(), effect, control);
1771
  builder.AllocateArray(elements_length, elements_map.object(), pretenure);
1772
  ElementAccess const access =
1773
      (elements_map.instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
1774 1775 1776 1777 1778 1779 1780 1781
          ? AccessBuilder::ForFixedDoubleArrayElement()
          : AccessBuilder::ForFixedArrayElement();
  for (int i = 0; i < elements_length; ++i) {
    builder.Store(access, jsgraph()->Constant(i), elements_values[i]);
  }
  return builder.Finish();
}

1782
Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
1783
                                              JSRegExpRef boilerplate) {
1784
  MapRef boilerplate_map = boilerplate.map();
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799

  // Sanity check that JSRegExp object layout hasn't changed.
  STATIC_ASSERT(JSRegExp::kDataOffset == JSObject::kHeaderSize);
  STATIC_ASSERT(JSRegExp::kSourceOffset ==
                JSRegExp::kDataOffset + kPointerSize);
  STATIC_ASSERT(JSRegExp::kFlagsOffset ==
                JSRegExp::kSourceOffset + kPointerSize);
  STATIC_ASSERT(JSRegExp::kSize == JSRegExp::kFlagsOffset + kPointerSize);
  STATIC_ASSERT(JSRegExp::kLastIndexOffset == JSRegExp::kSize);
  STATIC_ASSERT(JSRegExp::kInObjectFieldCount == 1);  // LastIndex.

  const PretenureFlag pretenure = NOT_TENURED;
  const int size =
      JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;

1800
  AllocationBuilder builder(jsgraph(), effect, control);
1801
  builder.Allocate(size, pretenure, Type::For(boilerplate_map));
1802
  builder.Store(AccessBuilder::ForMap(), boilerplate_map);
1803
  builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
1804 1805 1806 1807 1808 1809
                boilerplate.raw_properties_or_hash());
  builder.Store(AccessBuilder::ForJSObjectElements(), boilerplate.elements());

  builder.Store(AccessBuilder::ForJSRegExpData(), boilerplate.data());
  builder.Store(AccessBuilder::ForJSRegExpSource(), boilerplate.source());
  builder.Store(AccessBuilder::ForJSRegExpFlags(), boilerplate.flags());
1810
  builder.Store(AccessBuilder::ForJSRegExpLastIndex(),
1811
                boilerplate.last_index());
1812 1813 1814 1815

  return builder.Finish();
}

1816 1817 1818
Factory* JSCreateLowering::factory() const {
  return jsgraph()->isolate()->factory();
}
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829

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

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

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

1830
NativeContextRef JSCreateLowering::native_context() const {
1831
  return broker()->native_context();
1832 1833
}

1834 1835 1836
}  // namespace compiler
}  // namespace internal
}  // namespace v8