| 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..f9c013c1f5d2bb4cbf8f7cf1cd2ec60c4e0508d6 100644
|
| --- a/src/mips/lithium-codegen-mips.h
|
| +++ b/src/mips/lithium-codegen-mips.h
|
| @@ -29,35 +29,398 @@
|
| #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;
|
| + double ToDouble(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; }
|
| +
|
| + StrictModeFlag strict_mode_flag() const {
|
| + return info()->strict_mode_flag();
|
| + }
|
| +
|
| + 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 a1.
|
| + 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
|
|
|