// unknown pc location. Assembler::bind() is used to bind a label to the
// current pc. A label can be bound only once.
-class Label BASE_EMBEDDED {
+class Label {
public:
enum Distance {
kNear, kFar
break;
}
case kArchJmp:
- __ b(code_->GetLabel(i.InputRpo(0)));
+ __ b(GetLabel(i.InputRpo(0)));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchNop:
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
- Label* tlabel = code()->GetLabel(tblock);
- Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
+ Label* tlabel = GetLabel(tblock);
+ Label* flabel = fallthru ? &done : GetLabel(fblock);
switch (condition) {
case kUnorderedEqual:
__ b(vs, flabel);
} while (0)
-#define ASSEMBLE_TEST_AND_BRANCH(asm_instr, width) \
- do { \
- bool fallthrough = IsNextInAssemblyOrder(i.InputRpo(3)); \
- __ asm_instr(i.InputRegister##width(0), i.InputInt6(1), \
- code_->GetLabel(i.InputRpo(2))); \
- if (!fallthrough) __ B(code_->GetLabel(i.InputRpo(3))); \
+#define ASSEMBLE_TEST_AND_BRANCH(asm_instr, width) \
+ do { \
+ bool fallthrough = IsNextInAssemblyOrder(i.InputRpo(3)); \
+ __ asm_instr(i.InputRegister##width(0), i.InputInt6(1), \
+ GetLabel(i.InputRpo(2))); \
+ if (!fallthrough) __ B(GetLabel(i.InputRpo(3))); \
} while (0)
break;
}
case kArchJmp:
- __ B(code_->GetLabel(i.InputRpo(0)));
+ __ B(GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
- Label* tlabel = code()->GetLabel(tblock);
- Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
+ Label* tlabel = GetLabel(tblock);
+ Label* flabel = fallthru ? &done : GetLabel(fblock);
switch (condition) {
case kUnorderedEqual:
__ B(vs, flabel);
return ToHeapObject(instr_->InputAt(index));
}
- Label* InputLabel(int index) {
- return gen_->code()->GetLabel(InputRpo(index));
- }
+ Label* InputLabel(int index) { return gen_->GetLabel(InputRpo(index)); }
BasicBlock::RpoNumber InputRpo(int index) {
int rpo_number = InputInt32(index);
linkage_(linkage),
code_(code),
info_(info),
+ labels_(zone()->NewArray<Label>(code->InstructionBlockCount())),
current_block_(BasicBlock::RpoNumber::Invalid()),
current_source_position_(SourcePosition::Invalid()),
masm_(code->zone()->isolate(), NULL, 0),
deoptimization_states_(code->zone()),
deoptimization_literals_(code->zone()),
translations_(code->zone()),
- last_lazy_deopt_pc_(0) {}
+ last_lazy_deopt_pc_(0) {
+ for (int i = 0; i < code->InstructionBlockCount(); ++i) {
+ new (&labels_[i]) Label;
+ }
+}
Handle<Code> CodeGenerator::GenerateCode() {
info->set_prologue_offset(masm()->pc_offset());
AssemblePrologue();
- // Assemble all non-deferred instructions.
- for (auto const block : code()->instruction_blocks()) {
- if (block->IsDeferred()) continue;
- for (int i = block->code_start(); i < block->code_end(); ++i) {
- AssembleInstruction(code()->InstructionAt(i));
- }
- }
-
- // Assemble all deferred instructions.
- for (auto const block : code()->instruction_blocks()) {
- if (!block->IsDeferred()) continue;
- for (int i = block->code_start(); i < block->code_end(); ++i) {
- AssembleInstruction(code()->InstructionAt(i));
+ // Assemble all non-deferred blocks, followed by deferred ones.
+ for (int deferred = 0; deferred < 2; ++deferred) {
+ for (auto const block : code()->instruction_blocks()) {
+ if (block->IsDeferred() == (deferred == 0)) {
+ continue;
+ }
+ // Bind a label for a block.
+ current_block_ = block->rpo_number();
+ if (FLAG_code_comments) {
+ // TODO(titzer): these code comments are a giant memory leak.
+ Vector<char> buffer = Vector<char>::New(32);
+ SNPrintF(buffer, "-- B%d start --", block->id().ToInt());
+ masm()->RecordComment(buffer.start());
+ }
+ masm()->bind(GetLabel(current_block_));
+ for (int i = block->code_start(); i < block->code_end(); ++i) {
+ AssembleInstruction(code()->InstructionAt(i));
+ }
}
}
void CodeGenerator::AssembleInstruction(Instruction* instr) {
- if (instr->IsBlockStart()) {
- // Bind a label for a block start and handle parallel moves.
- BlockStartInstruction* block_start = BlockStartInstruction::cast(instr);
- current_block_ = block_start->rpo_number();
- if (FLAG_code_comments) {
- // TODO(titzer): these code comments are a giant memory leak.
- Vector<char> buffer = Vector<char>::New(32);
- SNPrintF(buffer, "-- B%d start --", block_start->id().ToInt());
- masm()->RecordComment(buffer.start());
- }
- masm()->bind(block_start->label());
- }
if (instr->IsGapMoves()) {
// Handle parallel moves associated with the gap instruction.
AssembleGap(GapInstruction::cast(instr));
Isolate* isolate() const { return zone()->isolate(); }
Linkage* linkage() const { return linkage_; }
+ Label* GetLabel(BasicBlock::RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
+
private:
MacroAssembler* masm() { return &masm_; }
GapResolver* resolver() { return &resolver_; }
Linkage* const linkage_;
InstructionSequence* const code_;
CompilationInfo* const info_;
+ Label* const labels_;
BasicBlock::RpoNumber current_block_;
SourcePosition current_source_position_;
MacroAssembler masm_;
break;
}
case kArchJmp:
- __ jmp(code()->GetLabel(i.InputRpo(0)));
+ __ jmp(GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
- Label* tlabel = code()->GetLabel(tblock);
- Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
+ Label* tlabel = GetLabel(tblock);
+ Label* flabel = fallthru ? &done : GetLabel(fblock);
Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
switch (condition) {
case kUnorderedEqual:
InstructionBlocks* instruction_blocks)
: zone_(instruction_zone),
instruction_blocks_(instruction_blocks),
+ block_starts_(zone()),
constants_(ConstantMap::key_compare(),
ConstantMap::allocator_type(zone())),
immediates_(zone()),
pointer_maps_(zone()),
doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
references_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
- deoptimization_entries_(zone()) {}
-
-
-Label* InstructionSequence::GetLabel(BasicBlock::RpoNumber rpo) {
- return GetBlockStart(rpo)->label();
+ deoptimization_entries_(zone()) {
+ block_starts_.reserve(instruction_blocks_->size());
}
BlockStartInstruction* InstructionSequence::GetBlockStart(
BasicBlock::RpoNumber rpo) {
InstructionBlock* block = InstructionBlockAt(rpo);
- BlockStartInstruction* block_start =
- BlockStartInstruction::cast(InstructionAt(block->code_start()));
- DCHECK_EQ(rpo.ToInt(), block_start->rpo_number().ToInt());
- return block_start;
+ return BlockStartInstruction::cast(InstructionAt(block->code_start()));
}
void InstructionSequence::StartBlock(BasicBlock::RpoNumber rpo) {
+ DCHECK(block_starts_.size() == rpo.ToSize());
InstructionBlock* block = InstructionBlockAt(rpo);
- block->set_code_start(static_cast<int>(instructions_.size()));
- BlockStartInstruction* block_start =
- BlockStartInstruction::New(zone(), block->id(), rpo);
+ int code_start = static_cast<int>(instructions_.size());
+ block->set_code_start(code_start);
+ block_starts_.push_back(code_start);
+ BlockStartInstruction* block_start = BlockStartInstruction::New(zone());
AddInstruction(block_start);
}
const InstructionBlock* InstructionSequence::GetInstructionBlock(
int instruction_index) const {
- // TODO(turbofan): Optimize this.
- for (;;) {
- DCHECK_LE(0, instruction_index);
- Instruction* instruction = InstructionAt(instruction_index--);
- if (instruction->IsBlockStart()) {
- return instruction_blocks_->at(
- BlockStartInstruction::cast(instruction)->rpo_number().ToSize());
- }
- }
+ DCHECK(instruction_blocks_->size() == block_starts_.size());
+ auto begin = block_starts_.begin();
+ auto end = std::lower_bound(begin, block_starts_.end(), instruction_index,
+ std::less_equal<int>());
+ size_t index = std::distance(begin, end) - 1;
+ auto block = instruction_blocks_->at(index);
+ DCHECK(block->code_start() <= instruction_index &&
+ instruction_index < block->code_end());
+ return block;
}
// This special kind of gap move instruction represents the beginning of a
// block of code.
-// TODO(titzer): move code_start and code_end from BasicBlock to here.
class BlockStartInstruction FINAL : public GapInstruction {
public:
- Label* label() { return &label_; }
- BasicBlock::RpoNumber rpo_number() const { return rpo_number_; }
- BasicBlock::Id id() const { return id_; }
-
- static BlockStartInstruction* New(Zone* zone, BasicBlock::Id id,
- BasicBlock::RpoNumber rpo_number) {
+ static BlockStartInstruction* New(Zone* zone) {
void* buffer = zone->New(sizeof(BlockStartInstruction));
- return new (buffer) BlockStartInstruction(id, rpo_number);
+ return new (buffer) BlockStartInstruction();
}
static BlockStartInstruction* cast(Instruction* instr) {
}
private:
- BlockStartInstruction(BasicBlock::Id id, BasicBlock::RpoNumber rpo_number)
- : GapInstruction(kBlockStartInstruction),
- id_(id),
- rpo_number_(rpo_number) {}
-
- BasicBlock::Id id_;
- BasicBlock::RpoNumber rpo_number_;
- Label label_;
+ BlockStartInstruction() : GapInstruction(kBlockStartInstruction) {}
};
void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to);
- Label* GetLabel(BasicBlock::RpoNumber rpo);
BlockStartInstruction* GetBlockStart(BasicBlock::RpoNumber rpo);
typedef InstructionDeque::const_iterator const_iterator;
Zone* const zone_;
InstructionBlocks* const instruction_blocks_;
+ IntVector block_starts_;
ConstantMap constants_;
ConstantDeque immediates_;
InstructionDeque instructions_;
break;
}
case kArchJmp:
- __ Branch(code_->GetLabel(i.InputRpo(0)));
+ __ Branch(GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
- Label* tlabel = code()->GetLabel(tblock);
- Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
+ Label* tlabel = GetLabel(tblock);
+ Label* flabel = fallthru ? &done : GetLabel(fblock);
Condition cc = kNoCondition;
// MIPS does not have condition code flags, so compare and branch are
break;
}
case kArchJmp:
- __ jmp(code_->GetLabel(i.InputRpo(0)));
+ __ jmp(GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
- Label* tlabel = code()->GetLabel(tblock);
- Label* flabel = fallthru ? &done : code()->GetLabel(fblock);
+ Label* tlabel = GetLabel(tblock);
+ Label* flabel = fallthru ? &done : GetLabel(fblock);
Label::Distance flabel_distance = fallthru ? Label::kNear : Label::kFar;
switch (condition) {
case kUnorderedEqual: