Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: src/compiler/js-typed-lowering.cc

Issue 1678833002: [turbofan] Introduce JSCreateLowering for optimizing JSCreate nodes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-typed-lowering.cc
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 851b6d69c27ae521ed1cd8a8afec299eacb4b7b9..f0c4b81137b9cdb2cf2503fe6ad86916938f99d6 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -11,7 +11,6 @@
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
-#include "src/compiler/state-values-utils.h"
#include "src/type-cache.h"
#include "src/types.h"
@@ -19,86 +18,6 @@ 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_;
-};
-
-} // namespace
-
-
// A helper class to simplify the process of reducing a single binop node with a
// JSOperator. This class manages the rewriting of context, control, and effect
// dependencies during lowering of a binop and contains numerous helper
@@ -1432,505 +1351,6 @@ Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
}
-namespace {
-
-// Maximum instance size for which allocations will be inlined.
-const int kMaxInlineInstanceSize = 64 * kPointerSize;
-
-
-// Checks whether allocation using the given constructor can be inlined.
-bool IsAllocationInlineable(Handle<JSFunction> constructor) {
- // TODO(bmeurer): Further relax restrictions on inlining, i.e.
- // instance type and maybe instance size (inobject properties
- // are limited anyways by the runtime).
- return constructor->has_initial_map() &&
- constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
- constructor->initial_map()->instance_size() < kMaxInlineInstanceSize;
-}
-
-} // namespace
-
-
-Reduction JSTypedLowering::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);
- Node* const effect = NodeProperties::GetEffectInput(node);
- // TODO(turbofan): Add support for NewTarget passed to JSCreate.
- if (target != new_target) return NoChange();
- // Extract constructor function.
- if (target_type->IsConstant() &&
- target_type->AsConstant()->Value()->IsJSFunction()) {
- Handle<JSFunction> constructor =
- Handle<JSFunction>::cast(target_type->AsConstant()->Value());
- DCHECK(constructor->IsConstructor());
- // Force completion of inobject slack tracking before
- // generating code to finalize the instance size.
- constructor->CompleteInobjectSlackTrackingIfActive();
-
- // TODO(bmeurer): We fall back to the runtime in case we cannot inline
- // the allocation here, which is sort of expensive. We should think about
- // a soft fallback to some NewObjectCodeStub.
- if (IsAllocationInlineable(constructor)) {
- // Compute instance size from initial map of {constructor}.
- Handle<Map> initial_map(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 {constructor} changes.
- dependencies()->AssumeInitialMapCantChange(initial_map);
-
- // Emit code to allocate the JSObject instance for the {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();
-}
-
-
-namespace {
-
-// Retrieves the frame state holding actual argument values.
-Node* GetArgumentsFrameState(Node* frame_state) {
- Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
- FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state);
- return outer_state_info.type() == FrameStateType::kArgumentsAdaptor
- ? outer_state
- : frame_state;
-}
-
-} // namespace
-
-
-Reduction JSTypedLowering::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) {
- if (type != CreateArgumentsType::kRestParameter) {
- // TODO(bmeurer): Cleanup this mess at some point.
- Isolate* isolate = jsgraph()->isolate();
- int parameter_count = state_info.parameter_count() - 1;
- int parameter_offset = parameter_count * kPointerSize;
- int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset;
- Node* parameter_pointer = graph()->NewNode(
- machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()),
- jsgraph()->IntPtrConstant(offset));
- Handle<SharedFunctionInfo> shared;
- if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
- bool unmapped = type == CreateArgumentsType::kUnmappedArguments;
- Callable callable = CodeFactory::ArgumentsAccess(
- isolate, unmapped, shared->has_duplicate_parameters());
- 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);
- node->InsertInput(graph()->zone(), 2,
- jsgraph()->Constant(parameter_count));
- node->InsertInput(graph()->zone(), 3, parameter_pointer);
- NodeProperties::ChangeOp(node, new_op);
- return Changed(node);
- } else {
- 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);
- }
- } 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(Heap::kSloppyArgumentsObjectSize == 5 * kPointerSize);
- a.Allocate(Heap::kSloppyArgumentsObjectSize);
- 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(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize);
- a.Allocate(Heap::kStrictArgumentsObjectSize);
- 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 JSTypedLowering::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));
- if (flags() & kDeoptimizationEnabled) {
- 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 JSTypedLowering::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_cache_.kElementLoopUnrollType)) {
- int capacity = static_cast<int>(length_type->Max());
- return ReduceNewArray(node, length, capacity, site);
- }
- }
- }
-
- return NoChange();
-}
-
-
-Reduction JSTypedLowering::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 JSTypedLowering::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 JSTypedLowering::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 JSTypedLowering::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 JSTypedLowering::ReduceJSCreateBlockContext(Node* node) {
- DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode());
- Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
- int 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();
-}
-
-
Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
CallConstructParameters const& p = CallConstructParametersOf(node->op());
@@ -2313,22 +1733,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSStoreContext(node);
case IrOpcode::kJSConvertReceiver:
return ReduceJSConvertReceiver(node);
- 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::kJSCreateFunctionContext:
- return ReduceJSCreateFunctionContext(node);
- case IrOpcode::kJSCreateWithContext:
- return ReduceJSCreateWithContext(node);
- case IrOpcode::kJSCreateCatchContext:
- return ReduceJSCreateCatchContext(node);
- case IrOpcode::kJSCreateBlockContext:
- return ReduceJSCreateBlockContext(node);
case IrOpcode::kJSCallConstruct:
return ReduceJSCallConstruct(node);
case IrOpcode::kJSCallFunction:
@@ -2355,139 +1759,6 @@ Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
}
-// Helper that allocates a FixedArray holding argument values recorded in the
-// given {frame_state}. Serves as backing store for JSCreateArguments nodes.
-Node* JSTypedLowering::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* JSTypedLowering::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* JSTypedLowering::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* JSTypedLowering::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();
-}
-
-
Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698