Remove duplicated LChunk code.
Divide the LChunk class into an arch-independent LChunkBase and an arch-dependent LChunk which inherits from LChunkBase. BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/10701141 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12045 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ef701cb7ba
commit
951b64d55f
@ -407,16 +407,6 @@ void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
LChunk::LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: spill_slot_count_(0),
|
||||
info_(info),
|
||||
graph_(graph),
|
||||
instructions_(32, graph->zone()),
|
||||
pointer_maps_(8, graph->zone()),
|
||||
inlined_closures_(1, graph->zone()) {
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetNextSpillIndex(bool is_double) {
|
||||
// Skip a slot if for a double-width slot.
|
||||
if (is_double) spill_slot_count_++;
|
||||
@ -434,117 +424,6 @@ LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::MarkEmptyBlocks() {
|
||||
HPhase phase("L_Mark empty blocks", this);
|
||||
for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
||||
HBasicBlock* block = graph()->blocks()->at(i);
|
||||
int first = block->first_instruction_index();
|
||||
int last = block->last_instruction_index();
|
||||
LInstruction* first_instr = instructions()->at(first);
|
||||
LInstruction* last_instr = instructions()->at(last);
|
||||
|
||||
LLabel* label = LLabel::cast(first_instr);
|
||||
if (last_instr->IsGoto()) {
|
||||
LGoto* goto_instr = LGoto::cast(last_instr);
|
||||
if (label->IsRedundant() &&
|
||||
!label->is_loop_header()) {
|
||||
bool can_eliminate = true;
|
||||
for (int i = first + 1; i < last && can_eliminate; ++i) {
|
||||
LInstruction* cur = instructions()->at(i);
|
||||
if (cur->IsGap()) {
|
||||
LGap* gap = LGap::cast(cur);
|
||||
if (!gap->IsRedundant()) {
|
||||
can_eliminate = false;
|
||||
}
|
||||
} else {
|
||||
can_eliminate = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_eliminate) {
|
||||
label->set_replacement(GetLabel(goto_instr->block_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
||||
LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
|
||||
int index = -1;
|
||||
if (instr->IsControl()) {
|
||||
instructions_.Add(gap, zone());
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
} else {
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
instructions_.Add(gap, zone());
|
||||
}
|
||||
if (instr->HasPointerMap()) {
|
||||
pointer_maps_.Add(instr->pointer_map(), zone());
|
||||
instr->pointer_map()->set_lithium_position(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
|
||||
return LConstantOperand::Create(constant->id(), zone());
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetParameterStackSlot(int index) const {
|
||||
// The receiver is at index 0, the first parameter at index 1, so we
|
||||
// shift all parameter indexes down by the number of parameters, and
|
||||
// make sure they end up negative so they are distinguishable from
|
||||
// spill slots.
|
||||
int result = index - info()->scope()->num_parameters() - 1;
|
||||
ASSERT(result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A parameter relative to ebp in the arguments stub.
|
||||
int LChunk::ParameterAt(int index) {
|
||||
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
return (1 + info()->scope()->num_parameters() - index) *
|
||||
kPointerSize;
|
||||
}
|
||||
|
||||
|
||||
LGap* LChunk::GetGapAt(int index) const {
|
||||
return LGap::cast(instructions_[index]);
|
||||
}
|
||||
|
||||
|
||||
bool LChunk::IsGapAt(int index) const {
|
||||
return instructions_[index]->IsGap();
|
||||
}
|
||||
|
||||
|
||||
int LChunk::NearestGapPos(int index) const {
|
||||
while (!IsGapAt(index)) index--;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
|
||||
GetGapAt(index)->GetOrCreateParallelMove(
|
||||
LGap::START, zone())->AddMove(from, to, zone());
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
|
||||
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
|
||||
}
|
||||
|
||||
|
||||
Representation LChunk::LookupLiteralRepresentation(
|
||||
LConstantOperand* operand) const {
|
||||
return graph_->LookupValue(operand->index())->representation();
|
||||
}
|
||||
|
||||
|
||||
LChunk* LChunkBuilder::Build() {
|
||||
ASSERT(is_unused());
|
||||
chunk_ = new(zone()) LChunk(info(), graph());
|
||||
|
@ -2224,65 +2224,13 @@ class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
|
||||
class LChunkBuilder;
|
||||
class LChunk: public ZoneObject {
|
||||
class LChunk: public LChunkBase {
|
||||
public:
|
||||
explicit LChunk(CompilationInfo* info, HGraph* graph);
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
LConstantOperand* DefineConstantOperand(HConstant* constant);
|
||||
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
|
||||
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
|
||||
explicit LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: LChunkBase(info, graph) { }
|
||||
|
||||
int GetNextSpillIndex(bool is_double);
|
||||
LOperand* GetNextSpillSlot(bool is_double);
|
||||
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
void AddGapMove(int index, LOperand* from, LOperand* to);
|
||||
LGap* GetGapAt(int index) const;
|
||||
bool IsGapAt(int index) const;
|
||||
int NearestGapPos(int index) const;
|
||||
void MarkEmptyBlocks();
|
||||
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
||||
LLabel* GetLabel(int block_id) const {
|
||||
HBasicBlock* block = graph_->blocks()->at(block_id);
|
||||
int first_instruction = block->first_instruction_index();
|
||||
return LLabel::cast(instructions_[first_instruction]);
|
||||
}
|
||||
int LookupDestination(int block_id) const {
|
||||
LLabel* cur = GetLabel(block_id);
|
||||
while (cur->replacement() != NULL) {
|
||||
cur = cur->replacement();
|
||||
}
|
||||
return cur->block_id();
|
||||
}
|
||||
Label* GetAssemblyLabel(int block_id) const {
|
||||
LLabel* label = GetLabel(block_id);
|
||||
ASSERT(!label->HasReplacement());
|
||||
return label->label();
|
||||
}
|
||||
|
||||
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
||||
return &inlined_closures_;
|
||||
}
|
||||
|
||||
void AddInlinedClosure(Handle<JSFunction> closure) {
|
||||
inlined_closures_.Add(closure, zone());
|
||||
}
|
||||
|
||||
Zone* zone() const { return graph_->zone(); }
|
||||
|
||||
private:
|
||||
int spill_slot_count_;
|
||||
CompilationInfo* info_;
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -9251,7 +9251,7 @@ void HTracer::TraceCompilation(FunctionLiteral* function) {
|
||||
}
|
||||
|
||||
|
||||
void HTracer::TraceLithium(const char* name, LChunk* chunk) {
|
||||
void HTracer::TraceLithium(const char* name, LChunkBase* chunk) {
|
||||
Trace(name, chunk->graph(), chunk);
|
||||
}
|
||||
|
||||
@ -9261,7 +9261,7 @@ void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
|
||||
}
|
||||
|
||||
|
||||
void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
|
||||
void HTracer::Trace(const char* name, HGraph* graph, LChunkBase* chunk) {
|
||||
Tag tag(this, "cfg");
|
||||
PrintStringProperty("name", name);
|
||||
const ZoneList<HBasicBlock*>* blocks = graph->blocks();
|
||||
@ -9523,7 +9523,7 @@ const char* const HPhase::kTotal = "Total";
|
||||
|
||||
void HPhase::Begin(const char* name,
|
||||
HGraph* graph,
|
||||
LChunk* chunk,
|
||||
LChunkBase* chunk,
|
||||
LAllocator* allocator) {
|
||||
name_ = name;
|
||||
graph_ = graph;
|
||||
|
@ -48,7 +48,7 @@ class HGraph;
|
||||
class HLoopInformation;
|
||||
class HTracer;
|
||||
class LAllocator;
|
||||
class LChunk;
|
||||
class LChunkBase;
|
||||
class LiveRange;
|
||||
|
||||
|
||||
@ -1334,7 +1334,7 @@ class HPhase BASE_EMBEDDED {
|
||||
HPhase(const char* name, HGraph* graph) {
|
||||
Begin(name, graph, NULL, NULL);
|
||||
}
|
||||
HPhase(const char* name, LChunk* chunk) {
|
||||
HPhase(const char* name, LChunkBase* chunk) {
|
||||
Begin(name, NULL, chunk, NULL);
|
||||
}
|
||||
HPhase(const char* name, LAllocator* allocator) {
|
||||
@ -1348,14 +1348,14 @@ class HPhase BASE_EMBEDDED {
|
||||
private:
|
||||
void Begin(const char* name,
|
||||
HGraph* graph,
|
||||
LChunk* chunk,
|
||||
LChunkBase* chunk,
|
||||
LAllocator* allocator);
|
||||
void End() const;
|
||||
|
||||
int64_t start_;
|
||||
const char* name_;
|
||||
HGraph* graph_;
|
||||
LChunk* chunk_;
|
||||
LChunkBase* chunk_;
|
||||
LAllocator* allocator_;
|
||||
unsigned start_allocation_size_;
|
||||
};
|
||||
@ -1365,7 +1365,7 @@ class HTracer: public Malloced {
|
||||
public:
|
||||
void TraceCompilation(FunctionLiteral* function);
|
||||
void TraceHydrogen(const char* name, HGraph* graph);
|
||||
void TraceLithium(const char* name, LChunk* chunk);
|
||||
void TraceLithium(const char* name, LChunkBase* chunk);
|
||||
void TraceLiveRanges(const char* name, LAllocator* allocator);
|
||||
|
||||
static HTracer* Instance() {
|
||||
@ -1406,7 +1406,7 @@ class HTracer: public Malloced {
|
||||
}
|
||||
|
||||
void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
|
||||
void Trace(const char* name, HGraph* graph, LChunk* chunk);
|
||||
void Trace(const char* name, HGraph* graph, LChunkBase* chunk);
|
||||
void FlushToFile();
|
||||
|
||||
void PrintEmptyProperty(const char* name) {
|
||||
|
@ -387,42 +387,6 @@ LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::MarkEmptyBlocks() {
|
||||
HPhase phase("L_Mark empty blocks", this);
|
||||
for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
||||
HBasicBlock* block = graph()->blocks()->at(i);
|
||||
int first = block->first_instruction_index();
|
||||
int last = block->last_instruction_index();
|
||||
LInstruction* first_instr = instructions()->at(first);
|
||||
LInstruction* last_instr = instructions()->at(last);
|
||||
|
||||
LLabel* label = LLabel::cast(first_instr);
|
||||
if (last_instr->IsGoto()) {
|
||||
LGoto* goto_instr = LGoto::cast(last_instr);
|
||||
if (label->IsRedundant() &&
|
||||
!label->is_loop_header()) {
|
||||
bool can_eliminate = true;
|
||||
for (int i = first + 1; i < last && can_eliminate; ++i) {
|
||||
LInstruction* cur = instructions()->at(i);
|
||||
if (cur->IsGap()) {
|
||||
LGap* gap = LGap::cast(cur);
|
||||
if (!gap->IsRedundant()) {
|
||||
can_eliminate = false;
|
||||
}
|
||||
} else {
|
||||
can_eliminate = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_eliminate) {
|
||||
label->set_replacement(GetLabel(goto_instr->block_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LStoreNamedField::PrintDataTo(StringStream* stream) {
|
||||
object()->PrintTo(stream);
|
||||
stream->Add(".");
|
||||
@ -474,81 +438,6 @@ void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
||||
LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
|
||||
int index = -1;
|
||||
if (instr->IsControl()) {
|
||||
instructions_.Add(gap, zone());
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
} else {
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
instructions_.Add(gap, zone());
|
||||
}
|
||||
if (instr->HasPointerMap()) {
|
||||
pointer_maps_.Add(instr->pointer_map(), zone());
|
||||
instr->pointer_map()->set_lithium_position(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
|
||||
return LConstantOperand::Create(constant->id(), zone());
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetParameterStackSlot(int index) const {
|
||||
// The receiver is at index 0, the first parameter at index 1, so we
|
||||
// shift all parameter indexes down by the number of parameters, and
|
||||
// make sure they end up negative so they are distinguishable from
|
||||
// spill slots.
|
||||
int result = index - info()->scope()->num_parameters() - 1;
|
||||
ASSERT(result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A parameter relative to ebp in the arguments stub.
|
||||
int LChunk::ParameterAt(int index) {
|
||||
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
return (1 + info()->scope()->num_parameters() - index) *
|
||||
kPointerSize;
|
||||
}
|
||||
|
||||
|
||||
LGap* LChunk::GetGapAt(int index) const {
|
||||
return LGap::cast(instructions_[index]);
|
||||
}
|
||||
|
||||
|
||||
bool LChunk::IsGapAt(int index) const {
|
||||
return instructions_[index]->IsGap();
|
||||
}
|
||||
|
||||
|
||||
int LChunk::NearestGapPos(int index) const {
|
||||
while (!IsGapAt(index)) index--;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
|
||||
GetGapAt(index)->GetOrCreateParallelMove(
|
||||
LGap::START, zone())->AddMove(from, to, zone());
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
|
||||
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
|
||||
}
|
||||
|
||||
|
||||
Representation LChunk::LookupLiteralRepresentation(
|
||||
LConstantOperand* operand) const {
|
||||
return graph_->LookupValue(operand->index())->representation();
|
||||
}
|
||||
|
||||
|
||||
LChunk* LChunkBuilder::Build() {
|
||||
ASSERT(is_unused());
|
||||
chunk_ = new(zone()) LChunk(info(), graph());
|
||||
|
@ -2319,74 +2319,19 @@ class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
|
||||
class LChunkBuilder;
|
||||
class LChunk: public ZoneObject {
|
||||
class LChunk: public LChunkBase {
|
||||
public:
|
||||
LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: spill_slot_count_(0),
|
||||
num_double_slots_(0),
|
||||
info_(info),
|
||||
graph_(graph),
|
||||
instructions_(32, graph->zone()),
|
||||
pointer_maps_(8, graph->zone()),
|
||||
inlined_closures_(1, graph->zone()) { }
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
LConstantOperand* DefineConstantOperand(HConstant* constant);
|
||||
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
|
||||
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
|
||||
: LChunkBase(info, graph),
|
||||
num_double_slots_(0) { }
|
||||
|
||||
int GetNextSpillIndex(bool is_double);
|
||||
LOperand* GetNextSpillSlot(bool is_double);
|
||||
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
int num_double_slots() const { return num_double_slots_; }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
void AddGapMove(int index, LOperand* from, LOperand* to);
|
||||
LGap* GetGapAt(int index) const;
|
||||
bool IsGapAt(int index) const;
|
||||
int NearestGapPos(int index) const;
|
||||
void MarkEmptyBlocks();
|
||||
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
||||
LLabel* GetLabel(int block_id) const {
|
||||
HBasicBlock* block = graph_->blocks()->at(block_id);
|
||||
int first_instruction = block->first_instruction_index();
|
||||
return LLabel::cast(instructions_[first_instruction]);
|
||||
}
|
||||
int LookupDestination(int block_id) const {
|
||||
LLabel* cur = GetLabel(block_id);
|
||||
while (cur->replacement() != NULL) {
|
||||
cur = cur->replacement();
|
||||
}
|
||||
return cur->block_id();
|
||||
}
|
||||
Label* GetAssemblyLabel(int block_id) const {
|
||||
LLabel* label = GetLabel(block_id);
|
||||
ASSERT(!label->HasReplacement());
|
||||
return label->label();
|
||||
}
|
||||
|
||||
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
||||
return &inlined_closures_;
|
||||
}
|
||||
|
||||
void AddInlinedClosure(Handle<JSFunction> closure) {
|
||||
inlined_closures_.Add(closure, zone());
|
||||
}
|
||||
|
||||
Zone* zone() const { return graph_->zone(); }
|
||||
|
||||
private:
|
||||
int spill_slot_count_;
|
||||
int num_double_slots_;
|
||||
CompilationInfo* info_;
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
||||
|
146
src/lithium.cc
146
src/lithium.cc
@ -27,6 +27,19 @@
|
||||
|
||||
#include "v8.h"
|
||||
#include "lithium.h"
|
||||
#include "scopes.h"
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#include "ia32/lithium-ia32.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#include "x64/lithium-x64.h"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#include "arm/lithium-arm.h"
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
#include "mips/lithium-mips.h"
|
||||
#else
|
||||
#error "Unknown architecture."
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -240,4 +253,137 @@ int ElementsKindToShiftSize(ElementsKind elements_kind) {
|
||||
}
|
||||
|
||||
|
||||
LLabel* LChunkBase::GetLabel(int block_id) const {
|
||||
HBasicBlock* block = graph_->blocks()->at(block_id);
|
||||
int first_instruction = block->first_instruction_index();
|
||||
return LLabel::cast(instructions_[first_instruction]);
|
||||
}
|
||||
|
||||
|
||||
int LChunkBase::LookupDestination(int block_id) const {
|
||||
LLabel* cur = GetLabel(block_id);
|
||||
while (cur->replacement() != NULL) {
|
||||
cur = cur->replacement();
|
||||
}
|
||||
return cur->block_id();
|
||||
}
|
||||
|
||||
Label* LChunkBase::GetAssemblyLabel(int block_id) const {
|
||||
LLabel* label = GetLabel(block_id);
|
||||
ASSERT(!label->HasReplacement());
|
||||
return label->label();
|
||||
}
|
||||
|
||||
void LChunkBase::MarkEmptyBlocks() {
|
||||
HPhase phase("L_Mark empty blocks", this);
|
||||
for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
||||
HBasicBlock* block = graph()->blocks()->at(i);
|
||||
int first = block->first_instruction_index();
|
||||
int last = block->last_instruction_index();
|
||||
LInstruction* first_instr = instructions()->at(first);
|
||||
LInstruction* last_instr = instructions()->at(last);
|
||||
|
||||
LLabel* label = LLabel::cast(first_instr);
|
||||
if (last_instr->IsGoto()) {
|
||||
LGoto* goto_instr = LGoto::cast(last_instr);
|
||||
if (label->IsRedundant() &&
|
||||
!label->is_loop_header()) {
|
||||
bool can_eliminate = true;
|
||||
for (int i = first + 1; i < last && can_eliminate; ++i) {
|
||||
LInstruction* cur = instructions()->at(i);
|
||||
if (cur->IsGap()) {
|
||||
LGap* gap = LGap::cast(cur);
|
||||
if (!gap->IsRedundant()) {
|
||||
can_eliminate = false;
|
||||
}
|
||||
} else {
|
||||
can_eliminate = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_eliminate) {
|
||||
label->set_replacement(GetLabel(goto_instr->block_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LChunkBase::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
||||
LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
|
||||
int index = -1;
|
||||
if (instr->IsControl()) {
|
||||
instructions_.Add(gap, zone());
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
} else {
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
instructions_.Add(gap, zone());
|
||||
}
|
||||
if (instr->HasPointerMap()) {
|
||||
pointer_maps_.Add(instr->pointer_map(), zone());
|
||||
instr->pointer_map()->set_lithium_position(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LConstantOperand* LChunkBase::DefineConstantOperand(HConstant* constant) {
|
||||
return LConstantOperand::Create(constant->id(), zone());
|
||||
}
|
||||
|
||||
|
||||
int LChunkBase::GetParameterStackSlot(int index) const {
|
||||
// The receiver is at index 0, the first parameter at index 1, so we
|
||||
// shift all parameter indexes down by the number of parameters, and
|
||||
// make sure they end up negative so they are distinguishable from
|
||||
// spill slots.
|
||||
int result = index - info()->scope()->num_parameters() - 1;
|
||||
ASSERT(result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// A parameter relative to ebp in the arguments stub.
|
||||
int LChunkBase::ParameterAt(int index) {
|
||||
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
return (1 + info()->scope()->num_parameters() - index) *
|
||||
kPointerSize;
|
||||
}
|
||||
|
||||
|
||||
LGap* LChunkBase::GetGapAt(int index) const {
|
||||
return LGap::cast(instructions_[index]);
|
||||
}
|
||||
|
||||
|
||||
bool LChunkBase::IsGapAt(int index) const {
|
||||
return instructions_[index]->IsGap();
|
||||
}
|
||||
|
||||
|
||||
int LChunkBase::NearestGapPos(int index) const {
|
||||
while (!IsGapAt(index)) index--;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void LChunkBase::AddGapMove(int index, LOperand* from, LOperand* to) {
|
||||
GetGapAt(index)->GetOrCreateParallelMove(
|
||||
LGap::START, zone())->AddMove(from, to, zone());
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> LChunkBase::LookupLiteral(LConstantOperand* operand) const {
|
||||
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
|
||||
}
|
||||
|
||||
|
||||
Representation LChunkBase::LookupLiteralRepresentation(
|
||||
LConstantOperand* operand) const {
|
||||
return graph_->LookupValue(operand->index())->representation();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -622,6 +622,64 @@ class DeepIterator BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
class LGap;
|
||||
class LLabel;
|
||||
|
||||
// Superclass providing data and behavior common to all the
|
||||
// arch-specific LChunk classes.
|
||||
class LChunkBase: public ZoneObject {
|
||||
public:
|
||||
LChunkBase(CompilationInfo* info, HGraph* graph)
|
||||
: spill_slot_count_(0),
|
||||
info_(info),
|
||||
graph_(graph),
|
||||
instructions_(32, graph->zone()),
|
||||
pointer_maps_(8, graph->zone()),
|
||||
inlined_closures_(1, graph->zone()) { }
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
LConstantOperand* DefineConstantOperand(HConstant* constant);
|
||||
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
|
||||
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
|
||||
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
void AddGapMove(int index, LOperand* from, LOperand* to);
|
||||
LGap* GetGapAt(int index) const;
|
||||
bool IsGapAt(int index) const;
|
||||
int NearestGapPos(int index) const;
|
||||
void MarkEmptyBlocks();
|
||||
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
||||
LLabel* GetLabel(int block_id) const;
|
||||
int LookupDestination(int block_id) const;
|
||||
Label* GetAssemblyLabel(int block_id) const;
|
||||
|
||||
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
||||
return &inlined_closures_;
|
||||
}
|
||||
|
||||
void AddInlinedClosure(Handle<JSFunction> closure) {
|
||||
inlined_closures_.Add(closure, zone());
|
||||
}
|
||||
|
||||
Zone* zone() const { return info_->zone(); }
|
||||
|
||||
protected:
|
||||
int spill_slot_count_;
|
||||
|
||||
private:
|
||||
CompilationInfo* info_;
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
||||
int ElementsKindToShiftSize(ElementsKind elements_kind);
|
||||
|
||||
|
||||
|
@ -407,16 +407,6 @@ void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
LChunk::LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: spill_slot_count_(0),
|
||||
info_(info),
|
||||
graph_(graph),
|
||||
instructions_(32, graph->zone()),
|
||||
pointer_maps_(8, graph->zone()),
|
||||
inlined_closures_(1, graph->zone()) {
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetNextSpillIndex(bool is_double) {
|
||||
// Skip a slot if for a double-width slot.
|
||||
if (is_double) spill_slot_count_++;
|
||||
@ -434,117 +424,6 @@ LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::MarkEmptyBlocks() {
|
||||
HPhase phase("L_Mark empty blocks", this);
|
||||
for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
||||
HBasicBlock* block = graph()->blocks()->at(i);
|
||||
int first = block->first_instruction_index();
|
||||
int last = block->last_instruction_index();
|
||||
LInstruction* first_instr = instructions()->at(first);
|
||||
LInstruction* last_instr = instructions()->at(last);
|
||||
|
||||
LLabel* label = LLabel::cast(first_instr);
|
||||
if (last_instr->IsGoto()) {
|
||||
LGoto* goto_instr = LGoto::cast(last_instr);
|
||||
if (label->IsRedundant() &&
|
||||
!label->is_loop_header()) {
|
||||
bool can_eliminate = true;
|
||||
for (int i = first + 1; i < last && can_eliminate; ++i) {
|
||||
LInstruction* cur = instructions()->at(i);
|
||||
if (cur->IsGap()) {
|
||||
LGap* gap = LGap::cast(cur);
|
||||
if (!gap->IsRedundant()) {
|
||||
can_eliminate = false;
|
||||
}
|
||||
} else {
|
||||
can_eliminate = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_eliminate) {
|
||||
label->set_replacement(GetLabel(goto_instr->block_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
||||
LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
|
||||
int index = -1;
|
||||
if (instr->IsControl()) {
|
||||
instructions_.Add(gap, zone());
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
} else {
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
instructions_.Add(gap, zone());
|
||||
}
|
||||
if (instr->HasPointerMap()) {
|
||||
pointer_maps_.Add(instr->pointer_map(), zone());
|
||||
instr->pointer_map()->set_lithium_position(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
|
||||
return LConstantOperand::Create(constant->id(), zone());
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetParameterStackSlot(int index) const {
|
||||
// The receiver is at index 0, the first parameter at index 1, so we
|
||||
// shift all parameter indexes down by the number of parameters, and
|
||||
// make sure they end up negative so they are distinguishable from
|
||||
// spill slots.
|
||||
int result = index - info()->scope()->num_parameters() - 1;
|
||||
ASSERT(result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A parameter relative to ebp in the arguments stub.
|
||||
int LChunk::ParameterAt(int index) {
|
||||
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
return (1 + info()->scope()->num_parameters() - index) *
|
||||
kPointerSize;
|
||||
}
|
||||
|
||||
|
||||
LGap* LChunk::GetGapAt(int index) const {
|
||||
return LGap::cast(instructions_[index]);
|
||||
}
|
||||
|
||||
|
||||
bool LChunk::IsGapAt(int index) const {
|
||||
return instructions_[index]->IsGap();
|
||||
}
|
||||
|
||||
|
||||
int LChunk::NearestGapPos(int index) const {
|
||||
while (!IsGapAt(index)) index--;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
|
||||
GetGapAt(index)->GetOrCreateParallelMove(
|
||||
LGap::START, zone())->AddMove(from, to, zone());
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
|
||||
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
|
||||
}
|
||||
|
||||
|
||||
Representation LChunk::LookupLiteralRepresentation(
|
||||
LConstantOperand* operand) const {
|
||||
return graph_->LookupValue(operand->index())->representation();
|
||||
}
|
||||
|
||||
|
||||
LChunk* LChunkBuilder::Build() {
|
||||
ASSERT(is_unused());
|
||||
chunk_ = new(zone()) LChunk(info(), graph());
|
||||
|
@ -2188,65 +2188,13 @@ class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
|
||||
class LChunkBuilder;
|
||||
class LChunk: public ZoneObject {
|
||||
class LChunk: public LChunkBase {
|
||||
public:
|
||||
explicit LChunk(CompilationInfo* info, HGraph* graph);
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
LConstantOperand* DefineConstantOperand(HConstant* constant);
|
||||
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
|
||||
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
|
||||
explicit LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: LChunkBase(info, graph) { }
|
||||
|
||||
int GetNextSpillIndex(bool is_double);
|
||||
LOperand* GetNextSpillSlot(bool is_double);
|
||||
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
void AddGapMove(int index, LOperand* from, LOperand* to);
|
||||
LGap* GetGapAt(int index) const;
|
||||
bool IsGapAt(int index) const;
|
||||
int NearestGapPos(int index) const;
|
||||
void MarkEmptyBlocks();
|
||||
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
||||
LLabel* GetLabel(int block_id) const {
|
||||
HBasicBlock* block = graph_->blocks()->at(block_id);
|
||||
int first_instruction = block->first_instruction_index();
|
||||
return LLabel::cast(instructions_[first_instruction]);
|
||||
}
|
||||
int LookupDestination(int block_id) const {
|
||||
LLabel* cur = GetLabel(block_id);
|
||||
while (cur->replacement() != NULL) {
|
||||
cur = cur->replacement();
|
||||
}
|
||||
return cur->block_id();
|
||||
}
|
||||
Label* GetAssemblyLabel(int block_id) const {
|
||||
LLabel* label = GetLabel(block_id);
|
||||
ASSERT(!label->HasReplacement());
|
||||
return label->label();
|
||||
}
|
||||
|
||||
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
||||
return &inlined_closures_;
|
||||
}
|
||||
|
||||
void AddInlinedClosure(Handle<JSFunction> closure) {
|
||||
inlined_closures_.Add(closure, zone());
|
||||
}
|
||||
|
||||
Zone* zone() const { return graph_->zone(); }
|
||||
|
||||
private:
|
||||
int spill_slot_count_;
|
||||
CompilationInfo* info_;
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -376,42 +376,6 @@ LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::MarkEmptyBlocks() {
|
||||
HPhase phase("L_Mark empty blocks", this);
|
||||
for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
||||
HBasicBlock* block = graph()->blocks()->at(i);
|
||||
int first = block->first_instruction_index();
|
||||
int last = block->last_instruction_index();
|
||||
LInstruction* first_instr = instructions()->at(first);
|
||||
LInstruction* last_instr = instructions()->at(last);
|
||||
|
||||
LLabel* label = LLabel::cast(first_instr);
|
||||
if (last_instr->IsGoto()) {
|
||||
LGoto* goto_instr = LGoto::cast(last_instr);
|
||||
if (label->IsRedundant() &&
|
||||
!label->is_loop_header()) {
|
||||
bool can_eliminate = true;
|
||||
for (int i = first + 1; i < last && can_eliminate; ++i) {
|
||||
LInstruction* cur = instructions()->at(i);
|
||||
if (cur->IsGap()) {
|
||||
LGap* gap = LGap::cast(cur);
|
||||
if (!gap->IsRedundant()) {
|
||||
can_eliminate = false;
|
||||
}
|
||||
} else {
|
||||
can_eliminate = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_eliminate) {
|
||||
label->set_replacement(GetLabel(goto_instr->block_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LStoreNamedField::PrintDataTo(StringStream* stream) {
|
||||
object()->PrintTo(stream);
|
||||
stream->Add(".");
|
||||
@ -463,81 +427,6 @@ void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
||||
LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
|
||||
int index = -1;
|
||||
if (instr->IsControl()) {
|
||||
instructions_.Add(gap, zone());
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
} else {
|
||||
index = instructions_.length();
|
||||
instructions_.Add(instr, zone());
|
||||
instructions_.Add(gap, zone());
|
||||
}
|
||||
if (instr->HasPointerMap()) {
|
||||
pointer_maps_.Add(instr->pointer_map(), zone());
|
||||
instr->pointer_map()->set_lithium_position(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
|
||||
return LConstantOperand::Create(constant->id(), zone());
|
||||
}
|
||||
|
||||
|
||||
int LChunk::GetParameterStackSlot(int index) const {
|
||||
// The receiver is at index 0, the first parameter at index 1, so we
|
||||
// shift all parameter indexes down by the number of parameters, and
|
||||
// make sure they end up negative so they are distinguishable from
|
||||
// spill slots.
|
||||
int result = index - info()->scope()->num_parameters() - 1;
|
||||
ASSERT(result < 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A parameter relative to ebp in the arguments stub.
|
||||
int LChunk::ParameterAt(int index) {
|
||||
ASSERT(-1 <= index); // -1 is the receiver.
|
||||
return (1 + info()->scope()->num_parameters() - index) *
|
||||
kPointerSize;
|
||||
}
|
||||
|
||||
|
||||
LGap* LChunk::GetGapAt(int index) const {
|
||||
return LGap::cast(instructions_[index]);
|
||||
}
|
||||
|
||||
|
||||
bool LChunk::IsGapAt(int index) const {
|
||||
return instructions_[index]->IsGap();
|
||||
}
|
||||
|
||||
|
||||
int LChunk::NearestGapPos(int index) const {
|
||||
while (!IsGapAt(index)) index--;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
|
||||
GetGapAt(index)->GetOrCreateParallelMove(
|
||||
LGap::START, zone())->AddMove(from, to, zone());
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
|
||||
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
|
||||
}
|
||||
|
||||
|
||||
Representation LChunk::LookupLiteralRepresentation(
|
||||
LConstantOperand* operand) const {
|
||||
return graph_->LookupValue(operand->index())->representation();
|
||||
}
|
||||
|
||||
|
||||
LChunk* LChunkBuilder::Build() {
|
||||
ASSERT(is_unused());
|
||||
chunk_ = new(zone()) LChunk(info(), graph());
|
||||
|
@ -2178,71 +2178,13 @@ class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
|
||||
|
||||
|
||||
class LChunkBuilder;
|
||||
class LChunk: public ZoneObject {
|
||||
class LChunk: public LChunkBase {
|
||||
public:
|
||||
LChunk(CompilationInfo* info, HGraph* graph)
|
||||
: spill_slot_count_(0),
|
||||
info_(info),
|
||||
graph_(graph),
|
||||
instructions_(32, graph->zone()),
|
||||
pointer_maps_(8, graph->zone()),
|
||||
inlined_closures_(1, graph->zone()) { }
|
||||
|
||||
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
|
||||
LConstantOperand* DefineConstantOperand(HConstant* constant);
|
||||
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
|
||||
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
|
||||
: LChunkBase(info, graph) { }
|
||||
|
||||
int GetNextSpillIndex(bool is_double);
|
||||
LOperand* GetNextSpillSlot(bool is_double);
|
||||
|
||||
int ParameterAt(int index);
|
||||
int GetParameterStackSlot(int index) const;
|
||||
int spill_slot_count() const { return spill_slot_count_; }
|
||||
CompilationInfo* info() const { return info_; }
|
||||
HGraph* graph() const { return graph_; }
|
||||
const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
|
||||
void AddGapMove(int index, LOperand* from, LOperand* to);
|
||||
LGap* GetGapAt(int index) const;
|
||||
bool IsGapAt(int index) const;
|
||||
int NearestGapPos(int index) const;
|
||||
void MarkEmptyBlocks();
|
||||
const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
|
||||
LLabel* GetLabel(int block_id) const {
|
||||
HBasicBlock* block = graph_->blocks()->at(block_id);
|
||||
int first_instruction = block->first_instruction_index();
|
||||
return LLabel::cast(instructions_[first_instruction]);
|
||||
}
|
||||
int LookupDestination(int block_id) const {
|
||||
LLabel* cur = GetLabel(block_id);
|
||||
while (cur->replacement() != NULL) {
|
||||
cur = cur->replacement();
|
||||
}
|
||||
return cur->block_id();
|
||||
}
|
||||
Label* GetAssemblyLabel(int block_id) const {
|
||||
LLabel* label = GetLabel(block_id);
|
||||
ASSERT(!label->HasReplacement());
|
||||
return label->label();
|
||||
}
|
||||
|
||||
const ZoneList<Handle<JSFunction> >* inlined_closures() const {
|
||||
return &inlined_closures_;
|
||||
}
|
||||
|
||||
void AddInlinedClosure(Handle<JSFunction> closure) {
|
||||
inlined_closures_.Add(closure, zone());
|
||||
}
|
||||
|
||||
Zone* zone() const { return graph_->zone(); }
|
||||
|
||||
private:
|
||||
int spill_slot_count_;
|
||||
CompilationInfo* info_;
|
||||
HGraph* const graph_;
|
||||
ZoneList<LInstruction*> instructions_;
|
||||
ZoneList<LPointerMap*> pointer_maps_;
|
||||
ZoneList<Handle<JSFunction> > inlined_closures_;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user