Chromium Code Reviews| Index: src/mips/lithium-codegen-mips.h |
| diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h |
| index 2aec68456d164a92e964c639b6af9185272443f3..8fcaec251be6d5e10bcb23ae46cd3e578b0e0f4e 100644 |
| --- a/src/mips/lithium-codegen-mips.h |
| +++ b/src/mips/lithium-codegen-mips.h |
| @@ -29,35 +29,397 @@ |
| #define V8_MIPS_LITHIUM_CODEGEN_MIPS_H_ |
| #include "mips/lithium-mips.h" |
| - |
| +#include "mips/lithium-gap-resolver-mips.h" |
| #include "deoptimizer.h" |
| #include "safepoint-table.h" |
| #include "scopes.h" |
| -// Note: this file was taken from the X64 version. ARM has a partially working |
| -// lithium implementation, but for now it is not ported to mips. |
| - |
| namespace v8 { |
| namespace internal { |
| // Forward declarations. |
| class LDeferredCode; |
| +class SafepointGenerator; |
| class LCodeGen BASE_EMBEDDED { |
| public: |
| - LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) { } |
| + LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) |
| + : chunk_(chunk), |
| + masm_(assembler), |
| + info_(info), |
| + current_block_(-1), |
| + current_instruction_(-1), |
| + instructions_(chunk->instructions()), |
| + deoptimizations_(4), |
| + deopt_jump_table_(4), |
| + deoptimization_literals_(8), |
| + inlined_function_count_(0), |
| + scope_(info->scope()), |
| + status_(UNUSED), |
| + deferred_(8), |
| + osr_pc_offset_(-1), |
| + resolver_(this), |
| + expected_safepoint_kind_(Safepoint::kSimple) { |
| + PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| + } |
| + |
| + |
| + // Simple accessors. |
| + MacroAssembler* masm() const { return masm_; } |
| + CompilationInfo* info() const { return info_; } |
| + Isolate* isolate() const { return info_->isolate(); } |
| + Factory* factory() const { return isolate()->factory(); } |
| + Heap* heap() const { return isolate()->heap(); } |
| + |
| + // Support for converting LOperands to assembler types. |
| + // LOperand must be a register. |
| + Register ToRegister(LOperand* op) const; |
| + |
| + // LOperand is loaded into scratch, unless already a register. |
| + Register EmitLoadRegister(LOperand* op, Register scratch); |
| + |
| + // LOperand must be a double register. |
| + DoubleRegister ToDoubleRegister(LOperand* op) const; |
| + |
| + // LOperand is loaded into dbl_scratch, unless already a double register. |
| + DoubleRegister EmitLoadDoubleRegister(LOperand* op, |
| + FloatRegister flt_scratch, |
| + DoubleRegister dbl_scratch); |
| + int ToInteger32(LConstantOperand* op) const; |
| + Operand ToOperand(LOperand* op); |
| + MemOperand ToMemOperand(LOperand* op) const; |
| + // Returns a MemOperand pointing to the high word of a DoubleStackSlot. |
| + MemOperand ToHighMemOperand(LOperand* op) const; |
| // Try to generate code for the entire chunk, but it may fail if the |
| // chunk contains constructs we cannot handle. Returns true if the |
| // code generation attempt succeeded. |
| - bool GenerateCode() { |
| - UNIMPLEMENTED(); |
| - return false; |
| - } |
| + bool GenerateCode(); |
| // Finish the code by setting stack height, safepoint, and bailout |
| // information on it. |
| - void FinishCode(Handle<Code> code) { UNIMPLEMENTED(); } |
| + void FinishCode(Handle<Code> code); |
| + |
| + // Deferred code support. |
| + template<int T> |
| + void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
| + Token::Value op); |
| + void DoDeferredNumberTagD(LNumberTagD* instr); |
| + void DoDeferredNumberTagI(LNumberTagI* instr); |
| + void DoDeferredTaggedToI(LTaggedToI* instr); |
| + void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); |
| + void DoDeferredStackCheck(LStackCheck* instr); |
| + void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); |
| + void DoDeferredStringCharFromCode(LStringCharFromCode* instr); |
| + void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| + Label* map_check); |
| + |
| + // Parallel move support. |
| + void DoParallelMove(LParallelMove* move); |
| + void DoGap(LGap* instr); |
| + |
| + // Emit frame translation commands for an environment. |
| + void WriteTranslation(LEnvironment* environment, Translation* translation); |
| + |
| + // Declare methods that deal with the individual node types. |
| +#define DECLARE_DO(type) void Do##type(L##type* node); |
| + LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) |
| +#undef DECLARE_DO |
| + |
| + private: |
| + enum Status { |
| + UNUSED, |
| + GENERATING, |
| + DONE, |
| + ABORTED |
| + }; |
| + |
| + bool is_unused() const { return status_ == UNUSED; } |
| + bool is_generating() const { return status_ == GENERATING; } |
| + bool is_done() const { return status_ == DONE; } |
| + bool is_aborted() const { return status_ == ABORTED; } |
| + |
| + int strict_mode_flag() const { |
| + return info()->is_strict_mode() ? kStrictMode : kNonStrictMode; |
| + } |
| + |
| + LChunk* chunk() const { return chunk_; } |
| + Scope* scope() const { return scope_; } |
| + HGraph* graph() const { return chunk_->graph(); } |
| + |
| + Register scratch0() { return lithiumScratchReg; } |
| + Register scratch1() { return lithiumScratchReg2; } |
| + DoubleRegister double_scratch0() { return lithiumScratchDouble; } |
| + |
| + int GetNextEmittedBlock(int block); |
| + LInstruction* GetNextInstruction(); |
| + |
| + void EmitClassOfTest(Label* if_true, |
| + Label* if_false, |
| + Handle<String> class_name, |
| + Register input, |
| + Register temporary, |
| + Register temporary2); |
| + |
| + int GetStackSlotCount() const { return chunk()->spill_slot_count(); } |
| + int GetParameterCount() const { return scope()->num_parameters(); } |
| + |
| + void Abort(const char* format, ...); |
| + void Comment(const char* format, ...); |
| + |
| + void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } |
| + |
| + // Code generation passes. Returns true if code generation should |
| + // continue. |
| + bool GeneratePrologue(); |
| + bool GenerateBody(); |
| + bool GenerateDeferredCode(); |
| + bool GenerateDeoptJumpTable(); |
| + bool GenerateSafepointTable(); |
| + |
| + enum SafepointMode { |
| + RECORD_SIMPLE_SAFEPOINT, |
| + RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS |
| + }; |
| + |
| + void CallCode(Handle<Code> code, |
| + RelocInfo::Mode mode, |
| + LInstruction* instr); |
| + |
| + void CallCodeGeneric(Handle<Code> code, |
| + RelocInfo::Mode mode, |
| + LInstruction* instr, |
| + SafepointMode safepoint_mode); |
| + |
| + void CallRuntime(const Runtime::Function* function, |
| + int num_arguments, |
| + LInstruction* instr); |
| + |
| + void CallRuntime(Runtime::FunctionId id, |
| + int num_arguments, |
| + LInstruction* instr) { |
| + const Runtime::Function* function = Runtime::FunctionForId(id); |
| + CallRuntime(function, num_arguments, instr); |
| + } |
| + |
| + void CallRuntimeFromDeferred(Runtime::FunctionId id, |
| + int argc, |
| + LInstruction* instr); |
| + |
| + // Generate a direct call to a known function. Expects the function |
| + // to be in edi. |
|
fschneider
2011/10/18 14:27:58
Wrong register in comment: Function expected in a1
Paul Lind
2011/10/19 02:18:27
Done.
|
| + void CallKnownFunction(Handle<JSFunction> function, |
| + int arity, |
| + LInstruction* instr, |
| + CallKind call_kind); |
| + |
| + void LoadHeapObject(Register result, Handle<HeapObject> object); |
| + |
| + void RegisterLazyDeoptimization(LInstruction* instr, |
| + SafepointMode safepoint_mode); |
| + |
| + void RegisterEnvironmentForDeoptimization(LEnvironment* environment); |
| + void DeoptimizeIf(Condition cc, |
| + LEnvironment* environment, |
| + Register src1, |
| + const Operand& src2); |
| + |
| + void AddToTranslation(Translation* translation, |
| + LOperand* op, |
| + bool is_tagged); |
| + void PopulateDeoptimizationData(Handle<Code> code); |
| + int DefineDeoptimizationLiteral(Handle<Object> literal); |
| + |
| + void PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| + |
| + Register ToRegister(int index) const; |
| + DoubleRegister ToDoubleRegister(int index) const; |
| + |
| + // Specific math operations - used from DoUnaryMathOperation. |
| + void EmitIntegerMathAbs(LUnaryMathOperation* instr); |
| + void DoMathAbs(LUnaryMathOperation* instr); |
| + void DoMathFloor(LUnaryMathOperation* instr); |
| + void DoMathRound(LUnaryMathOperation* instr); |
| + void DoMathSqrt(LUnaryMathOperation* instr); |
| + void DoMathPowHalf(LUnaryMathOperation* instr); |
| + void DoMathLog(LUnaryMathOperation* instr); |
| + void DoMathCos(LUnaryMathOperation* instr); |
| + void DoMathSin(LUnaryMathOperation* instr); |
| + |
| + // Support for recording safepoint and position information. |
| + void RecordSafepoint(LPointerMap* pointers, |
| + Safepoint::Kind kind, |
| + int arguments, |
| + int deoptimization_index); |
| + void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); |
| + void RecordSafepoint(int deoptimization_index); |
| + void RecordSafepointWithRegisters(LPointerMap* pointers, |
| + int arguments, |
| + int deoptimization_index); |
| + void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers, |
| + int arguments, |
| + int deoptimization_index); |
| + void RecordPosition(int position); |
| + int LastSafepointEnd() { |
| + return static_cast<int>(safepoints_.GetPcAfterGap()); |
| + } |
| + |
| + static Condition TokenToCondition(Token::Value op, bool is_unsigned); |
| + void EmitGoto(int block); |
| + void EmitBranch(int left_block, |
| + int right_block, |
| + Condition cc, |
| + Register src1, |
| + const Operand& src2); |
| + void EmitBranchF(int left_block, |
| + int right_block, |
| + Condition cc, |
| + FPURegister src1, |
| + FPURegister src2); |
| + void EmitCmpI(LOperand* left, LOperand* right); |
| + void EmitNumberUntagD(Register input, |
| + DoubleRegister result, |
| + bool deoptimize_on_undefined, |
| + LEnvironment* env); |
| + |
| + // Emits optimized code for typeof x == "y". Modifies input register. |
| + // Returns the condition on which a final split to |
| + // true and false label should be made, to optimize fallthrough. |
| + // Returns two registers in cmp1 and cmp2 that can be used in the |
| + // Branch instruction after EmitTypeofIs. |
| + Condition EmitTypeofIs(Label* true_label, |
| + Label* false_label, |
| + Register input, |
| + Handle<String> type_name, |
| + Register& cmp1, |
| + Operand& cmp2); |
| + |
| + // Emits optimized code for %_IsObject(x). Preserves input register. |
| + // Returns the condition on which a final split to |
| + // true and false label should be made, to optimize fallthrough. |
| + Condition EmitIsObject(Register input, |
| + Register temp1, |
| + Label* is_not_object, |
| + Label* is_object); |
| + |
| + // Emits optimized code for %_IsConstructCall(). |
| + // Caller should branch on equal condition. |
| + void EmitIsConstructCall(Register temp1, Register temp2); |
| + |
| + void EmitLoadFieldOrConstantFunction(Register result, |
| + Register object, |
| + Handle<Map> type, |
| + Handle<String> name); |
| + |
| + struct JumpTableEntry { |
| + explicit inline JumpTableEntry(Address entry) |
| + : label(), |
| + address(entry) { } |
| + Label label; |
| + Address address; |
| + }; |
| + |
| + LChunk* const chunk_; |
| + MacroAssembler* const masm_; |
| + CompilationInfo* const info_; |
| + |
| + int current_block_; |
| + int current_instruction_; |
| + const ZoneList<LInstruction*>* instructions_; |
| + ZoneList<LEnvironment*> deoptimizations_; |
| + ZoneList<JumpTableEntry> deopt_jump_table_; |
| + ZoneList<Handle<Object> > deoptimization_literals_; |
| + int inlined_function_count_; |
| + Scope* const scope_; |
| + Status status_; |
| + TranslationBuffer translations_; |
| + ZoneList<LDeferredCode*> deferred_; |
| + int osr_pc_offset_; |
| + |
| + // Builder that keeps track of safepoints in the code. The table |
| + // itself is emitted at the end of the generated code. |
| + SafepointTableBuilder safepoints_; |
| + |
| + // Compiler from a set of parallel moves to a sequential list of moves. |
| + LGapResolver resolver_; |
| + |
| + Safepoint::Kind expected_safepoint_kind_; |
| + |
| + class PushSafepointRegistersScope BASE_EMBEDDED { |
| + public: |
| + PushSafepointRegistersScope(LCodeGen* codegen, |
| + Safepoint::Kind kind) |
| + : codegen_(codegen) { |
| + ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); |
| + codegen_->expected_safepoint_kind_ = kind; |
| + |
| + switch (codegen_->expected_safepoint_kind_) { |
| + case Safepoint::kWithRegisters: |
| + codegen_->masm_->PushSafepointRegisters(); |
| + break; |
| + case Safepoint::kWithRegistersAndDoubles: |
| + codegen_->masm_->PushSafepointRegistersAndDoubles(); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + } |
| + |
| + ~PushSafepointRegistersScope() { |
| + Safepoint::Kind kind = codegen_->expected_safepoint_kind_; |
| + ASSERT((kind & Safepoint::kWithRegisters) != 0); |
| + switch (kind) { |
| + case Safepoint::kWithRegisters: |
| + codegen_->masm_->PopSafepointRegisters(); |
| + break; |
| + case Safepoint::kWithRegistersAndDoubles: |
| + codegen_->masm_->PopSafepointRegistersAndDoubles(); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + codegen_->expected_safepoint_kind_ = Safepoint::kSimple; |
| + } |
| + |
| + private: |
| + LCodeGen* codegen_; |
| + }; |
| + |
| + friend class LDeferredCode; |
| + friend class LEnvironment; |
| + friend class SafepointGenerator; |
| + DISALLOW_COPY_AND_ASSIGN(LCodeGen); |
| +}; |
| + |
| + |
| +class LDeferredCode: public ZoneObject { |
| + public: |
| + explicit LDeferredCode(LCodeGen* codegen) |
| + : codegen_(codegen), |
| + external_exit_(NULL), |
| + instruction_index_(codegen->current_instruction_) { |
| + codegen->AddDeferredCode(this); |
| + } |
| + |
| + virtual ~LDeferredCode() { } |
| + virtual void Generate() = 0; |
| + virtual LInstruction* instr() = 0; |
| + |
| + void SetExit(Label *exit) { external_exit_ = exit; } |
| + Label* entry() { return &entry_; } |
| + Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } |
| + int instruction_index() const { return instruction_index_; } |
| + |
| + protected: |
| + LCodeGen* codegen() const { return codegen_; } |
| + MacroAssembler* masm() const { return codegen_->masm(); } |
| + |
| + private: |
| + LCodeGen* codegen_; |
| + Label entry_; |
| + Label exit_; |
| + Label* external_exit_; |
| + int instruction_index_; |
| }; |
| } } // namespace v8::internal |