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..13efd4cf1a0225ff17302b33f6fe26d06f214afd 100644 |
--- a/src/compiler/js-typed-lowering.cc |
+++ b/src/compiler/js-typed-lowering.cc |
@@ -10,6 +10,7 @@ |
#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/types.h" |
namespace v8 { |
@@ -36,17 +37,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_; |
@@ -71,22 +70,26 @@ class AllocationBuilder final { |
Store(access, jsgraph()->Constant(value)); |
} |
- void Finish(Node* node) { |
+ void FinishAndChange(Node* node) { |
NodeProperties::SetType(allocation_, NodeProperties::GetType(node)); |
node->ReplaceInput(0, allocation_); |
node->ReplaceInput(1, effect_); |
node->TrimInputCount(2); |
- NodeProperties::ChangeOp(node, jsgraph()->common()->FinishRegion()); |
+ NodeProperties::ChangeOp(node, common()->FinishRegion()); |
+ } |
+ |
+ Node* Finish() { |
+ 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 +1162,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.FinishAndChange(node); |
+ return Changed(node); |
+ } |
+ |
return NoChange(); |
} |
@@ -1270,7 +1317,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()); |
@@ -1282,7 +1329,7 @@ Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) { |
a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); |
} |
RelaxControls(node); |
- a.Finish(node); |
+ a.FinishAndChange(node); |
return Changed(node); |
} |
@@ -1325,7 +1372,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); |
@@ -1333,7 +1380,7 @@ Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { |
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), input); |
a.Store(AccessBuilder::ForContextSlot(Context::GLOBAL_OBJECT_INDEX), load); |
RelaxControls(node); |
- a.Finish(node); |
+ a.FinishAndChange(node); |
return Changed(node); |
} |
@@ -1363,7 +1410,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); |
@@ -1374,7 +1421,7 @@ Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { |
a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->TheHoleConstant()); |
} |
RelaxControls(node); |
- a.Finish(node); |
+ a.FinishAndChange(node); |
return Changed(node); |
} |
@@ -1813,6 +1860,25 @@ 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 parameters = frame_state->InputAt(kFrameStateParametersInput); |
+ StateValuesAccess parameters_access(parameters); |
+ auto paratemers_it = ++parameters_access.begin(); |
+ AllocationBuilder a(jsgraph(), effect, control); |
+ a.AllocateArray(length, factory()->fixed_array_map()); |
+ for (int i = 0; i < length; ++i, ++paratemers_it) { |
+ a.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node); |
+ } |
+ return a.Finish(); |
+} |
+ |
+ |
Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |