lithium-codegen-arm.h revision 1e0659c275bb392c045087af4f6b0d7565cb3d77
1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#ifndef V8_ARM_LITHIUM_CODEGEN_ARM_H_ 29#define V8_ARM_LITHIUM_CODEGEN_ARM_H_ 30 31#include "arm/lithium-arm.h" 32 33#include "deoptimizer.h" 34#include "safepoint-table.h" 35#include "scopes.h" 36 37namespace v8 { 38namespace internal { 39 40// Forward declarations. 41class LDeferredCode; 42class LGapNode; 43class SafepointGenerator; 44 45class LGapResolver BASE_EMBEDDED { 46 public: 47 LGapResolver(); 48 const ZoneList<LMoveOperands>* Resolve(const ZoneList<LMoveOperands>* moves, 49 LOperand* marker_operand); 50 51 private: 52 LGapNode* LookupNode(LOperand* operand); 53 bool CanReach(LGapNode* a, LGapNode* b, int visited_id); 54 bool CanReach(LGapNode* a, LGapNode* b); 55 void RegisterMove(LMoveOperands move); 56 void AddResultMove(LOperand* from, LOperand* to); 57 void AddResultMove(LGapNode* from, LGapNode* to); 58 void ResolveCycle(LGapNode* start, LOperand* marker_operand); 59 60 ZoneList<LGapNode*> nodes_; 61 ZoneList<LGapNode*> identified_cycles_; 62 ZoneList<LMoveOperands> result_; 63 int next_visited_id_; 64}; 65 66 67class LCodeGen BASE_EMBEDDED { 68 public: 69 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) 70 : chunk_(chunk), 71 masm_(assembler), 72 info_(info), 73 current_block_(-1), 74 current_instruction_(-1), 75 instructions_(chunk->instructions()), 76 deoptimizations_(4), 77 deoptimization_literals_(8), 78 inlined_function_count_(0), 79 scope_(chunk->graph()->info()->scope()), 80 status_(UNUSED), 81 deferred_(8), 82 osr_pc_offset_(-1) { 83 PopulateDeoptimizationLiteralsWithInlinedFunctions(); 84 } 85 86 // Try to generate code for the entire chunk, but it may fail if the 87 // chunk contains constructs we cannot handle. Returns true if the 88 // code generation attempt succeeded. 89 bool GenerateCode(); 90 91 // Finish the code by setting stack height, safepoint, and bailout 92 // information on it. 93 void FinishCode(Handle<Code> code); 94 95 // Deferred code support. 96 template<int T> 97 void DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr, 98 Token::Value op); 99 void DoDeferredNumberTagD(LNumberTagD* instr); 100 void DoDeferredNumberTagI(LNumberTagI* instr); 101 void DoDeferredTaggedToI(LTaggedToI* instr); 102 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); 103 void DoDeferredStackCheck(LGoto* instr); 104 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 105 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 106 Label* map_check); 107 108 // Parallel move support. 109 void DoParallelMove(LParallelMove* move); 110 111 // Emit frame translation commands for an environment. 112 void WriteTranslation(LEnvironment* environment, Translation* translation); 113 114 // Declare methods that deal with the individual node types. 115#define DECLARE_DO(type) void Do##type(L##type* node); 116 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 117#undef DECLARE_DO 118 119 private: 120 enum Status { 121 UNUSED, 122 GENERATING, 123 DONE, 124 ABORTED 125 }; 126 127 bool is_unused() const { return status_ == UNUSED; } 128 bool is_generating() const { return status_ == GENERATING; } 129 bool is_done() const { return status_ == DONE; } 130 bool is_aborted() const { return status_ == ABORTED; } 131 132 LChunk* chunk() const { return chunk_; } 133 Scope* scope() const { return scope_; } 134 HGraph* graph() const { return chunk_->graph(); } 135 MacroAssembler* masm() const { return masm_; } 136 137 Register scratch0() { return r9; } 138 DwVfpRegister double_scratch0() { return d0; } 139 140 int GetNextEmittedBlock(int block); 141 LInstruction* GetNextInstruction(); 142 143 void EmitClassOfTest(Label* if_true, 144 Label* if_false, 145 Handle<String> class_name, 146 Register input, 147 Register temporary, 148 Register temporary2); 149 150 int StackSlotCount() const { return chunk()->spill_slot_count(); } 151 int ParameterCount() const { return scope()->num_parameters(); } 152 153 void Abort(const char* format, ...); 154 void Comment(const char* format, ...); 155 156 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } 157 158 // Code generation passes. Returns true if code generation should 159 // continue. 160 bool GeneratePrologue(); 161 bool GenerateBody(); 162 bool GenerateDeferredCode(); 163 bool GenerateSafepointTable(); 164 165 void CallCode(Handle<Code> code, 166 RelocInfo::Mode mode, 167 LInstruction* instr); 168 void CallRuntime(Runtime::Function* function, 169 int num_arguments, 170 LInstruction* instr); 171 void CallRuntime(Runtime::FunctionId id, 172 int num_arguments, 173 LInstruction* instr) { 174 Runtime::Function* function = Runtime::FunctionForId(id); 175 CallRuntime(function, num_arguments, instr); 176 } 177 178 // Generate a direct call to a known function. Expects the function 179 // to be in edi. 180 void CallKnownFunction(Handle<JSFunction> function, 181 int arity, 182 LInstruction* instr); 183 184 void LoadHeapObject(Register result, Handle<HeapObject> object); 185 186 void RegisterLazyDeoptimization(LInstruction* instr); 187 void RegisterEnvironmentForDeoptimization(LEnvironment* environment); 188 void DeoptimizeIf(Condition cc, LEnvironment* environment); 189 190 void AddToTranslation(Translation* translation, 191 LOperand* op, 192 bool is_tagged); 193 void PopulateDeoptimizationData(Handle<Code> code); 194 int DefineDeoptimizationLiteral(Handle<Object> literal); 195 196 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 197 198 Register ToRegister(int index) const; 199 DoubleRegister ToDoubleRegister(int index) const; 200 201 // LOperand must be a register. 202 Register ToRegister(LOperand* op) const; 203 204 // LOperand is loaded into scratch, unless already a register. 205 Register EmitLoadRegister(LOperand* op, Register scratch); 206 207 // LOperand must be a double register. 208 DoubleRegister ToDoubleRegister(LOperand* op) const; 209 210 // LOperand is loaded into dbl_scratch, unless already a double register. 211 DoubleRegister EmitLoadDoubleRegister(LOperand* op, 212 SwVfpRegister flt_scratch, 213 DoubleRegister dbl_scratch); 214 215 int ToInteger32(LConstantOperand* op) const; 216 Operand ToOperand(LOperand* op); 217 MemOperand ToMemOperand(LOperand* op) const; 218 219 // Specific math operations - used from DoUnaryMathOperation. 220 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 221 void DoMathAbs(LUnaryMathOperation* instr); 222 void EmitVFPTruncate(VFPRoundingMode rounding_mode, 223 SwVfpRegister result, 224 DwVfpRegister double_input, 225 Register scratch1, 226 Register scratch2); 227 void DoMathFloor(LUnaryMathOperation* instr); 228 void DoMathSqrt(LUnaryMathOperation* instr); 229 230 // Support for recording safepoint and position information. 231 void RecordSafepoint(LPointerMap* pointers, 232 Safepoint::Kind kind, 233 int arguments, 234 int deoptimization_index); 235 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); 236 void RecordSafepointWithRegisters(LPointerMap* pointers, 237 int arguments, 238 int deoptimization_index); 239 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers, 240 int arguments, 241 int deoptimization_index); 242 void RecordPosition(int position); 243 244 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 245 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL); 246 void EmitBranch(int left_block, int right_block, Condition cc); 247 void EmitCmpI(LOperand* left, LOperand* right); 248 void EmitNumberUntagD(Register input, 249 DoubleRegister result, 250 LEnvironment* env); 251 252 // Emits optimized code for typeof x == "y". Modifies input register. 253 // Returns the condition on which a final split to 254 // true and false label should be made, to optimize fallthrough. 255 Condition EmitTypeofIs(Label* true_label, Label* false_label, 256 Register input, Handle<String> type_name); 257 258 // Emits optimized code for %_IsObject(x). Preserves input register. 259 // Returns the condition on which a final split to 260 // true and false label should be made, to optimize fallthrough. 261 Condition EmitIsObject(Register input, 262 Register temp1, 263 Register temp2, 264 Label* is_not_object, 265 Label* is_object); 266 267 // Emits optimized code for %_IsConstructCall(). 268 // Caller should branch on equal condition. 269 void EmitIsConstructCall(Register temp1, Register temp2); 270 271 LChunk* const chunk_; 272 MacroAssembler* const masm_; 273 CompilationInfo* const info_; 274 275 int current_block_; 276 int current_instruction_; 277 const ZoneList<LInstruction*>* instructions_; 278 ZoneList<LEnvironment*> deoptimizations_; 279 ZoneList<Handle<Object> > deoptimization_literals_; 280 int inlined_function_count_; 281 Scope* const scope_; 282 Status status_; 283 TranslationBuffer translations_; 284 ZoneList<LDeferredCode*> deferred_; 285 int osr_pc_offset_; 286 287 // Builder that keeps track of safepoints in the code. The table 288 // itself is emitted at the end of the generated code. 289 SafepointTableBuilder safepoints_; 290 291 // Compiler from a set of parallel moves to a sequential list of moves. 292 LGapResolver resolver_; 293 294 friend class LDeferredCode; 295 friend class LEnvironment; 296 friend class SafepointGenerator; 297 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 298}; 299 300 301class LDeferredCode: public ZoneObject { 302 public: 303 explicit LDeferredCode(LCodeGen* codegen) 304 : codegen_(codegen), external_exit_(NULL) { 305 codegen->AddDeferredCode(this); 306 } 307 308 virtual ~LDeferredCode() { } 309 virtual void Generate() = 0; 310 311 void SetExit(Label *exit) { external_exit_ = exit; } 312 Label* entry() { return &entry_; } 313 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 314 315 protected: 316 LCodeGen* codegen() const { return codegen_; } 317 MacroAssembler* masm() const { return codegen_->masm(); } 318 319 private: 320 LCodeGen* codegen_; 321 Label entry_; 322 Label exit_; 323 Label* external_exit_; 324}; 325 326} } // namespace v8::internal 327 328#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_ 329