namespace v8 {
namespace internal {
+LOsrEntry::LOsrEntry() {
+ for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
+ register_spills_[i] = NULL;
+ }
+ for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
+ double_register_spills_[i] = NULL;
+ }
+}
+
+
+void LOsrEntry::MarkSpilledRegister(int allocation_index,
+ LOperand* spill_operand) {
+ ASSERT(spill_operand->IsStackSlot());
+ ASSERT(register_spills_[allocation_index] == NULL);
+ register_spills_[allocation_index] = spill_operand;
+}
+
+
+void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
+ LOperand* spill_operand) {
+ ASSERT(spill_operand->IsDoubleStackSlot());
+ ASSERT(double_register_spills_[allocation_index] == NULL);
+ double_register_spills_[allocation_index] = spill_operand;
+}
+
+
+void LOsrEntry::CompileToNative(LCodeGen* generator) {
+ UNIMPLEMENTED();
+ // Implement in lithium-codegen-x64.cc.
+}
+
+
+void LInstruction::PrintTo(StringStream* stream) {
+ stream->Add("%s ", this->Mnemonic());
+ if (HasResult()) {
+ LTemplateInstruction<1>::cast(this)->result()->PrintTo(stream);
+ stream->Add(" ");
+ }
+ PrintDataTo(stream);
+
+ if (HasEnvironment()) {
+ stream->Add(" ");
+ // environment()->PrintTo(stream);
+ }
+
+ if (HasPointerMap()) {
+ stream->Add(" ");
+ //pointer_map()->PrintTo(stream);
+ }
+}
+
+
+void LLabel::PrintDataTo(StringStream* stream) {
+ LGap::PrintDataTo(stream);
+ LLabel* rep = replacement();
+ if (rep != NULL) {
+ stream->Add(" Dead block replaced with B%d", rep->block_id());
+ }
+}
+
+
bool LGap::IsRedundant() const {
for (int i = 0; i < 4; i++) {
if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
}
-void LGap::PrintDataTo(StringStream* stream) const {
+void LGap::PrintDataTo(StringStream* stream) {
for (int i = 0; i < 4; i++) {
stream->Add("(");
if (parallel_moves_[i] != NULL) {
}
+void LGoto::PrintDataTo(StringStream* stream) {
+ stream->Add("B%d", block_id());
+}
+
+
LChunk* LChunkBuilder::Build() {
ASSERT(is_unused());
chunk_ = new LChunk(graph());
// Type hierarchy:
//
// LInstruction
+// LDeoptimize
// LGap
+// LLabel
+// LGoto
+// LLazyBailout
+// LOsrEntry
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
- V(Gap)
+ V(Deoptimize) \
+ V(Gap) \
+ V(Goto) \
+ V(Label) \
+ V(LazyBailout) \
+ V(OsrEntry)
#define DECLARE_INSTRUCTION(type) \
: hydrogen_value_(NULL) { }
virtual ~LInstruction() { }
- // Predicates should be generated by macro as in lithium-ia32.h.
- virtual bool IsLabel() const {
- UNIMPLEMENTED();
- return false;
- }
- virtual bool IsOsrEntry() const {
- UNIMPLEMENTED();
- return false;
- }
-
virtual void CompileToNative(LCodeGen* generator) = 0;
virtual const char* Mnemonic() const = 0;
- virtual void PrintTo(StringStream* stream) const;
- virtual void PrintDataTo(StringStream* stream) const { }
+ virtual void PrintTo(StringStream* stream);
+ virtual void PrintDataTo(StringStream* stream) { }
// Declare virtual type testers.
#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
LPointerMap* pointer_map() const { return pointer_map_.get(); }
bool HasPointerMap() const { return pointer_map_.is_set(); }
- void set_result(LOperand* operand) { result_.set(operand); }
- LOperand* result() const { return result_.get(); }
- bool HasResult() const { return result_.is_set(); }
+ virtual bool HasResult() const = 0;
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
HValue* hydrogen_value() const { return hydrogen_value_; }
private:
SetOncePointer<LEnvironment> environment_;
SetOncePointer<LPointerMap> pointer_map_;
- SetOncePointer<LOperand> result_;
HValue* hydrogen_value_;
SetOncePointer<LEnvironment> deoptimization_environment_;
};
-class LGap: public LInstruction {
+template <int Result>
+class LTemplateInstruction: public LInstruction { };
+
+
+template<>
+class LTemplateInstruction<0>: public LInstruction {
+ virtual bool HasResult() const { return false; }
+};
+
+
+template<>
+class LTemplateInstruction<1>: public LInstruction {
+ public:
+ static LTemplateInstruction<1>* cast(LInstruction* instr) {
+ ASSERT(instr->HasResult());
+ return reinterpret_cast<LTemplateInstruction<1>*>(instr);
+ }
+ void set_result(LOperand* operand) { result_.set(operand); }
+ LOperand* result() const { return result_.get(); }
+ virtual bool HasResult() const { return result_.is_set(); }
+ private:
+ SetOncePointer<LOperand> result_;
+};
+
+
+class LGap: public LTemplateInstruction<0> {
public:
explicit LGap(HBasicBlock* block)
: block_(block) {
}
DECLARE_CONCRETE_INSTRUCTION(Gap, "gap")
- virtual void PrintDataTo(StringStream* stream) const;
+ virtual void PrintDataTo(StringStream* stream);
bool IsRedundant() const;
};
+class LGoto: public LTemplateInstruction<0> {
+ public:
+ LGoto(int block_id, bool include_stack_check = false)
+ : block_id_(block_id), include_stack_check_(include_stack_check) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
+ virtual void PrintDataTo(StringStream* stream);
+ virtual bool IsControl() const { return true; }
+
+ int block_id() const { return block_id_; }
+ bool include_stack_check() const { return include_stack_check_; }
+
+ private:
+ int block_id_;
+ bool include_stack_check_;
+};
+
+
+class LLazyBailout: public LTemplateInstruction<0> {
+ public:
+ LLazyBailout() : gap_instructions_size_(0) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
+
+ void set_gap_instructions_size(int gap_instructions_size) {
+ gap_instructions_size_ = gap_instructions_size;
+ }
+ int gap_instructions_size() { return gap_instructions_size_; }
+
+ private:
+ int gap_instructions_size_;
+};
+
+
+class LDeoptimize: public LTemplateInstruction<0> {
+ public:
+ DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+};
+
+
class LLabel: public LGap {
public:
- explicit LLabel(HBasicBlock* block) : LGap(block) { }
+ explicit LLabel(HBasicBlock* block)
+ : LGap(block), replacement_(NULL) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(Label, "label")
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ int block_id() const { return block()->block_id(); }
+ bool is_loop_header() const { return block()->IsLoopHeader(); }
+ Label* label() { return &label_; }
+ LLabel* replacement() const { return replacement_; }
+ void set_replacement(LLabel* label) { replacement_ = label; }
+ bool HasReplacement() const { return replacement_ != NULL; }
private:
Label label_;
};
-class LOsrEntry: public LInstruction {
+class LOsrEntry: public LTemplateInstruction<0> {
public:
- // Function could be generated by a macro as in lithium-ia32.h.
- static LOsrEntry* cast(LInstruction* instr) {
- UNIMPLEMENTED();
- return NULL;
- }
+ LOsrEntry();
- LOperand** SpilledRegisterArray() {
- UNIMPLEMENTED();
- return NULL;
- }
- LOperand** SpilledDoubleRegisterArray() {
- UNIMPLEMENTED();
- return NULL;
- }
+ DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
- void MarkSpilledRegister(int allocation_index, LOperand* spill_operand) {
- UNIMPLEMENTED();
- }
+ LOperand** SpilledRegisterArray() { return register_spills_; }
+ LOperand** SpilledDoubleRegisterArray() { return double_register_spills_; }
+
+ void MarkSpilledRegister(int allocation_index, LOperand* spill_operand);
void MarkSpilledDoubleRegister(int allocation_index,
- LOperand* spill_operand) {
- UNIMPLEMENTED();
- }
+ LOperand* spill_operand);
private:
// Arrays of spill slot operands for registers with an assigned spill