[turbofan] Remember types for deoptimization during simplified lowering.

With this change, we remember the types of frame state inputs (in a new
operator, called TypedStateValues). Instead of inferring the value types
when building translations, we used the recorded types.

The original approach was not reliable because the passes after
simplified lowering can change node types, and this in turn confuses
the translation builder.

BUG=chromium:468727
LOG=n
R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1015423002

Cr-Commit-Position: refs/heads/master@{#27310}
This commit is contained in:
jarin 2015-03-19 07:00:28 -07:00 committed by Commit bot
parent 87af601824
commit b7dc9c580a
17 changed files with 172 additions and 208 deletions

View File

@ -509,8 +509,10 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
InstructionOperand* op,
MachineType type) {
if (op->IsStackSlot()) {
if (type == kMachBool || type == kMachInt32 || type == kMachInt8 ||
type == kMachInt16) {
// TODO(jarin) kMachBool and kRepBit should materialize true and false
// rather than creating an int value.
if (type == kMachBool || type == kRepBit || type == kMachInt32 ||
type == kMachInt8 || type == kMachInt16) {
translation->StoreInt32StackSlot(op->index());
} else if (type == kMachUint32 || type == kMachUint16 ||
type == kMachUint8) {
@ -525,8 +527,10 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
translation->StoreDoubleStackSlot(op->index());
} else if (op->IsRegister()) {
InstructionOperandConverter converter(this, instr);
if (type == kMachBool || type == kMachInt32 || type == kMachInt8 ||
type == kMachInt16) {
// TODO(jarin) kMachBool and kRepBit should materialize true and false
// rather than creating an int value.
if (type == kMachBool || type == kRepBit || type == kMachInt32 ||
type == kMachInt8 || type == kMachInt16) {
translation->StoreInt32Register(converter.ToRegister(op));
} else if (type == kMachUint32 || type == kMachUint16 ||
type == kMachUint8) {
@ -546,12 +550,14 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
Handle<Object> constant_object;
switch (constant.type()) {
case Constant::kInt32:
DCHECK(type == kMachInt32 || type == kMachUint32);
DCHECK(type == kMachInt32 || type == kMachUint32 || type == kRepBit);
constant_object =
isolate()->factory()->NewNumberFromInt(constant.ToInt32());
break;
case Constant::kFloat64:
DCHECK(type == kMachFloat64 || type == kMachAnyTagged);
DCHECK(type == kMachFloat64 || type == kMachAnyTagged ||
type == kRepTagged || type == (kTypeInt32 | kRepTagged) ||
type == (kTypeUint32 | kRepTagged));
constant_object = isolate()->factory()->NewNumber(constant.ToFloat64());
break;
case Constant::kHeapObject:

View File

@ -604,6 +604,15 @@ const Operator* CommonOperatorBuilder::StateValues(int arguments) {
}
const Operator* CommonOperatorBuilder::TypedStateValues(
const ZoneVector<MachineType>* types) {
return new (zone()) Operator1<const ZoneVector<MachineType>*>( // --
IrOpcode::kTypedStateValues, Operator::kPure, // opcode
"TypedStateValues", // name
static_cast<int>(types->size()), 0, 0, 1, 0, 0, types); // counts
}
const Operator* CommonOperatorBuilder::FrameState(
FrameStateType type, BailoutId bailout_id,
OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {

View File

@ -205,6 +205,7 @@ class CommonOperatorBuilder FINAL : public ZoneObject {
const Operator* ValueEffect(int arguments);
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,

View File

@ -574,147 +574,6 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
}
MachineType InstructionSelector::GetMachineType(Node* node) {
DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
switch (node->opcode()) {
case IrOpcode::kStart:
case IrOpcode::kLoop:
case IrOpcode::kEnd:
case IrOpcode::kBranch:
case IrOpcode::kIfTrue:
case IrOpcode::kIfFalse:
case IrOpcode::kSwitch:
case IrOpcode::kIfValue:
case IrOpcode::kIfDefault:
case IrOpcode::kEffectPhi:
case IrOpcode::kEffectSet:
case IrOpcode::kMerge:
// No code needed for these graph artifacts.
return kMachNone;
case IrOpcode::kFinish:
return kMachAnyTagged;
case IrOpcode::kParameter:
return linkage()->GetParameterType(OpParameter<int>(node));
case IrOpcode::kOsrValue:
return kMachAnyTagged;
case IrOpcode::kPhi:
return OpParameter<MachineType>(node);
case IrOpcode::kProjection:
// TODO(jarin) Really project from outputs.
return kMachAnyTagged;
case IrOpcode::kInt32Constant:
return kMachInt32;
case IrOpcode::kInt64Constant:
return kMachInt64;
case IrOpcode::kExternalConstant:
return kMachPtr;
case IrOpcode::kFloat64Constant:
return kMachFloat64;
case IrOpcode::kHeapConstant:
case IrOpcode::kNumberConstant:
return kMachAnyTagged;
case IrOpcode::kCall:
return kMachAnyTagged;
case IrOpcode::kFrameState:
case IrOpcode::kStateValues:
return kMachNone;
case IrOpcode::kLoad:
return OpParameter<LoadRepresentation>(node);
case IrOpcode::kStore:
return kMachNone;
case IrOpcode::kCheckedLoad:
return OpParameter<MachineType>(node);
case IrOpcode::kCheckedStore:
return kMachNone;
case IrOpcode::kWord32And:
case IrOpcode::kWord32Or:
case IrOpcode::kWord32Xor:
case IrOpcode::kWord32Shl:
case IrOpcode::kWord32Shr:
case IrOpcode::kWord32Sar:
case IrOpcode::kWord32Ror:
return kMachInt32;
case IrOpcode::kWord32Equal:
return kMachBool;
case IrOpcode::kWord64And:
case IrOpcode::kWord64Or:
case IrOpcode::kWord64Xor:
case IrOpcode::kWord64Shl:
case IrOpcode::kWord64Shr:
case IrOpcode::kWord64Sar:
case IrOpcode::kWord64Ror:
return kMachInt64;
case IrOpcode::kWord64Equal:
return kMachBool;
case IrOpcode::kInt32Add:
case IrOpcode::kInt32AddWithOverflow:
case IrOpcode::kInt32Sub:
case IrOpcode::kInt32SubWithOverflow:
case IrOpcode::kInt32Mul:
case IrOpcode::kInt32Div:
case IrOpcode::kInt32Mod:
return kMachInt32;
case IrOpcode::kInt32LessThan:
case IrOpcode::kInt32LessThanOrEqual:
case IrOpcode::kUint32LessThan:
case IrOpcode::kUint32LessThanOrEqual:
return kMachBool;
case IrOpcode::kInt64Add:
case IrOpcode::kInt64Sub:
case IrOpcode::kInt64Mul:
case IrOpcode::kInt64Div:
case IrOpcode::kInt64Mod:
return kMachInt64;
case IrOpcode::kInt64LessThan:
case IrOpcode::kInt64LessThanOrEqual:
return kMachBool;
case IrOpcode::kChangeFloat32ToFloat64:
case IrOpcode::kChangeInt32ToFloat64:
case IrOpcode::kChangeUint32ToFloat64:
return kMachFloat64;
case IrOpcode::kChangeFloat64ToInt32:
return kMachInt32;
case IrOpcode::kChangeFloat64ToUint32:
return kMachUint32;
case IrOpcode::kChangeInt32ToInt64:
return kMachInt64;
case IrOpcode::kChangeUint32ToUint64:
return kMachUint64;
case IrOpcode::kTruncateFloat64ToFloat32:
return kMachFloat32;
case IrOpcode::kTruncateFloat64ToInt32:
case IrOpcode::kTruncateInt64ToInt32:
return kMachInt32;
case IrOpcode::kFloat64Add:
case IrOpcode::kFloat64Sub:
case IrOpcode::kFloat64Mul:
case IrOpcode::kFloat64Div:
case IrOpcode::kFloat64Mod:
case IrOpcode::kFloat64Max:
case IrOpcode::kFloat64Min:
case IrOpcode::kFloat64Sqrt:
case IrOpcode::kFloat64RoundDown:
case IrOpcode::kFloat64RoundTruncate:
case IrOpcode::kFloat64RoundTiesAway:
return kMachFloat64;
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThanOrEqual:
return kMachBool;
case IrOpcode::kFloat64ExtractLowWord32:
case IrOpcode::kFloat64ExtractHighWord32:
return kMachInt32;
case IrOpcode::kFloat64InsertLowWord32:
case IrOpcode::kFloat64InsertHighWord32:
return kMachFloat64;
default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id());
}
return kMachNone;
}
void InstructionSelector::VisitNode(Node* node) {
DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
SourcePosition source_position = source_positions_->GetSourcePosition(node);
@ -1149,9 +1008,9 @@ FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
Node* state) {
DCHECK(state->opcode() == IrOpcode::kFrameState);
DCHECK_EQ(5, state->InputCount());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(0)->opcode());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(1)->opcode());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(2)->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(0)->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(1)->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, state->InputAt(2)->opcode());
FrameStateCallInfo state_info = OpParameter<FrameStateCallInfo>(state);
int parameters =
@ -1197,9 +1056,9 @@ void InstructionSelector::AddFrameStateInputs(
Node* stack = state->InputAt(2);
Node* context = state->InputAt(3);
DCHECK_EQ(IrOpcode::kStateValues, parameters->op()->opcode());
DCHECK_EQ(IrOpcode::kStateValues, locals->op()->opcode());
DCHECK_EQ(IrOpcode::kStateValues, stack->op()->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, parameters->op()->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, locals->op()->opcode());
DCHECK_EQ(IrOpcode::kTypedStateValues, stack->op()->opcode());
DCHECK_EQ(descriptor->parameters_count(),
StateValuesAccess(parameters).size());
@ -1211,21 +1070,22 @@ void InstructionSelector::AddFrameStateInputs(
OperandGenerator g(this);
size_t value_index = 0;
for (Node* input_node : StateValuesAccess(parameters)) {
inputs->push_back(UseOrImmediate(&g, input_node));
descriptor->SetType(value_index++, GetMachineType(input_node));
for (StateValuesAccess::TypedNode input_node :
StateValuesAccess(parameters)) {
inputs->push_back(UseOrImmediate(&g, input_node.node));
descriptor->SetType(value_index++, input_node.type);
}
if (descriptor->HasContext()) {
inputs->push_back(UseOrImmediate(&g, context));
descriptor->SetType(value_index++, kMachAnyTagged);
}
for (Node* input_node : StateValuesAccess(locals)) {
inputs->push_back(UseOrImmediate(&g, input_node));
descriptor->SetType(value_index++, GetMachineType(input_node));
for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) {
inputs->push_back(UseOrImmediate(&g, input_node.node));
descriptor->SetType(value_index++, input_node.type);
}
for (Node* input_node : StateValuesAccess(stack)) {
inputs->push_back(UseOrImmediate(&g, input_node));
descriptor->SetType(value_index++, GetMachineType(input_node));
for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) {
inputs->push_back(UseOrImmediate(&g, input_node.node));
descriptor->SetType(value_index++, input_node.type);
}
DCHECK(value_index == descriptor->GetSize());
}

View File

@ -173,7 +173,6 @@ class InstructionSelector FINAL {
FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
void AddFrameStateInputs(Node* state, InstructionOperandVector* inputs,
FrameStateDescriptor* descriptor);
MachineType GetMachineType(Node* node);
// ===========================================================================
// ============= Architecture-specific graph covering methods. ===============

View File

@ -142,12 +142,12 @@ void NonLiveFrameStateSlotReplacer::ClearNonLiveFrameStateSlots(
Node* NonLiveFrameStateSlotReplacer::ClearNonLiveStateValues(
Node* values, BitVector* liveness) {
DCHECK(inputs_buffer_.empty());
for (Node* node : StateValuesAccess(values)) {
for (StateValuesAccess::TypedNode node : StateValuesAccess(values)) {
// Index of the next variable is its furure index in the inputs buffer,
// i.e., the buffer's size.
int var = static_cast<int>(inputs_buffer_.size());
bool live = liveness->Contains(var) || permanently_live_.Contains(var);
inputs_buffer_.push_back(live ? node : replacement_node_);
inputs_buffer_.push_back(live ? node.node : replacement_node_);
}
Node* result = state_values_cache()->GetNodeForValues(
inputs_buffer_.empty() ? nullptr : &(inputs_buffer_.front()),

View File

@ -48,6 +48,7 @@
V(Finish) \
V(FrameState) \
V(StateValues) \
V(TypedStateValues) \
V(Call) \
V(Parameter) \
V(OsrValue) \

View File

@ -424,6 +424,25 @@ class RepresentationSelector {
}
}
void VisitStateValues(Node* node) {
if (phase_ == PROPAGATE) {
for (int i = 0; i < node->InputCount(); i++) {
Enqueue(node->InputAt(i), kTypeAny);
}
} else {
Zone* zone = jsgraph_->zone();
ZoneVector<MachineType>* types =
new (zone->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(node->InputCount(), zone);
for (int i = 0; i < node->InputCount(); i++) {
MachineTypeUnion input_type = GetInfo(node->InputAt(i))->output;
(*types)[i] = static_cast<MachineType>(input_type);
}
node->set_op(jsgraph_->common()->TypedStateValues(types));
}
SetOutput(node, kMachAnyTagged);
}
const Operator* Int32Op(Node* node) {
return changer_->Int32OperatorFor(node->opcode());
}
@ -1021,10 +1040,7 @@ class RepresentationSelector {
case IrOpcode::kLoadStackPointer:
return VisitLeaf(node, kMachPtr);
case IrOpcode::kStateValues:
for (int i = 0; i < node->InputCount(); i++) {
ProcessInput(node, i, kTypeAny);
}
SetOutput(node, kMachAnyTagged);
VisitStateValues(node);
break;
default:
VisitInputs(node);

View File

@ -173,6 +173,7 @@ Node* StateValuesCache::GetNodeForValues(Node** values, size_t count) {
#if DEBUG
for (size_t i = 0; i < count; i++) {
DCHECK_NE(values[i]->opcode(), IrOpcode::kStateValues);
DCHECK_NE(values[i]->opcode(), IrOpcode::kTypedStateValues);
}
#endif
if (count == 0) {
@ -190,7 +191,8 @@ Node* StateValuesCache::GetNodeForValues(Node** values, size_t count) {
Node* tree = BuildTree(&it, height);
// If the 'tree' is a single node, equip it with a StateValues wrapper.
if (tree->opcode() != IrOpcode::kStateValues) {
if (tree->opcode() != IrOpcode::kStateValues &&
tree->opcode() != IrOpcode::kTypedStateValues) {
tree = GetValuesNodeFromCache(&tree, 1);
}
@ -249,7 +251,8 @@ void StateValuesAccess::iterator::Advance() {
return;
}
Top()->index++;
} else if (node->InputAt(index)->opcode() == IrOpcode::kStateValues) {
} else if (node->InputAt(index)->opcode() == IrOpcode::kStateValues ||
node->InputAt(index)->opcode() == IrOpcode::kTypedStateValues) {
// Nested state, we need to push to the stack.
Push(node->InputAt(index));
} else {
@ -265,6 +268,19 @@ Node* StateValuesAccess::iterator::node() {
}
MachineType StateValuesAccess::iterator::type() {
Node* state = Top()->node;
if (state->opcode() == IrOpcode::kStateValues) {
return kMachAnyTagged;
} else {
DCHECK_EQ(IrOpcode::kTypedStateValues, state->opcode());
const ZoneVector<MachineType>* types =
OpParameter<const ZoneVector<MachineType>*>(state);
return (*types)[Top()->index];
}
}
bool StateValuesAccess::iterator::operator!=(iterator& other) {
// We only allow comparison with end().
CHECK(other.done());
@ -278,13 +294,16 @@ StateValuesAccess::iterator& StateValuesAccess::iterator::operator++() {
}
Node* StateValuesAccess::iterator::operator*() { return node(); }
StateValuesAccess::TypedNode StateValuesAccess::iterator::operator*() {
return TypedNode(node(), type());
}
size_t StateValuesAccess::size() {
size_t count = 0;
for (int i = 0; i < node_->InputCount(); i++) {
if (node_->InputAt(i)->opcode() == IrOpcode::kStateValues) {
if (node_->InputAt(i)->opcode() == IrOpcode::kStateValues ||
node_->InputAt(i)->opcode() == IrOpcode::kTypedStateValues) {
count += StateValuesAccess(node_->InputAt(i)).size();
} else {
count++;

View File

@ -62,12 +62,18 @@ class StateValuesCache {
class StateValuesAccess {
public:
struct TypedNode {
Node* node;
MachineType type;
TypedNode(Node* node, MachineType type) : node(node), type(type) {}
};
class iterator {
public:
// Bare minimum of operators needed for range iteration.
bool operator!=(iterator& other);
iterator& operator++();
Node* operator*();
TypedNode operator*();
private:
friend class StateValuesAccess;
@ -76,6 +82,7 @@ class StateValuesAccess {
explicit iterator(Node* node);
Node* node();
MachineType type();
bool done();
void Advance();

View File

@ -716,6 +716,11 @@ Bounds Typer::Visitor::TypeStateValues(Node* node) {
}
Bounds Typer::Visitor::TypeTypedStateValues(Node* node) {
return Bounds(Type::None(zone()), Type::Internal(zone()));
}
Bounds Typer::Visitor::TypeCall(Node* node) {
return Bounds::Unbounded(zone());
}

View File

@ -427,6 +427,7 @@ void Verifier::Visitor::Check(Node* node) {
// TODO(jarin): what are the constraints on these?
break;
case IrOpcode::kStateValues:
case IrOpcode::kTypedStateValues:
// TODO(jarin): what are the constraints on these?
break;
case IrOpcode::kCall:

View File

@ -46,7 +46,9 @@ class DeoptCodegenTester {
function(NewFunction(src)),
parse_info(scope->main_zone(), function),
info(&parse_info),
bailout_id(-1) {
bailout_id(-1),
tagged_type(1, kMachAnyTagged, zone()),
empty_types(zone()) {
CHECK(Parser::ParseStatic(&parse_info));
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
CHECK(Compiler::Analyze(&parse_info));
@ -83,6 +85,8 @@ class DeoptCodegenTester {
Handle<Code> result_code;
TestInstrSeq* code;
Graph* graph;
ZoneVector<MachineType> tagged_type;
ZoneVector<MachineType> empty_types;
};
@ -120,9 +124,10 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
m.NewNode(common.HeapConstant(caller_context_constant));
bailout_id = GetCallBailoutId();
Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
Node* locals = m.NewNode(common.StateValues(0));
Node* stack = m.NewNode(common.StateValues(0));
Node* parameters =
m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant());
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,
@ -235,9 +240,10 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
Node* context_node = m.NewNode(common.HeapConstant(context_constant));
bailout_id = GetCallBailoutId();
Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
Node* locals = m.NewNode(common.StateValues(0));
Node* stack = m.NewNode(common.StateValues(0));
Node* parameters =
m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant());
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,

View File

@ -0,0 +1,16 @@
// Copyright 2015 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.
// Flags: --noanalyze-environment-liveness
function f() {
var __v_7 = -126 - __v_3;
var __v_17 = ((__v_15 & __v_14) != 4) | 16;
if (__v_17) {
var __v_11 = 1 << __v_7;
}
__v_12 >>= __v_3;
}
assertThrows(f);

View File

@ -347,9 +347,13 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
Node* receiver = m.Parameter(1);
Node* context = m.Parameter(2);
Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1));
Node* locals = m.NewNode(m.common()->StateValues(0));
Node* stack = m.NewNode(m.common()->StateValues(0));
ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
ZoneVector<MachineType> empty_types(zone());
Node* parameters =
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1));
Node* locals = m.NewNode(m.common()->TypedStateValues(&empty_types));
Node* stack = m.NewNode(m.common()->TypedStateValues(&empty_types));
Node* context_dummy = m.Int32Constant(0);
Node* state_node = m.NewNode(
@ -387,10 +391,17 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
Node* receiver = m.Parameter(1);
Node* context = m.Int32Constant(1); // Context is ignored.
ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
ZoneVector<MachineType> float64_type(1, kMachFloat64, zone());
ZoneVector<MachineType> tagged_type(1, kMachAnyTagged, zone());
// Build frame state for the state before the call.
Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
Node* locals = m.NewNode(m.common()->StateValues(1), m.Float64Constant(0.5));
Node* stack = m.NewNode(m.common()->StateValues(1), m.UndefinedConstant());
Node* parameters =
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43));
Node* locals = m.NewNode(m.common()->TypedStateValues(&float64_type),
m.Float64Constant(0.5));
Node* stack = m.NewNode(m.common()->TypedStateValues(&tagged_type),
m.UndefinedConstant());
Node* context_sentinel = m.Int32Constant(0);
Node* frame_state_before = m.NewNode(
@ -473,10 +484,17 @@ TARGET_TEST_F(InstructionSelectorTest,
Node* receiver = m.Parameter(1);
Node* context = m.Int32Constant(66);
ZoneVector<MachineType> int32_type(1, kMachInt32, zone());
ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone());
ZoneVector<MachineType> float64_type(1, kMachFloat64, zone());
// Build frame state for the state before the call.
Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(63));
Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(64));
Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(65));
Node* parameters =
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63));
Node* locals =
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()),
@ -484,11 +502,11 @@ TARGET_TEST_F(InstructionSelectorTest,
Node* context2 = m.Int32Constant(46);
Node* parameters2 =
m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
Node* locals2 =
m.NewNode(m.common()->StateValues(1), m.Float64Constant(0.25));
Node* stack2 = m.NewNode(m.common()->StateValues(2), m.Int32Constant(44),
m.Int32Constant(45));
m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43));
Node* locals2 = m.NewNode(m.common()->TypedStateValues(&float64_type),
m.Float64Constant(0.25));
Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type),
m.Int32Constant(44), m.Int32Constant(45));
Node* frame_state_before =
m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before,
OutputFrameStateCombine::Push()),

View File

@ -115,15 +115,15 @@ class LivenessAnalysisTest : public GraphTest {
return false;
}
int i = 0;
for (Node* value : locals) {
for (StateValuesAccess::TypedNode value : locals) {
if (liveness_[i] == 'L') {
StringMatchResultListener value_listener;
if (value == replacement_) {
*listener << "whose local #" << i << " was " << value->opcode()
if (value.node == replacement_) {
*listener << "whose local #" << i << " was " << value.node->opcode()
<< " but should have been 'undefined'";
return false;
} else if (!IsInt32Constant(first_const + i)
.MatchAndExplain(value, &value_listener)) {
.MatchAndExplain(value.node, &value_listener)) {
*listener << "whose local #" << i << " does not match";
if (value_listener.str() != "") {
*listener << ", " << value_listener.str();
@ -131,8 +131,8 @@ class LivenessAnalysisTest : public GraphTest {
return false;
}
} else if (liveness_[i] == '.') {
if (value != replacement_) {
*listener << "whose local #" << i << " is " << value
if (value.node != replacement_) {
*listener << "whose local #" << i << " is " << value.node
<< " but should have been " << replacement_
<< " (undefined)";
return false;

View File

@ -32,8 +32,8 @@ TEST_F(StateValuesIteratorTest, SimpleIteration) {
}
Node* state_values = StateValuesFromVector(&inputs);
int i = 0;
for (Node* node : StateValuesAccess(state_values)) {
EXPECT_THAT(node, IsInt32Constant(i));
for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
EXPECT_THAT(node.node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(count, i);
@ -43,7 +43,7 @@ TEST_F(StateValuesIteratorTest, SimpleIteration) {
TEST_F(StateValuesIteratorTest, EmptyIteration) {
NodeVector inputs(zone());
Node* state_values = StateValuesFromVector(&inputs);
for (Node* node : StateValuesAccess(state_values)) {
for (auto node : StateValuesAccess(state_values)) {
USE(node);
FAIL();
}
@ -82,8 +82,8 @@ TEST_F(StateValuesIteratorTest, NestedIteration) {
}
Node* state_values = StateValuesFromVector(&inputs);
int i = 0;
for (Node* node : StateValuesAccess(state_values)) {
EXPECT_THAT(node, IsInt32Constant(i));
for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
EXPECT_THAT(node.node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(count, i);
@ -110,8 +110,8 @@ TEST_F(StateValuesIteratorTest, TreeFromVector) {
// Check the tree contents with vector.
int i = 0;
for (Node* node : StateValuesAccess(values_node)) {
EXPECT_THAT(node, IsInt32Constant(i));
for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
EXPECT_THAT(node.node, IsInt32Constant(i));
i++;
}
EXPECT_EQ(inputs.size(), static_cast<size_t>(i));