[turbofan] Check instruction input/output count limits in instruction selector.

BUG=chromium:625966

Review-Url: https://codereview.chromium.org/2390303002
Cr-Commit-Position: refs/heads/master@{#39970}
This commit is contained in:
jarin 2016-10-04 22:43:21 -07:00 committed by Commit bot
parent 17cb51254c
commit a974970cff
5 changed files with 56 additions and 14 deletions

View File

@ -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);
}
}

View File

@ -61,7 +61,7 @@ class InstructionSelector final {
: kDisableScheduling);
// Visit code for the entire graph with the included schedule.
void SelectInstructions();
bool SelectInstructions();
void StartBlock(RpoNumber rpo);
void EndBlock(RpoNumber rpo);
@ -332,6 +332,11 @@ class InstructionSelector final {
Zone* instruction_zone() const { return sequence()->zone(); }
Zone* zone() const { return zone_; }
void set_instruction_selection_failed() {
instruction_selection_failed_ = true;
}
bool instruction_selection_failed() { return instruction_selection_failed_; }
// ===========================================================================
Zone* const zone_;
@ -351,6 +356,7 @@ class InstructionSelector final {
InstructionScheduler* scheduler_;
EnableScheduling enable_scheduling_;
Frame* frame_;
bool instruction_selection_failed_;
};
} // namespace compiler

View File

@ -947,6 +947,14 @@ class Instruction final {
void Print(const RegisterConfiguration* config) const;
void Print() const;
typedef BitField<size_t, 0, 8> OutputCountField;
typedef BitField<size_t, 8, 16> InputCountField;
typedef BitField<size_t, 24, 6> TempCountField;
static const size_t kMaxOutputCount = OutputCountField::kMax;
static const size_t kMaxInputCount = InputCountField::kMax;
static const size_t kMaxTempCount = TempCountField::kMax;
private:
explicit Instruction(InstructionCode opcode);
@ -955,9 +963,6 @@ class Instruction final {
InstructionOperand* inputs, size_t temp_count,
InstructionOperand* temps);
typedef BitField<size_t, 0, 8> OutputCountField;
typedef BitField<size_t, 8, 16> InputCountField;
typedef BitField<size_t, 24, 6> TempCountField;
typedef BitField<bool, 30, 1> IsCallField;
InstructionCode opcode_;

View File

@ -1233,7 +1233,9 @@ struct InstructionSelectionPhase {
data->info()->is_source_positions_enabled()
? InstructionSelector::kAllSourcePositions
: InstructionSelector::kCallSourcePositions);
selector.SelectInstructions();
if (!selector.SelectInstructions()) {
data->set_compilation_failed();
}
}
};
@ -1754,6 +1756,11 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage) {
data->InitializeFrameData(call_descriptor);
// Select and schedule instructions covering the scheduled graph.
Run<InstructionSelectionPhase>(linkage);
if (data->compilation_failed()) {
info()->AbortOptimization(kCodeGenerationFailed);
data->EndPhaseKind();
return false;
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
AllowHandleDereference allow_deref;

View File

@ -0,0 +1,10 @@
// Copyright 2016 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.
"use strict";
var s = "";
for (var i = 0; i < 65535; i++) {
s += ("var a" + i + ";");
}
eval(s);