Register value = i.InputRegister(2);
__ Add(index, object, Operand(index, SXTW));
__ Str(value, MemOperand(index));
- SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
- ? kSaveFPRegs
- : kDontSaveFPRegs;
+ SaveFPRegsMode mode =
+ frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
// TODO(dcarney): we shouldn't test write barriers from c calls.
LinkRegisterStatus lr_status = kLRHasNotBeenSaved;
UseScratchRegisterScope scope(masm());
namespace internal {
namespace compiler {
-CodeGenerator::CodeGenerator(InstructionSequence* code)
- : code_(code),
+CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
+ InstructionSequence* code)
+ : frame_(frame),
+ linkage_(linkage),
+ code_(code),
current_block_(BasicBlock::RpoNumber::Invalid()),
current_source_position_(SourcePosition::Invalid()),
masm_(code->zone()->isolate(), NULL, 0),
// Generates native code for a sequence of instructions.
class CodeGenerator FINAL : public GapResolver::Assembler {
public:
- explicit CodeGenerator(InstructionSequence* code);
+ explicit CodeGenerator(Frame* frame, Linkage* linkage,
+ InstructionSequence* code);
// Generate native code.
Handle<Code> GenerateCode();
InstructionSequence* code() const { return code_; }
- Frame* frame() const { return code()->frame(); }
+ Frame* frame() const { return frame_; }
Isolate* isolate() const { return zone()->isolate(); }
- Linkage* linkage() const { return code()->linkage(); }
+ Linkage* linkage() const { return linkage_; }
private:
MacroAssembler* masm() { return &masm_; }
int pc_offset_;
};
- InstructionSequence* code_;
+ Frame* const frame_;
+ Linkage* const linkage_;
+ InstructionSequence* const code_;
BasicBlock::RpoNumber current_block_;
SourcePosition current_source_position_;
MacroAssembler masm_;
Register value = i.InputRegister(2);
__ mov(Operand(object, index, times_1, 0), value);
__ lea(index, Operand(object, index, times_1, 0));
- SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
- ? kSaveFPRegs
- : kDontSaveFPRegs;
+ SaveFPRegsMode mode =
+ frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
__ RecordWrite(object, index, value, mode);
break;
}
namespace internal {
namespace compiler {
-InstructionSelector::InstructionSelector(InstructionSequence* sequence,
+InstructionSelector::InstructionSelector(Linkage* linkage,
+ InstructionSequence* sequence,
Schedule* schedule,
SourcePositionTable* source_positions,
Features features)
: zone_(sequence->isolate()),
+ linkage_(linkage),
sequence_(sequence),
source_positions_(source_positions),
features_(features),
// Forward declarations.
class Features;
- InstructionSelector(InstructionSequence* sequence, Schedule* schedule,
- SourcePositionTable* source_positions,
+ InstructionSelector(Linkage* linkage, InstructionSequence* sequence,
+ Schedule* schedule, SourcePositionTable* source_positions,
Features features = SupportedFeatures());
// Visit code for the entire graph with the included schedule.
// ===========================================================================
- Linkage* linkage() const { return sequence()->linkage(); }
Schedule* schedule() const { return schedule_; }
+ Linkage* linkage() const { return linkage_; }
InstructionSequence* sequence() const { return sequence_; }
Zone* instruction_zone() const { return sequence()->zone(); }
Zone* zone() { return &zone_; }
// ===========================================================================
Zone zone_;
- InstructionSequence* sequence_;
- SourcePositionTable* source_positions_;
+ Linkage* const linkage_;
+ InstructionSequence* const sequence_;
+ SourcePositionTable* const source_positions_;
Features features_;
- Schedule* schedule_;
+ Schedule* const schedule_;
BasicBlock* current_block_;
ZoneDeque<Instruction*> instructions_;
BoolVector defined_;
InstructionSequence::InstructionSequence(Zone* instruction_zone,
- Linkage* linkage, const Graph* graph,
+ const Graph* graph,
const Schedule* schedule)
: zone_(instruction_zone),
- node_count_(graph->NodeCount()),
- node_map_(zone()->NewArray<int>(node_count_)),
+ node_map_(graph->NodeCount(), kNodeUnmapped, zone()),
instruction_blocks_(static_cast<int>(schedule->rpo_order()->size()), NULL,
zone()),
- linkage_(linkage),
constants_(ConstantMap::key_compare(),
ConstantMap::allocator_type(zone())),
immediates_(zone()),
doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
references_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
deoptimization_entries_(zone()) {
- for (int i = 0; i < node_count_; ++i) {
- node_map_[i] = -1;
- }
InitializeInstructionBlocks(zone(), schedule, &instruction_blocks_);
}
int InstructionSequence::GetVirtualRegister(const Node* node) {
- if (node_map_[node->id()] == -1) {
+ if (node_map_[node->id()] == kNodeUnmapped) {
node_map_[node->id()] = NextVirtualRegister();
}
return node_map_[node->id()];
it != code.constants_.end(); ++i, ++it) {
os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
}
- for (int i = 0; i < code.BasicBlockCount(); i++) {
+ for (int i = 0; i < code.InstructionBlockCount(); i++) {
BasicBlock::RpoNumber rpo = BasicBlock::RpoNumber::FromInt(i);
const InstructionBlock* block = code.InstructionBlockAt(rpo);
CHECK(block->rpo_number() == rpo);
typedef ZoneDeque<PointerMap*> PointerMapDeque;
typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
typedef ZoneVector<InstructionBlock*> InstructionBlocks;
+typedef IntVector NodeToVregMap;
// Represents architecture-specific generated code before, during, and after
// register allocation.
// TODO(titzer): s/IsDouble/IsFloat64/
class InstructionSequence FINAL {
public:
- InstructionSequence(Zone* zone, Linkage* linkage, const Graph* graph,
- const Schedule* schedule);
+ static const int kNodeUnmapped = -1;
+
+ InstructionSequence(Zone* zone, const Graph* graph, const Schedule* schedule);
int NextVirtualRegister() { return next_virtual_register_++; }
int VirtualRegisterCount() const { return next_virtual_register_; }
- int node_count() const { return node_count_; }
+ int node_count() const { return static_cast<int>(node_map_.size()); }
- int BasicBlockCount() const {
+ int InstructionBlockCount() const {
return static_cast<int>(instruction_blocks_.size());
}
return instruction_blocks_[rpo_number.ToSize()];
}
- // TODO(dcarney): move to register allocator.
- const InstructionBlock* GetContainingLoop(
- const InstructionBlock* block) const {
- BasicBlock::RpoNumber index = block->loop_header();
- if (!index.IsValid()) return NULL;
- return instruction_blocks_[index.ToInt()];
- }
-
const InstructionBlock* GetInstructionBlock(int instruction_index) const;
int GetVirtualRegister(const Node* node);
- // TODO(dcarney): find a way to remove this.
- const int* GetNodeMapForTesting() const { return node_map_; }
+ const NodeToVregMap& GetNodeMapForTesting() const { return node_map_; }
bool IsReference(int virtual_register) const;
bool IsDouble(int virtual_register) const;
return instructions_[index];
}
- Frame* frame() { return &frame_; }
Isolate* isolate() const { return zone()->isolate(); }
- Linkage* linkage() const { return linkage_; }
const PointerMapDeque* pointer_maps() const { return &pointer_maps_; }
Zone* zone() const { return zone_; }
typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
- Zone* zone_;
- int node_count_;
- int* node_map_;
+ Zone* const zone_;
+ NodeToVregMap node_map_;
InstructionBlocks instruction_blocks_;
- Linkage* linkage_;
ConstantMap constants_;
ConstantDeque immediates_;
InstructionDeque instructions_;
PointerMapDeque pointer_maps_;
VirtualRegisterSet doubles_;
VirtualRegisterSet references_;
- Frame frame_;
DeoptimizationVector deoptimization_entries_;
};
}
Zone* instruction_zone = schedule->zone();
- InstructionSequence sequence(instruction_zone, linkage, graph, schedule);
+ InstructionSequence sequence(instruction_zone, graph, schedule);
// Select and schedule instructions covering the scheduled graph.
{
- InstructionSelector selector(&sequence, schedule, source_positions);
+ InstructionSelector selector(linkage, &sequence, schedule,
+ source_positions);
selector.SelectInstructions();
}
}
// Allocate registers.
+ Frame frame;
{
int node_count = graph->NodeCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersForValues);
return Handle<Code>::null();
}
- RegisterAllocator allocator(&sequence);
+ RegisterAllocator allocator(&frame, linkage->info(), &sequence);
if (!allocator.Allocate()) {
linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return Handle<Code>::null();
}
// Generate native sequence.
- CodeGenerator generator(&sequence);
+ CodeGenerator generator(&frame, linkage, &sequence);
Handle<Code> code = generator.GenerateCode();
if (profiler_data != NULL) {
#if ENABLE_DISASSEMBLER
}
-RegisterAllocator::RegisterAllocator(InstructionSequence* code)
+RegisterAllocator::RegisterAllocator(Frame* frame, CompilationInfo* info,
+ InstructionSequence* code)
: zone_(code->isolate()),
+ frame_(frame),
+ info_(info),
code_(code),
- live_in_sets_(code->BasicBlockCount(), zone()),
+ live_in_sets_(code->InstructionBlockCount(), zone()),
live_ranges_(code->VirtualRegisterCount() * 2, zone()),
fixed_live_ranges_(NULL),
fixed_double_live_ranges_(NULL),
void RegisterAllocator::InitializeLivenessAnalysis() {
// Initialize the live_in sets for each block to NULL.
- int block_count = code()->BasicBlockCount();
+ int block_count = code()->InstructionBlockCount();
live_in_sets_.Initialize(block_count, zone());
live_in_sets_.AddBlock(NULL, block_count, zone());
}
PopulatePointerMaps();
ConnectRanges();
ResolveControlFlow();
- code()->frame()->SetAllocatedRegisters(assigned_registers_);
- code()->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
+ frame()->SetAllocatedRegisters(assigned_registers_);
+ frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
return true;
}
void RegisterAllocator::MeetRegisterConstraints() {
RegisterAllocatorPhase phase("L_Register constraints", this);
- for (int i = 0; i < code()->BasicBlockCount(); ++i) {
+ for (int i = 0; i < code()->InstructionBlockCount(); ++i) {
MeetRegisterConstraints(
code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(i)));
if (!AllocationOk()) return;
RegisterAllocatorPhase phase("L_Resolve phis", this);
// Process the blocks in reverse order.
- for (int i = code()->BasicBlockCount() - 1; i >= 0; --i) {
+ for (int i = code()->InstructionBlockCount() - 1; i >= 0; --i) {
ResolvePhis(code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(i)));
}
}
void RegisterAllocator::ResolveControlFlow() {
RegisterAllocatorPhase phase("L_Resolve control flow", this);
- for (int block_id = 1; block_id < code()->BasicBlockCount(); ++block_id) {
+ for (int block_id = 1; block_id < code()->InstructionBlockCount();
+ ++block_id) {
const InstructionBlock* block =
code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(block_id));
if (CanEagerlyResolveControlFlow(block)) continue;
RegisterAllocatorPhase phase("L_Build live ranges", this);
InitializeLivenessAnalysis();
// Process the blocks in reverse order.
- for (int block_id = code()->BasicBlockCount() - 1; block_id >= 0;
+ for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
--block_id) {
const InstructionBlock* block =
code()->InstructionBlockAt(BasicBlock::RpoNumber::FromInt(block_id));
operand_index);
LiveRange* range = LiveRangeFor(operand_index);
PrintF(" (first use is at %d)\n", range->first_pos()->pos().Value());
- CompilationInfo* info = code()->linkage()->info();
+ CompilationInfo* info = this->info();
if (info->IsStub()) {
if (info->code_stub() == NULL) {
PrintF("\n");
}
+static const InstructionBlock* GetContainingLoop(
+ const InstructionSequence* sequence, const InstructionBlock* block) {
+ BasicBlock::RpoNumber index = block->loop_header();
+ if (!index.IsValid()) return NULL;
+ return sequence->InstructionBlockAt(index);
+}
+
+
LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
LiveRange* range, LifetimePosition pos) {
const InstructionBlock* block = GetInstructionBlock(pos.InstructionStart());
const InstructionBlock* loop_header =
- block->IsLoopHeader() ? block : code()->GetContainingLoop(block);
+ block->IsLoopHeader() ? block : GetContainingLoop(code(), block);
if (loop_header == NULL) return pos;
}
// Try hoisting out to an outer loop.
- loop_header = code()->GetContainingLoop(loop_header);
+ loop_header = GetContainingLoop(code(), loop_header);
}
return pos;
const InstructionBlock* block = end_block;
// Find header of outermost loop.
// TODO(titzer): fix redundancy below.
- while (code()->GetContainingLoop(block) != NULL &&
- code()->GetContainingLoop(block)->rpo_number().ToInt() >
+ while (GetContainingLoop(code(), block) != NULL &&
+ GetContainingLoop(code(), block)->rpo_number().ToInt() >
start_block->rpo_number().ToInt()) {
- block = code()->GetContainingLoop(block);
+ block = GetContainingLoop(code(), block);
}
// We did not find any suitable outer loop. Split at the latest possible
if (op == NULL) {
// Allocate a new operand referring to the spill slot.
RegisterKind kind = range->Kind();
- int index = code()->frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
+ int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
if (kind == DOUBLE_REGISTERS) {
op = DoubleStackSlotOperand::Create(index, zone());
} else {
RegisterAllocatorPhase::RegisterAllocatorPhase(const char* name,
RegisterAllocator* allocator)
- : CompilationPhase(name, allocator->code()->linkage()->info()),
- allocator_(allocator) {
+ : CompilationPhase(name, allocator->info()), allocator_(allocator) {
if (FLAG_turbo_stats) {
allocator_zone_start_allocation_size_ =
allocator->zone()->allocation_size();
class RegisterAllocator BASE_EMBEDDED {
public:
- explicit RegisterAllocator(InstructionSequence* code);
+ // TODO(dcarney): remove info
+ explicit RegisterAllocator(Frame* frame, CompilationInfo* info,
+ InstructionSequence* code);
static void TraceAlloc(const char* msg, ...);
return &fixed_double_live_ranges_;
}
+ CompilationInfo* info() const { return info_; }
inline InstructionSequence* code() const { return code_; }
// This zone is for datastructures only needed during register allocation.
return code()->InstructionAt(index);
}
+ Frame* frame() const { return frame_; }
+
Zone zone_;
- InstructionSequence* code_;
+ Frame* const frame_;
+ CompilationInfo* const info_;
+ InstructionSequence* const code_;
// During liveness analysis keep a mapping from block id to live_in sets
// for blocks already analyzed.
__ movsxlq(index, index);
__ movq(Operand(object, index, times_1, 0), value);
__ leaq(index, Operand(object, index, times_1, 0));
- SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters()
- ? kSaveFPRegs
- : kDontSaveFPRegs;
+ SaveFPRegsMode mode =
+ frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
__ RecordWrite(object, index, value, mode);
break;
}
// Initialize the codegen and generate code.
Linkage* linkage = new (scope_->main_zone()) Linkage(&info);
- code = new v8::internal::compiler::InstructionSequence(
- scope_->main_zone(), linkage, graph, schedule);
+ code = new v8::internal::compiler::InstructionSequence(scope_->main_zone(),
+ graph, schedule);
SourcePositionTable source_positions(graph);
- InstructionSelector selector(code, schedule, &source_positions);
+ InstructionSelector selector(linkage, code, schedule, &source_positions);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
<< *code;
}
- RegisterAllocator allocator(code);
+ Frame frame;
+ RegisterAllocator allocator(&frame, &info, code);
CHECK(allocator.Allocate());
if (FLAG_trace_turbo) {
<< *code;
}
- compiler::CodeGenerator generator(code);
+ compiler::CodeGenerator generator(&frame, linkage, code);
result_code = generator.GenerateCode();
#ifdef OBJECT_PRINT
Scheduler::ComputeSpecialRPO(&schedule);
DCHECK(schedule.rpo_order()->size() > 0);
}
- code = new TestInstrSeq(main_zone(), &linkage, &graph, &schedule);
+ code = new TestInstrSeq(main_zone(), &graph, &schedule);
}
Node* Int32Constant(int32_t val) {
CHECK_EQ(R.graph.NodeCount(), R.code->node_count());
BasicBlockVector* blocks = R.schedule.rpo_order();
- CHECK_EQ(static_cast<int>(blocks->size()), R.code->BasicBlockCount());
+ CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount());
int index = 0;
for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end();
int initial_node_count = graph()->NodeCount();
CompilationInfo info(test_->isolate(), test_->zone());
Linkage linkage(&info, call_descriptor());
- InstructionSequence sequence(test_->zone(), &linkage, graph(), schedule);
+ InstructionSequence sequence(test_->zone(), graph(), schedule);
SourcePositionTable source_position_table(graph());
- InstructionSelector selector(&sequence, schedule, &source_position_table,
- features);
+ InstructionSelector selector(&linkage, &sequence, schedule,
+ &source_position_table, features);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
OFStream out(stdout);
Stream s;
// Map virtual registers.
{
- const int* node_map = sequence.GetNodeMapForTesting();
+ const NodeToVregMap& node_map = sequence.GetNodeMapForTesting();
for (int i = 0; i < initial_node_count; ++i) {
- if (node_map[i] >= 0) {
+ if (node_map[i] != InstructionSequence::kNodeUnmapped) {
s.virtual_registers_.insert(std::make_pair(i, node_map[i]));
}
}