[turbofan] Pass closure as node to FrameState.
First step towards support for inlining based on SharedFunctionInfo instead of JSFunction. R=jarin@chromium.org Review URL: https://codereview.chromium.org/1134713004 Cr-Commit-Position: refs/heads/master@{#28419}
This commit is contained in:
parent
3c1487db60
commit
1643671f1b
@ -814,6 +814,7 @@ Node* AstGraphBuilder::Environment::Checkpoint(
|
||||
|
||||
Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
|
||||
stack_node_, builder()->current_context(),
|
||||
builder()->GetFunctionClosure(),
|
||||
builder()->jsgraph()->UndefinedConstant());
|
||||
if (FLAG_analyze_environment_liveness) {
|
||||
liveness_block()->Checkpoint(result);
|
||||
|
@ -426,17 +426,20 @@ FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor(
|
||||
return code()->GetFrameStateDescriptor(state_id);
|
||||
}
|
||||
|
||||
struct OperandAndType {
|
||||
OperandAndType(InstructionOperand* operand, MachineType type)
|
||||
: operand_(operand), type_(type) {}
|
||||
|
||||
InstructionOperand* operand_;
|
||||
MachineType type_;
|
||||
namespace {
|
||||
|
||||
struct OperandAndType {
|
||||
InstructionOperand* const operand;
|
||||
MachineType const type;
|
||||
};
|
||||
|
||||
static OperandAndType TypedOperandForFrameState(
|
||||
FrameStateDescriptor* descriptor, Instruction* instr,
|
||||
size_t frame_state_offset, size_t index, OutputFrameStateCombine combine) {
|
||||
|
||||
OperandAndType TypedOperandForFrameState(FrameStateDescriptor* descriptor,
|
||||
Instruction* instr,
|
||||
size_t frame_state_offset,
|
||||
size_t index,
|
||||
OutputFrameStateCombine combine) {
|
||||
DCHECK(index < descriptor->GetSize(combine));
|
||||
switch (combine.kind()) {
|
||||
case OutputFrameStateCombine::kPushOutput: {
|
||||
@ -445,8 +448,7 @@ static OperandAndType TypedOperandForFrameState(
|
||||
descriptor->GetSize(OutputFrameStateCombine::Ignore());
|
||||
// If the index is past the existing stack items, return the output.
|
||||
if (index >= size_without_output) {
|
||||
return OperandAndType(instr->OutputAt(index - size_without_output),
|
||||
kMachAnyTagged);
|
||||
return {instr->OutputAt(index - size_without_output), kMachAnyTagged};
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -455,31 +457,35 @@ static OperandAndType TypedOperandForFrameState(
|
||||
descriptor->GetSize(combine) - 1 - combine.GetOffsetToPokeAt();
|
||||
if (index >= index_from_top &&
|
||||
index < index_from_top + instr->OutputCount()) {
|
||||
return OperandAndType(instr->OutputAt(index - index_from_top),
|
||||
kMachAnyTagged);
|
||||
return {instr->OutputAt(index - index_from_top), kMachAnyTagged};
|
||||
}
|
||||
break;
|
||||
}
|
||||
return OperandAndType(instr->InputAt(frame_state_offset + index),
|
||||
descriptor->GetType(index));
|
||||
return {instr->InputAt(frame_state_offset + index),
|
||||
descriptor->GetType(index)};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void CodeGenerator::BuildTranslationForFrameStateDescriptor(
|
||||
FrameStateDescriptor* descriptor, Instruction* instr,
|
||||
Translation* translation, size_t frame_state_offset,
|
||||
OutputFrameStateCombine state_combine) {
|
||||
// Outer-most state must be added to translation first.
|
||||
if (descriptor->outer_state() != NULL) {
|
||||
if (descriptor->outer_state() != nullptr) {
|
||||
BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr,
|
||||
translation, frame_state_offset,
|
||||
OutputFrameStateCombine::Ignore());
|
||||
}
|
||||
frame_state_offset += descriptor->outer_state()->GetTotalSize();
|
||||
|
||||
// TODO(bmeurer): Fix this special case here.
|
||||
int id = Translation::kSelfLiteralId;
|
||||
if (!descriptor->jsfunction().is_null()) {
|
||||
id = DefineDeoptimizationLiteral(
|
||||
Handle<Object>::cast(descriptor->jsfunction().ToHandleChecked()));
|
||||
if (descriptor->outer_state() != nullptr) {
|
||||
InstructionOperandConverter converter(this, instr);
|
||||
Handle<HeapObject> function(converter.InputHeapObject(frame_state_offset));
|
||||
id = DefineDeoptimizationLiteral(function);
|
||||
}
|
||||
|
||||
switch (descriptor->type()) {
|
||||
@ -487,7 +493,7 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
|
||||
translation->BeginJSFrame(
|
||||
descriptor->bailout_id(), id,
|
||||
static_cast<unsigned int>(descriptor->GetSize(state_combine) -
|
||||
descriptor->parameters_count()));
|
||||
(1 + descriptor->parameters_count())));
|
||||
break;
|
||||
case ARGUMENTS_ADAPTOR:
|
||||
translation->BeginArgumentsAdaptorFrame(
|
||||
@ -495,11 +501,10 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor(
|
||||
break;
|
||||
}
|
||||
|
||||
frame_state_offset += descriptor->outer_state()->GetTotalSize();
|
||||
for (size_t i = 0; i < descriptor->GetSize(state_combine); i++) {
|
||||
for (size_t i = 1; i < descriptor->GetSize(state_combine); i++) {
|
||||
OperandAndType op = TypedOperandForFrameState(
|
||||
descriptor, instr, frame_state_offset, i, state_combine);
|
||||
AddTranslationForOperand(translation, instr, op.operand_, op.type_);
|
||||
AddTranslationForOperand(translation, instr, op.operand, op.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,12 +609,12 @@ const Operator* CommonOperatorBuilder::TypedStateValues(
|
||||
|
||||
const Operator* CommonOperatorBuilder::FrameState(
|
||||
FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
|
||||
return new (zone()) Operator1<FrameStateCallInfo>( // --
|
||||
IrOpcode::kFrameState, Operator::kPure, // opcode
|
||||
"FrameState", // name
|
||||
4, 0, 0, 1, 0, 0, // counts
|
||||
FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
|
||||
OutputFrameStateCombine state_combine) {
|
||||
return new (zone()) Operator1<FrameStateCallInfo>( // --
|
||||
IrOpcode::kFrameState, Operator::kPure, // opcode
|
||||
"FrameState", // name
|
||||
5, 0, 0, 1, 0, 0, // counts
|
||||
FrameStateCallInfo(type, bailout_id, state_combine)); // parameter
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,10 +128,8 @@ class CommonOperatorBuilder final : public ZoneObject {
|
||||
const Operator* Finish(int arguments);
|
||||
const Operator* StateValues(int arguments);
|
||||
const Operator* TypedStateValues(const ZoneVector<MachineType>* types);
|
||||
const Operator* FrameState(
|
||||
FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine,
|
||||
MaybeHandle<JSFunction> jsfunction = MaybeHandle<JSFunction>());
|
||||
const Operator* FrameState(FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine);
|
||||
const Operator* Call(const CallDescriptor* descriptor);
|
||||
const Operator* TailCall(const CallDescriptor* descriptor);
|
||||
const Operator* Projection(size_t index);
|
||||
|
@ -48,6 +48,7 @@ std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) {
|
||||
return os << info.type() << ", " << info.bailout_id() << ", "
|
||||
<< info.state_combine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -5,8 +5,6 @@
|
||||
#ifndef V8_COMPILER_FRAME_STATES_H_
|
||||
#define V8_COMPILER_FRAME_STATES_H_
|
||||
|
||||
#include "src/handles-inl.h" // TODO(everyone): Fix our inl.h crap
|
||||
#include "src/objects-inl.h" // TODO(everyone): Fix our inl.h crap
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -80,25 +78,20 @@ enum FrameStateType {
|
||||
|
||||
class FrameStateCallInfo final {
|
||||
public:
|
||||
FrameStateCallInfo(
|
||||
FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine,
|
||||
MaybeHandle<JSFunction> jsfunction = MaybeHandle<JSFunction>())
|
||||
FrameStateCallInfo(FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine)
|
||||
: type_(type),
|
||||
bailout_id_(bailout_id),
|
||||
frame_state_combine_(state_combine),
|
||||
jsfunction_(jsfunction) {}
|
||||
frame_state_combine_(state_combine) {}
|
||||
|
||||
FrameStateType type() const { return type_; }
|
||||
BailoutId bailout_id() const { return bailout_id_; }
|
||||
OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
|
||||
MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
|
||||
|
||||
private:
|
||||
FrameStateType type_;
|
||||
BailoutId bailout_id_;
|
||||
OutputFrameStateCombine frame_state_combine_;
|
||||
MaybeHandle<JSFunction> jsfunction_;
|
||||
FrameStateType const type_;
|
||||
BailoutId const bailout_id_;
|
||||
OutputFrameStateCombine const frame_state_combine_;
|
||||
};
|
||||
|
||||
bool operator==(FrameStateCallInfo const&, FrameStateCallInfo const&);
|
||||
|
@ -1028,7 +1028,7 @@ void InstructionSelector::VisitThrow(Node* value) {
|
||||
FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
|
||||
Node* state) {
|
||||
DCHECK(state->opcode() == IrOpcode::kFrameState);
|
||||
DCHECK_EQ(5, state->InputCount());
|
||||
DCHECK_EQ(6, state->InputCount());
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(0)->opcode());
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(1)->opcode());
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(2)->opcode());
|
||||
@ -1040,13 +1040,14 @@ FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
|
||||
int stack = static_cast<int>(StateValuesAccess(state->InputAt(2)).size());
|
||||
|
||||
FrameStateDescriptor* outer_state = NULL;
|
||||
Node* outer_node = state->InputAt(4);
|
||||
Node* outer_node = state->InputAt(5);
|
||||
if (outer_node->opcode() == IrOpcode::kFrameState) {
|
||||
outer_state = GetFrameStateDescriptor(outer_node);
|
||||
}
|
||||
|
||||
return new (instruction_zone()) FrameStateDescriptor(
|
||||
instruction_zone(), state_info, parameters, locals, stack, outer_state);
|
||||
instruction_zone(), state_info.type(), state_info.bailout_id(),
|
||||
state_info.state_combine(), parameters, locals, stack, outer_state);
|
||||
}
|
||||
|
||||
|
||||
@ -1068,14 +1069,15 @@ void InstructionSelector::AddFrameStateInputs(
|
||||
FrameStateDescriptor* descriptor) {
|
||||
DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
|
||||
|
||||
if (descriptor->outer_state() != NULL) {
|
||||
AddFrameStateInputs(state->InputAt(4), inputs, descriptor->outer_state());
|
||||
if (descriptor->outer_state()) {
|
||||
AddFrameStateInputs(state->InputAt(5), inputs, descriptor->outer_state());
|
||||
}
|
||||
|
||||
Node* parameters = state->InputAt(0);
|
||||
Node* locals = state->InputAt(1);
|
||||
Node* stack = state->InputAt(2);
|
||||
Node* context = state->InputAt(3);
|
||||
Node* function = state->InputAt(4);
|
||||
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, parameters->op()->opcode());
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, locals->op()->opcode());
|
||||
@ -1091,6 +1093,8 @@ void InstructionSelector::AddFrameStateInputs(
|
||||
|
||||
OperandGenerator g(this);
|
||||
size_t value_index = 0;
|
||||
inputs->push_back(SlotOrImmediate(&g, function));
|
||||
descriptor->SetType(value_index++, kMachAnyTagged);
|
||||
for (StateValuesAccess::TypedNode input_node :
|
||||
StateValuesAccess(parameters)) {
|
||||
inputs->push_back(SlotOrImmediate(&g, input_node.node));
|
||||
|
@ -662,22 +662,23 @@ void InstructionSequence::SetSourcePosition(const Instruction* instr,
|
||||
|
||||
|
||||
FrameStateDescriptor::FrameStateDescriptor(
|
||||
Zone* zone, const FrameStateCallInfo& state_info, size_t parameters_count,
|
||||
Zone* zone, FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine, size_t parameters_count,
|
||||
size_t locals_count, size_t stack_count, FrameStateDescriptor* outer_state)
|
||||
: type_(state_info.type()),
|
||||
bailout_id_(state_info.bailout_id()),
|
||||
frame_state_combine_(state_info.state_combine()),
|
||||
: type_(type),
|
||||
bailout_id_(bailout_id),
|
||||
frame_state_combine_(state_combine),
|
||||
parameters_count_(parameters_count),
|
||||
locals_count_(locals_count),
|
||||
stack_count_(stack_count),
|
||||
types_(zone),
|
||||
outer_state_(outer_state),
|
||||
jsfunction_(state_info.jsfunction()) {
|
||||
outer_state_(outer_state) {
|
||||
types_.resize(GetSize(), kMachNone);
|
||||
}
|
||||
|
||||
|
||||
size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const {
|
||||
size_t size = parameters_count() + locals_count() + stack_count() +
|
||||
size_t size = 1 + parameters_count() + locals_count() + stack_count() +
|
||||
(HasContext() ? 1 : 0);
|
||||
switch (combine.kind()) {
|
||||
case OutputFrameStateCombine::kPushOutput:
|
||||
|
@ -862,10 +862,11 @@ class Constant final {
|
||||
|
||||
class FrameStateDescriptor : public ZoneObject {
|
||||
public:
|
||||
FrameStateDescriptor(Zone* zone, const FrameStateCallInfo& state_info,
|
||||
FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine,
|
||||
size_t parameters_count, size_t locals_count,
|
||||
size_t stack_count,
|
||||
FrameStateDescriptor* outer_state = NULL);
|
||||
FrameStateDescriptor* outer_state = nullptr);
|
||||
|
||||
FrameStateType type() const { return type_; }
|
||||
BailoutId bailout_id() const { return bailout_id_; }
|
||||
@ -874,7 +875,6 @@ class FrameStateDescriptor : public ZoneObject {
|
||||
size_t locals_count() const { return locals_count_; }
|
||||
size_t stack_count() const { return stack_count_; }
|
||||
FrameStateDescriptor* outer_state() const { return outer_state_; }
|
||||
MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
|
||||
bool HasContext() const { return type_ == JS_FRAME; }
|
||||
|
||||
size_t GetSize(OutputFrameStateCombine combine =
|
||||
@ -895,7 +895,6 @@ class FrameStateDescriptor : public ZoneObject {
|
||||
size_t stack_count_;
|
||||
ZoneVector<MachineType> types_;
|
||||
FrameStateDescriptor* outer_state_;
|
||||
MaybeHandle<JSFunction> jsfunction_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Constant& constant);
|
||||
|
@ -191,7 +191,7 @@ Node* JSGraph::EmptyFrameState() {
|
||||
common()->FrameState(JS_FRAME, BailoutId::None(),
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
state_values, state_values, state_values, NoContextConstant(),
|
||||
UndefinedConstant());
|
||||
UndefinedConstant(), UndefinedConstant());
|
||||
cached_nodes_[kEmptyFrameState] = empty_frame_state;
|
||||
}
|
||||
return empty_frame_state;
|
||||
|
@ -264,22 +264,11 @@ Reduction JSInliner::InlineCall(Node* call, Inlinee& inlinee) {
|
||||
}
|
||||
|
||||
|
||||
void JSInliner::AddClosureToFrameState(Node* frame_state,
|
||||
Handle<JSFunction> jsfunction) {
|
||||
FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
|
||||
const Operator* op = jsgraph_->common()->FrameState(
|
||||
FrameStateType::JS_FRAME, call_info.bailout_id(),
|
||||
call_info.state_combine(), jsfunction);
|
||||
frame_state->set_op(op);
|
||||
}
|
||||
|
||||
|
||||
Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
|
||||
Handle<JSFunction> jsfunction,
|
||||
Zone* temp_zone) {
|
||||
const Operator* op = jsgraph_->common()->FrameState(
|
||||
FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1),
|
||||
OutputFrameStateCombine::Ignore(), jsfunction);
|
||||
OutputFrameStateCombine::Ignore());
|
||||
const Operator* op0 = jsgraph_->common()->StateValues(0);
|
||||
Node* node0 = jsgraph_->graph()->NewNode(op0);
|
||||
NodeVector params(temp_zone);
|
||||
@ -293,7 +282,7 @@ Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
|
||||
op_param, static_cast<int>(params.size()), ¶ms.front());
|
||||
return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
|
||||
jsgraph_->UndefinedConstant(),
|
||||
call->frame_state());
|
||||
call->jsfunction(), call->frame_state());
|
||||
}
|
||||
|
||||
|
||||
@ -359,14 +348,12 @@ Reduction JSInliner::Reduce(Node* node) {
|
||||
call.formal_arguments() < inlinee.formal_parameters()) {
|
||||
return NoChange();
|
||||
}
|
||||
outer_frame_state =
|
||||
CreateArgumentsAdaptorFrameState(&call, function, info.zone());
|
||||
outer_frame_state = CreateArgumentsAdaptorFrameState(&call, info.zone());
|
||||
}
|
||||
|
||||
for (Node* node : visitor.copies()) {
|
||||
if (node && node->opcode() == IrOpcode::kFrameState) {
|
||||
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
|
||||
AddClosureToFrameState(node, function);
|
||||
NodeProperties::ReplaceFrameStateInput(node, 0, outer_frame_state);
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,7 @@ class JSInliner final : public AdvancedReducer {
|
||||
JSGraph* jsgraph_;
|
||||
|
||||
Node* CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
|
||||
Handle<JSFunction> jsfunction,
|
||||
Zone* temp_zone);
|
||||
void AddClosureToFrameState(Node* frame_state, Handle<JSFunction> jsfunction);
|
||||
|
||||
Reduction InlineCall(Node* call, Inlinee& inlinee);
|
||||
};
|
||||
|
@ -289,7 +289,8 @@ class JSBinopReduction final {
|
||||
|
||||
return graph()->NewNode(op, frame_state->InputAt(0),
|
||||
frame_state->InputAt(1), frame_state->InputAt(2),
|
||||
frame_state->InputAt(3), frame_state->InputAt(4));
|
||||
frame_state->InputAt(3), frame_state->InputAt(4),
|
||||
frame_state->InputAt(5));
|
||||
}
|
||||
|
||||
Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) {
|
||||
@ -326,7 +327,8 @@ class JSBinopReduction final {
|
||||
|
||||
return graph()->NewNode(op, frame_state->InputAt(0),
|
||||
frame_state->InputAt(1), new_stack,
|
||||
frame_state->InputAt(3), frame_state->InputAt(4));
|
||||
frame_state->InputAt(3), frame_state->InputAt(4),
|
||||
frame_state->InputAt(5));
|
||||
}
|
||||
|
||||
Node* ConvertPlainPrimitiveToNumber(Node* node) {
|
||||
|
@ -421,6 +421,10 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
}
|
||||
case IrOpcode::kFrameState:
|
||||
// TODO(jarin): what are the constraints on these?
|
||||
CHECK_EQ(5, value_count);
|
||||
CHECK_EQ(0, control_count);
|
||||
CHECK_EQ(0, effect_count);
|
||||
CHECK_EQ(6, input_count);
|
||||
break;
|
||||
case IrOpcode::kStateValues:
|
||||
case IrOpcode::kTypedStateValues:
|
||||
|
@ -129,10 +129,11 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
|
||||
Node* locals = m.NewNode(common.TypedStateValues(&empty_types));
|
||||
Node* stack = m.NewNode(common.TypedStateValues(&empty_types));
|
||||
|
||||
Node* state_node = m.NewNode(
|
||||
common.FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, caller_context_node, m.UndefinedConstant());
|
||||
Node* state_node =
|
||||
m.NewNode(common.FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, caller_context_node,
|
||||
deopt_fun_node, m.UndefinedConstant());
|
||||
|
||||
Handle<Context> context(deopt_function->context(), CcTest::i_isolate());
|
||||
Unique<Context> context_constant =
|
||||
@ -245,10 +246,11 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
|
||||
Node* locals = m.NewNode(common.TypedStateValues(&empty_types));
|
||||
Node* stack = m.NewNode(common.TypedStateValues(&empty_types));
|
||||
|
||||
Node* state_node = m.NewNode(
|
||||
common.FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, context_node, m.UndefinedConstant());
|
||||
Node* state_node =
|
||||
m.NewNode(common.FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, context_node, this_fun_node,
|
||||
m.UndefinedConstant());
|
||||
|
||||
m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, context_node,
|
||||
state_node);
|
||||
|
@ -362,10 +362,11 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
|
||||
Node* stack = m.NewNode(m.common()->TypedStateValues(&empty_types));
|
||||
Node* context_dummy = m.Int32Constant(0);
|
||||
|
||||
Node* state_node = m.NewNode(
|
||||
m.common()->FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Push()),
|
||||
parameters, locals, stack, context_dummy, m.UndefinedConstant());
|
||||
Node* state_node =
|
||||
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id,
|
||||
OutputFrameStateCombine::Push()),
|
||||
parameters, locals, stack, context_dummy, function_node,
|
||||
m.UndefinedConstant());
|
||||
Node* call = m.CallJS0(function_node, receiver, context, state_node);
|
||||
m.Return(call);
|
||||
|
||||
@ -410,10 +411,11 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
|
||||
m.UndefinedConstant());
|
||||
|
||||
Node* context_sentinel = m.Int32Constant(0);
|
||||
Node* frame_state_before = m.NewNode(
|
||||
m.common()->FrameState(JS_FRAME, bailout_id_before,
|
||||
OutputFrameStateCombine::Push()),
|
||||
parameters, locals, stack, context_sentinel, m.UndefinedConstant());
|
||||
Node* frame_state_before =
|
||||
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before,
|
||||
OutputFrameStateCombine::Push()),
|
||||
parameters, locals, stack, context_sentinel, function_node,
|
||||
m.UndefinedConstant());
|
||||
|
||||
// Build the call.
|
||||
Node* call = m.CallFunctionStub0(function_node, receiver, context,
|
||||
@ -437,7 +439,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
|
||||
size_t num_operands =
|
||||
1 + // Code object.
|
||||
1 +
|
||||
4 + // Frame state deopt id + one input for each value in frame state.
|
||||
5 + // Frame state deopt id + one input for each value in frame state.
|
||||
1 + // Function.
|
||||
1; // Context.
|
||||
ASSERT_EQ(num_operands, call_instr->InputCount());
|
||||
@ -455,21 +457,23 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
|
||||
EXPECT_EQ(1u, desc_before->parameters_count());
|
||||
EXPECT_EQ(1u, desc_before->locals_count());
|
||||
EXPECT_EQ(1u, desc_before->stack_count());
|
||||
EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
|
||||
EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3))); // This should be a context.
|
||||
EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(3)));
|
||||
EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(4))); // This should be a context.
|
||||
// We inserted 0 here.
|
||||
EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(4)));
|
||||
EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(5))->IsUndefined());
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(0));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); // context is always
|
||||
EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(5)));
|
||||
EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined());
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); // function is always
|
||||
// tagged/any.
|
||||
EXPECT_EQ(kMachFloat64, desc_before->GetType(2));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(3));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(1));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); // context is always
|
||||
// tagged/any.
|
||||
EXPECT_EQ(kMachFloat64, desc_before->GetType(3));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(4));
|
||||
|
||||
// Function.
|
||||
EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(6)));
|
||||
EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7)));
|
||||
// Context.
|
||||
EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(7)));
|
||||
EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8)));
|
||||
|
||||
EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
|
||||
|
||||
@ -501,10 +505,10 @@ TARGET_TEST_F(InstructionSelectorTest,
|
||||
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64));
|
||||
Node* stack =
|
||||
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65));
|
||||
Node* frame_state_parent =
|
||||
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_parent,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, context, m.UndefinedConstant());
|
||||
Node* frame_state_parent = m.NewNode(
|
||||
m.common()->FrameState(JS_FRAME, bailout_id_parent,
|
||||
OutputFrameStateCombine::Ignore()),
|
||||
parameters, locals, stack, context, function_node, m.UndefinedConstant());
|
||||
|
||||
Node* context2 = m.Int32Constant(46);
|
||||
Node* parameters2 =
|
||||
@ -516,7 +520,8 @@ TARGET_TEST_F(InstructionSelectorTest,
|
||||
Node* frame_state_before =
|
||||
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before,
|
||||
OutputFrameStateCombine::Push()),
|
||||
parameters2, locals2, stack2, context2, frame_state_parent);
|
||||
parameters2, locals2, stack2, context2, function_node,
|
||||
frame_state_parent);
|
||||
|
||||
// Build the call.
|
||||
Node* call = m.CallFunctionStub0(function_node, receiver, context2,
|
||||
@ -540,8 +545,8 @@ TARGET_TEST_F(InstructionSelectorTest,
|
||||
size_t num_operands =
|
||||
1 + // Code object.
|
||||
1 + // Frame state deopt id
|
||||
5 + // One input for each value in frame state + context.
|
||||
4 + // One input for each value in the parent frame state + context.
|
||||
6 + // One input for each value in frame state + context.
|
||||
5 + // One input for each value in the parent frame state + context.
|
||||
1 + // Function.
|
||||
1; // Context.
|
||||
EXPECT_EQ(num_operands, call_instr->InputCount());
|
||||
@ -558,34 +563,36 @@ TARGET_TEST_F(InstructionSelectorTest,
|
||||
EXPECT_EQ(1u, desc_before_outer->locals_count());
|
||||
EXPECT_EQ(1u, desc_before_outer->stack_count());
|
||||
// Values from parent environment.
|
||||
EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(2)));
|
||||
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(0));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0));
|
||||
EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(3)));
|
||||
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(1));
|
||||
// Context:
|
||||
EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(3)));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(1));
|
||||
EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(4)));
|
||||
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(2));
|
||||
EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(5)));
|
||||
EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(4)));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(2));
|
||||
EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(5)));
|
||||
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(3));
|
||||
EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(6)));
|
||||
EXPECT_EQ(kMachInt32, desc_before_outer->GetType(4));
|
||||
// Values from the nested frame.
|
||||
EXPECT_EQ(1u, desc_before->parameters_count());
|
||||
EXPECT_EQ(1u, desc_before->locals_count());
|
||||
EXPECT_EQ(2u, desc_before->stack_count());
|
||||
EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(6)));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(0));
|
||||
EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(7)));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1));
|
||||
EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(8)));
|
||||
EXPECT_EQ(kMachFloat64, desc_before->GetType(2));
|
||||
EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(9)));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(3));
|
||||
EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(10)));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0));
|
||||
EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(8)));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(1));
|
||||
EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(9)));
|
||||
EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2));
|
||||
EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(10)));
|
||||
EXPECT_EQ(kMachFloat64, desc_before->GetType(3));
|
||||
EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(11)));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(4));
|
||||
EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(12)));
|
||||
EXPECT_EQ(kMachInt32, desc_before->GetType(5));
|
||||
|
||||
// Function.
|
||||
EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(11)));
|
||||
EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(13)));
|
||||
// Context.
|
||||
EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(12)));
|
||||
EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14)));
|
||||
// Continuation.
|
||||
|
||||
EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
|
||||
|
Loading…
Reference in New Issue
Block a user