Chromium Code Reviews| Index: src/compiler/js-typed-lowering.cc |
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc |
| index 623fa51b8eb66d8d9d512557e6d1f55eaea41953..5702c773b301161cd18761345122dd95edd30704 100644 |
| --- a/src/compiler/js-typed-lowering.cc |
| +++ b/src/compiler/js-typed-lowering.cc |
| @@ -36,17 +36,15 @@ JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph, Zone* zone) |
| // allocated object and also provides helpers for commonly allocated objects. |
| class AllocationBuilder final { |
| public: |
| - AllocationBuilder(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified, |
| - Node* effect, Node* control) |
| + AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control) |
| : jsgraph_(jsgraph), |
| - simplified_(simplified), |
| allocation_(nullptr), |
| effect_(effect), |
| control_(control) {} |
| // Primitive allocation of static size. |
| void Allocate(int size) { |
| - effect_ = graph()->NewNode(jsgraph()->common()->BeginRegion(), effect_); |
| + effect_ = graph()->NewNode(common()->BeginRegion(), effect_); |
| allocation_ = graph()->NewNode( |
| simplified()->Allocate(), jsgraph()->Constant(size), effect_, control_); |
| effect_ = allocation_; |
| @@ -76,17 +74,21 @@ class AllocationBuilder final { |
| node->ReplaceInput(0, allocation_); |
| node->ReplaceInput(1, effect_); |
| node->TrimInputCount(2); |
| - NodeProperties::ChangeOp(node, jsgraph()->common()->FinishRegion()); |
| + NodeProperties::ChangeOp(node, common()->FinishRegion()); |
| + } |
| + |
| + Node* Finish() { |
|
Jarin
2015/10/23 14:09:22
I would prefer not to overload Finish. Perhaps ren
Michael Starzinger
2015/10/23 15:09:40
Done. As discussed offline, I went with "FinishAnd
|
| + return graph()->NewNode(common()->FinishRegion(), allocation_, effect_); |
| } |
| protected: |
| JSGraph* jsgraph() { return jsgraph_; } |
| Graph* graph() { return jsgraph_->graph(); } |
| - SimplifiedOperatorBuilder* simplified() { return simplified_; } |
| + CommonOperatorBuilder* common() { return jsgraph_->common(); } |
| + SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); } |
| private: |
| JSGraph* const jsgraph_; |
| - SimplifiedOperatorBuilder* simplified_; |
| Node* allocation_; |
| Node* effect_; |
| Node* control_; |
| @@ -1159,6 +1161,50 @@ Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) { |
| return Changed(node); |
| } |
| + // Use inline allocation for all unmapped arguments objects within inlined |
| + // (i.e. non-outermost) frames, independent of the object size. |
| + if (p.type() == CreateArgumentsParameters::kUnmappedArguments && |
| + outer_state->opcode() == IrOpcode::kFrameState) { |
| + Node* const effect = NodeProperties::GetEffectInput(node); |
| + Node* const control = NodeProperties::GetControlInput(node); |
| + Node* const context = NodeProperties::GetContextInput(node); |
| + FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); |
| + // 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 = |
| + outer_state_info.type() == FrameStateType::kArgumentsAdaptor |
| + ? outer_state |
| + : 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); |
| + // Load the arguments object map from the current native context. |
| + Node* const load_global_object = graph()->NewNode( |
| + simplified()->LoadField( |
| + AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| + context, effect, control); |
| + Node* const load_native_context = graph()->NewNode( |
| + simplified()->LoadField(AccessBuilder::ForGlobalObjectNativeContext()), |
| + load_global_object, effect, control); |
| + Node* const load_arguments_map = 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); |
| + Handle<Object> properties = factory()->empty_fixed_array(); |
| + 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.Finish(node); |
| + return Changed(node); |
| + } |
| + |
| return NoChange(); |
| } |
| @@ -1270,7 +1316,7 @@ Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) { |
| simplified()->LoadField( |
| AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| context, effect, control); |
| - AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| + 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()); |
| @@ -1325,7 +1371,7 @@ Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { |
| simplified()->LoadField( |
| AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| context, effect, control); |
| - AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| + 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); |
| @@ -1363,7 +1409,7 @@ Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
| simplified()->LoadField( |
| AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)), |
| context, effect, control); |
| - AllocationBuilder a(jsgraph(), simplified(), effect, control); |
| + 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); |
| @@ -1813,6 +1859,23 @@ 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 length = state_info.parameter_count() - 1; // Minus receiver argument. |
| + if (length == 0) return jsgraph()->Constant(factory()->empty_fixed_array()); |
| + Node* const params = frame_state->InputAt(kFrameStateParametersInput); |
| + AllocationBuilder a(jsgraph(), effect, control); |
| + a.AllocateArray(length, factory()->fixed_array_map()); |
| + for (int i = 0; i < length; ++i) { |
|
Jarin
2015/10/23 14:09:22
Could you use StateValuesIterator for this?
Michael Starzinger
2015/10/23 15:09:39
Done.
|
| + a.Store(AccessBuilder::ForFixedArraySlot(i), params->InputAt(i + 1)); |
| + } |
| + return a.Finish(); |
| +} |
| + |
| + |
| Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |