Index: src/compiler/instruction-selector.cc |
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc |
index d8409a3f89c8250155d645b73b189ece198083d4..e8a3153f7ff90350d83b7ae446af39d7c958bb79 100644 |
--- a/src/compiler/instruction-selector.cc |
+++ b/src/compiler/instruction-selector.cc |
@@ -41,11 +41,12 @@ InstructionSelector::InstructionSelector( |
virtual_register_rename_(zone), |
scheduler_(nullptr), |
enable_scheduling_(enable_scheduling), |
- frame_(frame) { |
+ frame_(frame), |
+ instruction_selection_failed_(false) { |
instructions_.reserve(node_count); |
} |
-void InstructionSelector::SelectInstructions() { |
+bool InstructionSelector::SelectInstructions() { |
// Mark the inputs of all phis in loop headers as used. |
BasicBlockVector* blocks = schedule()->rpo_order(); |
for (auto const block : *blocks) { |
@@ -64,6 +65,7 @@ void InstructionSelector::SelectInstructions() { |
// Visit each basic block in post order. |
for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { |
VisitBlock(*i); |
+ if (instruction_selection_failed()) return false; |
} |
// Schedule the selected instructions. |
@@ -90,6 +92,7 @@ void InstructionSelector::SelectInstructions() { |
#if DEBUG |
sequence()->ValidateSSA(); |
#endif |
+ return true; |
} |
void InstructionSelector::StartBlock(RpoNumber rpo) { |
@@ -208,6 +211,13 @@ Instruction* InstructionSelector::Emit( |
InstructionCode opcode, size_t output_count, InstructionOperand* outputs, |
size_t input_count, InstructionOperand* inputs, size_t temp_count, |
InstructionOperand* temps) { |
+ if (output_count >= Instruction::kMaxOutputCount || |
+ input_count >= Instruction::kMaxInputCount || |
+ temp_count >= Instruction::kMaxTempCount) { |
+ set_instruction_selection_failed(); |
+ return nullptr; |
+ } |
+ |
Instruction* instr = |
Instruction::New(instruction_zone(), opcode, output_count, outputs, |
input_count, inputs, temp_count, temps); |
@@ -767,7 +777,6 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, |
} |
} |
- |
void InstructionSelector::VisitBlock(BasicBlock* block) { |
DCHECK(!current_block_); |
current_block_ = block; |
@@ -804,6 +813,7 @@ void InstructionSelector::VisitBlock(BasicBlock* block) { |
// up". |
size_t current_node_end = instructions_.size(); |
VisitNode(node); |
+ if (instruction_selection_failed()) return; |
std::reverse(instructions_.begin() + current_node_end, instructions_.end()); |
if (instructions_.size() == current_node_end) continue; |
// Mark source position on first instruction emitted. |
@@ -1843,9 +1853,11 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
// Emit the call instruction. |
size_t const output_count = buffer.outputs.size(); |
auto* outputs = output_count ? &buffer.outputs.front() : nullptr; |
- Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
- &buffer.instruction_args.front()) |
- ->MarkAsCall(); |
+ Instruction* call_instr = |
+ Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
+ &buffer.instruction_args.front()); |
+ if (instruction_selection_failed()) return; |
+ call_instr->MarkAsCall(); |
} |
@@ -1951,9 +1963,11 @@ void InstructionSelector::VisitTailCall(Node* node) { |
// Emit the call instruction. |
size_t output_count = buffer.outputs.size(); |
auto* outputs = &buffer.outputs.front(); |
- Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
- &buffer.instruction_args.front()) |
- ->MarkAsCall(); |
+ Instruction* call_instr = |
+ Emit(opcode, output_count, outputs, buffer.instruction_args.size(), |
+ &buffer.instruction_args.front()); |
+ if (instruction_selection_failed()) return; |
+ call_instr->MarkAsCall(); |
Emit(kArchRet, 0, nullptr, output_count, outputs); |
} |
} |