Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/compiler/js-create-lowering.cc b/src/compiler/js-create-lowering.cc
new file mode 100644
index 0000000..df5c8d0
--- /dev/null
+++ b/src/compiler/js-create-lowering.cc
@@ -0,0 +1,1096 @@
+// 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/allocation-site-scopes.h"
+#include "src/code-factory.h"
+#include "src/compilation-dependencies.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/operator-properties.h"
+#include "src/compiler/simplified-operator.h"
+#include "src/compiler/state-values-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+// A helper class to construct inline allocations on the simplified operator
+// level. This keeps track of the effect chain for initial stores on a newly
+// allocated object and also provides helpers for commonly allocated objects.
+class AllocationBuilder final {
+ public:
+  AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control)
+      : jsgraph_(jsgraph),
+        allocation_(nullptr),
+        effect_(effect),
+        control_(control) {}
+
+  // Primitive allocation of static size.
+  void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) {
+    effect_ = graph()->NewNode(common()->BeginRegion(), effect_);
+    allocation_ =
+        graph()->NewNode(simplified()->Allocate(pretenure),
+                         jsgraph()->Constant(size), effect_, control_);
+    effect_ = allocation_;
+  }
+
+  // Primitive store into a field.
+  void Store(const FieldAccess& access, Node* value) {
+    effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_,
+                               value, effect_, control_);
+  }
+
+  // Primitive store into an element.
+  void Store(ElementAccess const& access, Node* index, Node* value) {
+    effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_,
+                               index, value, effect_, control_);
+  }
+
+  // Compound allocation of a FixedArray.
+  void AllocateArray(int length, Handle<Map> map,
+                     PretenureFlag pretenure = NOT_TENURED) {
+    DCHECK(map->instance_type() == FIXED_ARRAY_TYPE ||
+           map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE);
+    int size = (map->instance_type() == FIXED_ARRAY_TYPE)
+                   ? FixedArray::SizeFor(length)
+                   : FixedDoubleArray::SizeFor(length);
+    Allocate(size, pretenure);
+    Store(AccessBuilder::ForMap(), map);
+    Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length));
+  }
+
+  // Compound store of a constant into a field.
+  void Store(const FieldAccess& access, Handle<Object> value) {
+    Store(access, jsgraph()->Constant(value));
+  }
+
+  void FinishAndChange(Node* node) {
+    NodeProperties::SetType(allocation_, NodeProperties::GetType(node));
+    node->ReplaceInput(0, allocation_);
+    node->ReplaceInput(1, effect_);
+    node->TrimInputCount(2);
+    NodeProperties::ChangeOp(node, common()->FinishRegion());
+  }
+
+  Node* Finish() {
+    return graph()->NewNode(common()->FinishRegion(), allocation_, effect_);
+  }
+
+ protected:
+  JSGraph* jsgraph() { return jsgraph_; }
+  Graph* graph() { return jsgraph_->graph(); }
+  CommonOperatorBuilder* common() { return jsgraph_->common(); }
+  SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); }
+
+ private:
+  JSGraph* const jsgraph_;
+  Node* allocation_;
+  Node* effect_;
+  Node* control_;
+};
+
+// Retrieves the frame state holding actual argument values.
+Node* GetArgumentsFrameState(Node* frame_state) {
+  Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state, 0);
+  FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state);
+  return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
+             ? outer_state
+             : frame_state;
+}
+
+// Checks whether allocation using the given target and new.target can be
+// inlined.
+bool IsAllocationInlineable(Handle<JSFunction> target,
+                            Handle<JSFunction> new_target) {
+  return new_target->has_initial_map() &&
+         new_target->initial_map()->constructor_or_backpointer() == *target;
+}
+
+// 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;
+
+// Determines whether the given array or object literal boilerplate satisfies
+// all limits to be considered for fast deep-copying and computes the total
+// size of all objects that are part of the graph.
+bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth,
+                   int* max_properties) {
+  DCHECK_GE(max_depth, 0);
+  DCHECK_GE(*max_properties, 0);
+
+  // Make sure the boilerplate map is not deprecated.
+  if (!JSObject::TryMigrateInstance(boilerplate)) return false;
+
+  // Check for too deep nesting.
+  if (max_depth == 0) return false;
+
+  // Check the elements.
+  Isolate* const isolate = boilerplate->GetIsolate();
+  Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
+  if (elements->length() > 0 &&
+      elements->map() != isolate->heap()->fixed_cow_array_map()) {
+    if (boilerplate->HasFastSmiOrObjectElements()) {
+      Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
+      int length = elements->length();
+      for (int i = 0; i < length; i++) {
+        if ((*max_properties)-- == 0) return false;
+        Handle<Object> value(fast_elements->get(i), isolate);
+        if (value->IsJSObject()) {
+          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
+          if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
+            return false;
+          }
+        }
+      }
+    } else if (!boilerplate->HasFastDoubleElements()) {
+      return false;
+    }
+  }
+
+  // TODO(turbofan): Do we want to support out-of-object properties?
+  Handle<FixedArray> properties(boilerplate->properties(), isolate);
+  if (properties->length() > 0) return false;
+
+  // Check the in-object properties.
+  Handle<DescriptorArray> descriptors(
+      boilerplate->map()->instance_descriptors(), isolate);
+  int limit = boilerplate->map()->NumberOfOwnDescriptors();
+  for (int i = 0; i < limit; i++) {
+    PropertyDetails details = descriptors->GetDetails(i);
+    if (details.type() != DATA) continue;
+    if ((*max_properties)-- == 0) return false;
+    FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
+    if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
+    Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
+    if (value->IsJSObject()) {
+      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
+      if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+// Maximum depth and total number of elements and properties for literal
+// graphs to be considered for fast deep-copying.
+const int kMaxFastLiteralDepth = 3;
+const int kMaxFastLiteralProperties = 8;
+
+}  // 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);
+    case IrOpcode::kJSCreateIterResultObject:
+      return ReduceJSCreateIterResultObject(node);
+    case IrOpcode::kJSCreateLiteralArray:
+    case IrOpcode::kJSCreateLiteralObject:
+      return ReduceJSCreateLiteral(node);
+    case IrOpcode::kJSCreateFunctionContext:
+      return ReduceJSCreateFunctionContext(node);
+    case IrOpcode::kJSCreateWithContext:
+      return ReduceJSCreateWithContext(node);
+    case IrOpcode::kJSCreateCatchContext:
+      return ReduceJSCreateCatchContext(node);
+    case IrOpcode::kJSCreateBlockContext:
+      return ReduceJSCreateBlockContext(node);
+    default:
+      break;
+  }
+  return NoChange();
+}
+
+Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreate, node->opcode());
+  Node* const target = NodeProperties::GetValueInput(node, 0);
+  Type* const target_type = NodeProperties::GetType(target);
+  Node* const new_target = NodeProperties::GetValueInput(node, 1);
+  Type* const new_target_type = NodeProperties::GetType(new_target);
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  // Extract constructor and original constructor function.
+  if (target_type->IsConstant() &&
+      new_target_type->IsConstant() &&
+      new_target_type->AsConstant()->Value()->IsJSFunction()) {
+    Handle<JSFunction> constructor =
+        Handle<JSFunction>::cast(target_type->AsConstant()->Value());
+    Handle<JSFunction> original_constructor =
+        Handle<JSFunction>::cast(new_target_type->AsConstant()->Value());
+    DCHECK(constructor->IsConstructor());
+    DCHECK(original_constructor->IsConstructor());
+
+    // Check if we can inline the allocation.
+    if (IsAllocationInlineable(constructor, original_constructor)) {
+      // Force completion of inobject slack tracking before
+      // generating code to finalize the instance size.
+      original_constructor->CompleteInobjectSlackTrackingIfActive();
+
+      // Compute instance size from initial map of {original_constructor}.
+      Handle<Map> initial_map(original_constructor->initial_map(), isolate());
+      int const instance_size = initial_map->instance_size();
+
+      // Add a dependency on the {initial_map} to make sure that this code is
+      // deoptimized whenever the {initial_map} of the {original_constructor}
+      // changes.
+      dependencies()->AssumeInitialMapCantChange(initial_map);
+
+      // Emit code to allocate the JSObject instance for the
+      // {original_constructor}.
+      AllocationBuilder a(jsgraph(), effect, graph()->start());
+      a.Allocate(instance_size);
+      a.Store(AccessBuilder::ForMap(), initial_map);
+      a.Store(AccessBuilder::ForJSObjectProperties(),
+              jsgraph()->EmptyFixedArrayConstant());
+      a.Store(AccessBuilder::ForJSObjectElements(),
+              jsgraph()->EmptyFixedArrayConstant());
+      for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) {
+        a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i),
+                jsgraph()->UndefinedConstant());
+      }
+      a.FinishAndChange(node);
+      return Changed(node);
+    }
+  }
+  return NoChange();
+}
+
+Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
+  CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
+  Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
+  Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
+  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
+
+  // 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) {
+    switch (type) {
+      case CreateArgumentsType::kMappedArguments: {
+        // TODO(mstarzinger): Duplicate parameters are not handled yet.
+        Handle<SharedFunctionInfo> shared_info;
+        if (!state_info.shared_info().ToHandle(&shared_info) ||
+            shared_info->has_duplicate_parameters()) {
+          return NoChange();
+        }
+        // TODO(bmeurer): Actually we don't need a frame state here.
+        Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
+        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+            isolate(), graph()->zone(), callable.descriptor(), 0,
+            CallDescriptor::kNeedsFrameState);
+        const Operator* new_op = common()->Call(desc);
+        Node* stub_code = jsgraph()->HeapConstant(callable.code());
+        node->InsertInput(graph()->zone(), 0, stub_code);
+        NodeProperties::ChangeOp(node, new_op);
+        return Changed(node);
+      }
+      case CreateArgumentsType::kUnmappedArguments: {
+        // TODO(bmeurer): Actually we don't need a frame state here.
+        Callable callable = CodeFactory::FastNewStrictArguments(isolate());
+        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+            isolate(), graph()->zone(), callable.descriptor(), 0,
+            CallDescriptor::kNeedsFrameState);
+        const Operator* new_op = common()->Call(desc);
+        Node* stub_code = jsgraph()->HeapConstant(callable.code());
+        node->InsertInput(graph()->zone(), 0, stub_code);
+        NodeProperties::ChangeOp(node, new_op);
+        return Changed(node);
+      }
+      case CreateArgumentsType::kRestParameter: {
+        // TODO(bmeurer): Actually we don't need a frame state here.
+        Callable callable = CodeFactory::FastNewRestParameter(isolate());
+        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+            isolate(), graph()->zone(), callable.descriptor(), 0,
+            CallDescriptor::kNeedsFrameState);
+        const Operator* new_op = common()->Call(desc);
+        Node* stub_code = jsgraph()->HeapConstant(callable.code());
+        node->InsertInput(graph()->zone(), 0, stub_code);
+        NodeProperties::ChangeOp(node, new_op);
+        return Changed(node);
+      }
+    }
+    UNREACHABLE();
+  } 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) {
+      Handle<SharedFunctionInfo> shared;
+      if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
+      Node* const callee = NodeProperties::GetValueInput(node, 0);
+      Node* const control = NodeProperties::GetControlInput(node);
+      Node* const context = NodeProperties::GetContextInput(node);
+      Node* effect = NodeProperties::GetEffectInput(node);
+      // TODO(mstarzinger): Duplicate parameters are not handled yet.
+      if (shared->has_duplicate_parameters()) return NoChange();
+      // 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);
+      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
+      // 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;
+      // Load the arguments object map from the current native context.
+      Node* const load_native_context = effect = graph()->NewNode(
+          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+          context, context, effect);
+      Node* const load_arguments_map = effect = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForContextSlot(
+              has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX
+                                    : Context::SLOPPY_ARGUMENTS_MAP_INDEX)),
+          load_native_context, effect, control);
+      // Actually allocate and initialize the arguments object.
+      AllocationBuilder a(jsgraph(), effect, control);
+      Node* properties = jsgraph()->EmptyFixedArrayConstant();
+      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
+      STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
+      a.Allocate(JSSloppyArgumentsObject::kSize);
+      a.Store(AccessBuilder::ForMap(), load_arguments_map);
+      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
+      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* const control = NodeProperties::GetControlInput(node);
+      Node* const context = NodeProperties::GetContextInput(node);
+      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);
+      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
+      // 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;
+      // Load the arguments object map from the current native context.
+      Node* const load_native_context = effect = graph()->NewNode(
+          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+          context, context, effect);
+      Node* const load_arguments_map = effect = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForContextSlot(
+              Context::STRICT_ARGUMENTS_MAP_INDEX)),
+          load_native_context, effect, control);
+      // Actually allocate and initialize the arguments object.
+      AllocationBuilder a(jsgraph(), effect, control);
+      Node* properties = jsgraph()->EmptyFixedArrayConstant();
+      int length = args_state_info.parameter_count() - 1;  // Minus receiver.
+      STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
+      a.Allocate(JSStrictArgumentsObject::kSize);
+      a.Store(AccessBuilder::ForMap(), load_arguments_map);
+      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
+      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) {
+      Handle<SharedFunctionInfo> shared;
+      if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
+      int start_index = shared->internal_formal_parameter_count();
+      // Use inline allocation for all unmapped arguments objects within inlined
+      // (i.e. non-outermost) frames, independent of the object size.
+      Node* const control = NodeProperties::GetControlInput(node);
+      Node* const context = NodeProperties::GetContextInput(node);
+      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);
+      FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state);
+      // 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;
+      // Load the JSArray object map from the current native context.
+      Node* const load_native_context = effect = graph()->NewNode(
+          javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+          context, context, effect);
+      Node* const load_jsarray_map = effect = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForContextSlot(
+              Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX)),
+          load_native_context, effect, control);
+      // Actually allocate and initialize the jsarray.
+      AllocationBuilder a(jsgraph(), effect, control);
+      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);
+      a.Store(AccessBuilder::ForMap(), load_jsarray_map);
+      a.Store(AccessBuilder::ForJSObjectProperties(), properties);
+      a.Store(AccessBuilder::ForJSObjectElements(), elements);
+      a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS),
+              jsgraph()->Constant(length));
+      RelaxControls(node);
+      a.FinishAndChange(node);
+      return Changed(node);
+    }
+  }
+
+  return NoChange();
+}
+
+Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
+                                           int capacity,
+                                           Handle<AllocationSite> site) {
+  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+
+  // Extract transition and tenuring feedback from the {site} and add
+  // appropriate code dependencies on the {site} if deoptimization is
+  // enabled.
+  PretenureFlag pretenure = site->GetPretenureMode();
+  ElementsKind elements_kind = site->GetElementsKind();
+  DCHECK(IsFastElementsKind(elements_kind));
+  dependencies()->AssumeTenuringDecision(site);
+  dependencies()->AssumeTransitionStable(site);
+
+  // Retrieve the initial map for the array from the appropriate native context.
+  Node* native_context = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+      context, context, effect);
+  Node* js_array_map = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::ArrayMapIndex(elements_kind), true),
+      native_context, native_context, effect);
+
+  // 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.
+  AllocationBuilder a(jsgraph(), effect, control);
+  a.Allocate(JSArray::kSize, pretenure);
+  a.Store(AccessBuilder::ForMap(), js_array_map);
+  a.Store(AccessBuilder::ForJSObjectProperties(), properties);
+  a.Store(AccessBuilder::ForJSObjectElements(), elements);
+  a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length);
+  RelaxControls(node);
+  a.FinishAndChange(node);
+  return Changed(node);
+}
+
+Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
+  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
+  Node* target = NodeProperties::GetValueInput(node, 0);
+  Node* new_target = NodeProperties::GetValueInput(node, 1);
+
+  // TODO(bmeurer): Optimize the subclassing case.
+  if (target != new_target) return NoChange();
+
+  // Check if we have a feedback {site} on the {node}.
+  Handle<AllocationSite> site = p.site();
+  if (p.site().is_null()) return NoChange();
+
+  // Attempt to inline calls to the Array constructor for the relevant cases
+  // where either no arguments are provided, or exactly one unsigned number
+  // argument is given.
+  if (site->CanInlineCall()) {
+    if (p.arity() == 0) {
+      Node* length = jsgraph()->ZeroConstant();
+      int capacity = JSArray::kPreallocatedArrayElements;
+      return ReduceNewArray(node, length, capacity, site);
+    } else if (p.arity() == 1) {
+      Node* length = NodeProperties::GetValueInput(node, 2);
+      Type* length_type = NodeProperties::GetType(length);
+      if (length_type->Is(Type::SignedSmall()) &&
+          length_type->Min() >= 0 &&
+          length_type->Max() <= kElementLoopUnrollLimit) {
+        int capacity = static_cast<int>(length_type->Max());
+        return ReduceNewArray(node, length, capacity, site);
+      }
+    }
+  }
+
+  return NoChange();
+}
+
+Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
+  Node* value = NodeProperties::GetValueInput(node, 0);
+  Node* done = NodeProperties::GetValueInput(node, 1);
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* effect = NodeProperties::GetEffectInput(node);
+
+  // Load the JSIteratorResult map for the {context}.
+  Node* native_context = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+      context, context, effect);
+  Node* iterator_result_map = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::ITERATOR_RESULT_MAP_INDEX, true),
+      native_context, native_context, effect);
+
+  // Emit code to allocate the JSIteratorResult instance.
+  AllocationBuilder a(jsgraph(), effect, graph()->start());
+  a.Allocate(JSIteratorResult::kSize);
+  a.Store(AccessBuilder::ForMap(), iterator_result_map);
+  a.Store(AccessBuilder::ForJSObjectProperties(),
+          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);
+}
+
+Reduction JSCreateLowering::ReduceJSCreateLiteral(Node* node) {
+  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);
+
+  Handle<LiteralsArray> literals_array;
+  if (GetSpecializationLiterals(node).ToHandle(&literals_array)) {
+    Handle<Object> literal(literals_array->literal(p.index()), isolate());
+    if (literal->IsAllocationSite()) {
+      Handle<AllocationSite> site = Handle<AllocationSite>::cast(literal);
+      Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()),
+                                   isolate());
+      int max_properties = kMaxFastLiteralProperties;
+      if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
+        AllocationSiteUsageContext site_context(isolate(), site, false);
+        site_context.EnterNewScope();
+        Node* value = effect =
+            AllocateFastLiteral(effect, control, boilerplate, &site_context);
+        site_context.ExitScope(site, boilerplate);
+        ReplaceWithValue(node, value, effect, control);
+        return Replace(value);
+      }
+    }
+  }
+
+  return NoChange();
+}
+
+Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
+  int slot_count = OpParameter<int>(node->op());
+  Node* const closure = NodeProperties::GetValueInput(node, 0);
+
+  // 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();
+    Node* native_context = effect = graph()->NewNode(
+        javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+        context, context, effect);
+    AllocationBuilder a(jsgraph(), effect, control);
+    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
+    int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
+    a.AllocateArray(context_length, factory()->function_context_map());
+    a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
+    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
+    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
+    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
+            native_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());
+  Node* object = NodeProperties::GetValueInput(node, 0);
+  Node* closure = NodeProperties::GetValueInput(node, 1);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* native_context = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+      context, context, effect);
+  AllocationBuilder a(jsgraph(), effect, control);
+  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
+  a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
+  a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
+  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
+  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), object);
+  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
+          native_context);
+  RelaxControls(node);
+  a.FinishAndChange(node);
+  return Changed(node);
+}
+
+Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode());
+  Handle<String> name = OpParameter<Handle<String>>(node);
+  Node* exception = NodeProperties::GetValueInput(node, 0);
+  Node* closure = NodeProperties::GetValueInput(node, 1);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* native_context = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+      context, context, effect);
+  AllocationBuilder a(jsgraph(), effect, control);
+  STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
+  a.AllocateArray(Context::MIN_CONTEXT_SLOTS + 1,
+                  factory()->catch_context_map());
+  a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
+  a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
+  a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), name);
+  a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
+          native_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());
+  Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
+  int const context_length = scope_info->ContextLength();
+  Node* const closure = NodeProperties::GetValueInput(node, 0);
+
+  // 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);
+    Node* extension = jsgraph()->Constant(scope_info);
+    Node* native_context = effect = graph()->NewNode(
+        javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+        context, context, effect);
+    AllocationBuilder a(jsgraph(), effect, control);
+    STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);  // Ensure fully covered.
+    a.AllocateArray(context_length, factory()->block_context_map());
+    a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
+    a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
+    a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
+    a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
+            native_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();
+}
+
+// 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) {
+  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
+  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.
+  AllocationBuilder a(jsgraph(), effect, control);
+  a.AllocateArray(argument_count, factory()->fixed_array_map());
+  for (int i = 0; i < argument_count; ++i, ++parameters_it) {
+    a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
+  }
+  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) {
+  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
+  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.
+  AllocationBuilder a(jsgraph(), effect, control);
+  a.AllocateArray(num_elements, factory()->fixed_array_map());
+  for (int i = 0; i < num_elements; ++i, ++parameters_it) {
+    a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node);
+  }
+  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,
+    Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) {
+  FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
+  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.
+  int parameter_count = shared->internal_formal_parameter_count();
+  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);
+  auto paratemers_it = ++parameters_access.begin();
+
+  // 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.
+  AllocationBuilder aa(jsgraph(), effect, control);
+  aa.AllocateArray(argument_count, factory()->fixed_array_map());
+  for (int i = 0; i < mapped_count; ++i, ++paratemers_it) {
+    aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant());
+  }
+  for (int i = mapped_count; i < argument_count; ++i, ++paratemers_it) {
+    aa.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node);
+  }
+  Node* arguments = aa.Finish();
+
+  // Actually allocate the backing store.
+  AllocationBuilder a(jsgraph(), arguments, control);
+  a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map());
+  a.Store(AccessBuilder::ForFixedArraySlot(0), context);
+  a.Store(AccessBuilder::ForFixedArraySlot(1), arguments);
+  for (int i = 0; i < mapped_count; ++i) {
+    int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i;
+    a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx));
+  }
+  return a.Finish();
+}
+
+Node* JSCreateLowering::AllocateElements(Node* effect, Node* control,
+                                         ElementsKind elements_kind,
+                                         int capacity,
+                                         PretenureFlag pretenure) {
+  DCHECK_LE(1, capacity);
+  DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray);
+
+  Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind)
+                                 ? factory()->fixed_double_array_map()
+                                 : factory()->fixed_array_map();
+  ElementAccess access = IsFastDoubleElementsKind(elements_kind)
+                             ? AccessBuilder::ForFixedDoubleArrayElement()
+                             : AccessBuilder::ForFixedArrayElement();
+  Node* value =
+      IsFastDoubleElementsKind(elements_kind)
+          ? jsgraph()->Float64Constant(bit_cast<double>(kHoleNanInt64))
+          : jsgraph()->TheHoleConstant();
+
+  // Actually allocate the backing store.
+  AllocationBuilder a(jsgraph(), effect, control);
+  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();
+}
+
+Node* JSCreateLowering::AllocateFastLiteral(
+    Node* effect, Node* control, Handle<JSObject> boilerplate,
+    AllocationSiteUsageContext* site_context) {
+  Handle<AllocationSite> current_site(*site_context->current(), isolate());
+  dependencies()->AssumeTransitionStable(current_site);
+
+  PretenureFlag pretenure = NOT_TENURED;
+  if (FLAG_allocation_site_pretenuring) {
+    Handle<AllocationSite> top_site(*site_context->top(), isolate());
+    pretenure = top_site->GetPretenureMode();
+    if (current_site.is_identical_to(top_site)) {
+      // We install a dependency for pretenuring only on the outermost literal.
+      dependencies()->AssumeTenuringDecision(top_site);
+    }
+  }
+
+  // Setup the properties backing store.
+  Node* properties = jsgraph()->EmptyFixedArrayConstant();
+
+  // Setup the elements backing store.
+  Node* elements = AllocateFastLiteralElements(effect, control, boilerplate,
+                                               pretenure, site_context);
+  if (elements->op()->EffectOutputCount() > 0) effect = elements;
+
+  // Compute the in-object properties to store first (might have effects).
+  Handle<Map> boilerplate_map(boilerplate->map(), isolate());
+  ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone());
+  inobject_fields.reserve(boilerplate_map->GetInObjectProperties());
+  int const boilerplate_nof = boilerplate_map->NumberOfOwnDescriptors();
+  for (int i = 0; i < boilerplate_nof; ++i) {
+    PropertyDetails const property_details =
+        boilerplate_map->instance_descriptors()->GetDetails(i);
+    if (property_details.type() != DATA) continue;
+    Handle<Name> property_name(
+        boilerplate_map->instance_descriptors()->GetKey(i), isolate());
+    FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i);
+    FieldAccess access = {kTaggedBase, index.offset(), property_name,
+                          Type::Tagged(), MachineType::AnyTagged()};
+    Node* value;
+    if (boilerplate->IsUnboxedDoubleField(index)) {
+      access.machine_type = MachineType::Float64();
+      access.type = Type::Number();
+      value = jsgraph()->Constant(boilerplate->RawFastDoublePropertyAt(index));
+    } else {
+      Handle<Object> boilerplate_value(boilerplate->RawFastPropertyAt(index),
+                                       isolate());
+      if (boilerplate_value->IsJSObject()) {
+        Handle<JSObject> boilerplate_object =
+            Handle<JSObject>::cast(boilerplate_value);
+        Handle<AllocationSite> current_site = site_context->EnterNewScope();
+        value = effect = AllocateFastLiteral(effect, control,
+                                             boilerplate_object, site_context);
+        site_context->ExitScope(current_site, boilerplate_object);
+      } else if (property_details.representation().IsDouble()) {
+        // Allocate a mutable HeapNumber box and store the value into it.
+        value = effect = AllocateMutableHeapNumber(
+            Handle<HeapNumber>::cast(boilerplate_value)->value(),
+            effect, control);
+      } else if (property_details.representation().IsSmi()) {
+        // Ensure that value is stored as smi.
+        value = boilerplate_value->IsUninitialized()
+                    ? jsgraph()->ZeroConstant()
+                    : jsgraph()->Constant(boilerplate_value);
+      } else {
+        value = jsgraph()->Constant(boilerplate_value);
+      }
+    }
+    inobject_fields.push_back(std::make_pair(access, value));
+  }
+
+  // Fill slack at the end of the boilerplate object with filler maps.
+  int const boilerplate_length = boilerplate_map->GetInObjectProperties();
+  for (int index = static_cast<int>(inobject_fields.size());
+       index < boilerplate_length; ++index) {
+    FieldAccess access =
+        AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index);
+    Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map());
+    inobject_fields.push_back(std::make_pair(access, value));
+  }
+
+  // Actually allocate and initialize the object.
+  AllocationBuilder builder(jsgraph(), effect, control);
+  builder.Allocate(boilerplate_map->instance_size(), pretenure);
+  builder.Store(AccessBuilder::ForMap(), boilerplate_map);
+  builder.Store(AccessBuilder::ForJSObjectProperties(), properties);
+  builder.Store(AccessBuilder::ForJSObjectElements(), elements);
+  if (boilerplate_map->IsJSArrayMap()) {
+    Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate);
+    builder.Store(
+        AccessBuilder::ForJSArrayLength(boilerplate_array->GetElementsKind()),
+        handle(boilerplate_array->length(), isolate()));
+  }
+  for (auto const inobject_field : inobject_fields) {
+    builder.Store(inobject_field.first, inobject_field.second);
+  }
+  return builder.Finish();
+}
+
+Node* JSCreateLowering::AllocateFastLiteralElements(
+    Node* effect, Node* control, Handle<JSObject> boilerplate,
+    PretenureFlag pretenure, AllocationSiteUsageContext* site_context) {
+  Handle<FixedArrayBase> boilerplate_elements(boilerplate->elements(),
+                                              isolate());
+
+  // Empty or copy-on-write elements just store a constant.
+  if (boilerplate_elements->length() == 0 ||
+      boilerplate_elements->map() == isolate()->heap()->fixed_cow_array_map()) {
+    if (pretenure == TENURED &&
+        isolate()->heap()->InNewSpace(*boilerplate_elements)) {
+      // If we would like to pretenure a fixed cow array, we must ensure that
+      // the array is already in old space, otherwise we'll create too many
+      // old-to-new-space pointers (overflowing the store buffer).
+      boilerplate_elements = Handle<FixedArrayBase>(
+          isolate()->factory()->CopyAndTenureFixedCOWArray(
+              Handle<FixedArray>::cast(boilerplate_elements)));
+      boilerplate->set_elements(*boilerplate_elements);
+    }
+    return jsgraph()->HeapConstant(boilerplate_elements);
+  }
+
+  // Compute the elements to store first (might have effects).
+  int const elements_length = boilerplate_elements->length();
+  Handle<Map> elements_map(boilerplate_elements->map(), isolate());
+  ZoneVector<Node*> elements_values(elements_length, zone());
+  if (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) {
+    Handle<FixedDoubleArray> elements =
+        Handle<FixedDoubleArray>::cast(boilerplate_elements);
+    for (int i = 0; i < elements_length; ++i) {
+      if (elements->is_the_hole(i)) {
+        // TODO(turbofan): We cannot currently safely pass thru the (signaling)
+        // hole NaN in C++ code, as the C++ compiler on Intel might use FPU
+        // instructions/registers for doubles and therefore make the NaN quiet.
+        // We should consider passing doubles in the compiler as raw int64
+        // values to prevent this.
+        elements_values[i] = effect =
+            graph()->NewNode(simplified()->LoadElement(
+                                 AccessBuilder::ForFixedDoubleArrayElement()),
+                             jsgraph()->HeapConstant(elements),
+                             jsgraph()->Constant(i), effect, control);
+      } else {
+        elements_values[i] = jsgraph()->Constant(elements->get_scalar(i));
+      }
+    }
+  } else {
+    Handle<FixedArray> elements =
+        Handle<FixedArray>::cast(boilerplate_elements);
+    for (int i = 0; i < elements_length; ++i) {
+      if (elements->is_the_hole(i)) {
+        elements_values[i] = jsgraph()->TheHoleConstant();
+      } else {
+        Handle<Object> element_value(elements->get(i), isolate());
+        if (element_value->IsJSObject()) {
+          Handle<JSObject> boilerplate_object =
+              Handle<JSObject>::cast(element_value);
+          Handle<AllocationSite> current_site = site_context->EnterNewScope();
+          elements_values[i] = effect = AllocateFastLiteral(
+              effect, control, boilerplate_object, site_context);
+          site_context->ExitScope(current_site, boilerplate_object);
+        } else {
+          elements_values[i] = jsgraph()->Constant(element_value);
+        }
+      }
+    }
+  }
+
+  // Allocate the backing store array and store the elements.
+  AllocationBuilder builder(jsgraph(), effect, control);
+  builder.AllocateArray(elements_length, elements_map, pretenure);
+  ElementAccess const access =
+      (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE)
+          ? AccessBuilder::ForFixedDoubleArrayElement()
+          : AccessBuilder::ForFixedArrayElement();
+  for (int i = 0; i < elements_length; ++i) {
+    builder.Store(access, jsgraph()->Constant(i), elements_values[i]);
+  }
+  return builder.Finish();
+}
+
+Node* JSCreateLowering::AllocateMutableHeapNumber(double value, Node* effect,
+                                                  Node* control) {
+  // TODO(turbofan): Support inline allocation of MutableHeapNumber
+  // (requires proper alignment on Allocate, and Begin/FinishRegion).
+  Callable callable = CodeFactory::AllocateMutableHeapNumber(isolate());
+  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+      isolate(), jsgraph()->zone(), callable.descriptor(), 0,
+      CallDescriptor::kNoFlags, Operator::kNoThrow);
+  Node* result = effect = graph()->NewNode(
+      common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
+      jsgraph()->NoContextConstant(), effect, control);
+  effect = graph()->NewNode(
+      simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result,
+      jsgraph()->Constant(value), effect, control);
+  return result;
+}
+
+MaybeHandle<LiteralsArray> JSCreateLowering::GetSpecializationLiterals(
+    Node* node) {
+  Node* const closure = NodeProperties::GetValueInput(node, 0);
+  switch (closure->opcode()) {
+    case IrOpcode::kHeapConstant: {
+      Handle<HeapObject> object = OpParameter<Handle<HeapObject>>(closure);
+      return handle(Handle<JSFunction>::cast(object)->literals());
+    }
+    case IrOpcode::kParameter: {
+      int const index = ParameterIndexOf(closure->op());
+      // The closure is always the last parameter to a JavaScript function, and
+      // {Parameter} indices start at -1, so value outputs of {Start} look like
+      // this: closure, receiver, param0, ..., paramN, context.
+      if (index == -1) {
+        return literals_array_;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  return MaybeHandle<LiteralsArray>();
+}
+
+Factory* JSCreateLowering::factory() const { return isolate()->factory(); }
+
+Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }
+
+Isolate* JSCreateLowering::isolate() const { return jsgraph()->isolate(); }
+
+JSOperatorBuilder* JSCreateLowering::javascript() const {
+  return jsgraph()->javascript();
+}
+
+CommonOperatorBuilder* JSCreateLowering::common() const {
+  return jsgraph()->common();
+}
+
+SimplifiedOperatorBuilder* JSCreateLowering::simplified() const {
+  return jsgraph()->simplified();
+}
+
+MachineOperatorBuilder* JSCreateLowering::machine() const {
+  return jsgraph()->machine();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8