lithium-codegen-arm.h revision 44f0eee88ff00398ff7f715fab053374d808c90d
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#include "arm/lithium-gap-resolver-arm.h" 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 SafepointGenerator; 43 44class LCodeGen BASE_EMBEDDED { 45 public: 46 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) 47 : chunk_(chunk), 48 masm_(assembler), 49 info_(info), 50 current_block_(-1), 51 current_instruction_(-1), 52 instructions_(chunk->instructions()), 53 deoptimizations_(4), 54 deoptimization_literals_(8), 55 inlined_function_count_(0), 56 scope_(info->scope()), 57 status_(UNUSED), 58 deferred_(8), 59 osr_pc_offset_(-1), 60 resolver_(this) { 61 PopulateDeoptimizationLiteralsWithInlinedFunctions(); 62 } 63 64 65 // Simple accessors. 66 MacroAssembler* masm() const { return masm_; } 67 CompilationInfo* info() const { return info_; } 68 Isolate* isolate() const { return info_->isolate(); } 69 Factory* factory() const { return isolate()->factory(); } 70 Heap* heap() const { return isolate()->heap(); } 71 72 // Support for converting LOperands to assembler types. 73 // LOperand must be a register. 74 Register ToRegister(LOperand* op) const; 75 76 // LOperand is loaded into scratch, unless already a register. 77 Register EmitLoadRegister(LOperand* op, Register scratch); 78 79 // LOperand must be a double register. 80 DoubleRegister ToDoubleRegister(LOperand* op) const; 81 82 // LOperand is loaded into dbl_scratch, unless already a double register. 83 DoubleRegister EmitLoadDoubleRegister(LOperand* op, 84 SwVfpRegister flt_scratch, 85 DoubleRegister dbl_scratch); 86 int ToInteger32(LConstantOperand* op) const; 87 Operand ToOperand(LOperand* op); 88 MemOperand ToMemOperand(LOperand* op) const; 89 // Returns a MemOperand pointing to the high word of a DoubleStackSlot. 90 MemOperand ToHighMemOperand(LOperand* op) const; 91 92 // Try to generate code for the entire chunk, but it may fail if the 93 // chunk contains constructs we cannot handle. Returns true if the 94 // code generation attempt succeeded. 95 bool GenerateCode(); 96 97 // Finish the code by setting stack height, safepoint, and bailout 98 // information on it. 99 void FinishCode(Handle<Code> code); 100 101 // Deferred code support. 102 template<int T> 103 void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, 104 Token::Value op); 105 void DoDeferredNumberTagD(LNumberTagD* instr); 106 void DoDeferredNumberTagI(LNumberTagI* instr); 107 void DoDeferredTaggedToI(LTaggedToI* instr); 108 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); 109 void DoDeferredStackCheck(LGoto* instr); 110 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 111 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); 112 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 113 Label* map_check); 114 115 // Parallel move support. 116 void DoParallelMove(LParallelMove* move); 117 118 // Emit frame translation commands for an environment. 119 void WriteTranslation(LEnvironment* environment, Translation* translation); 120 121 // Declare methods that deal with the individual node types. 122#define DECLARE_DO(type) void Do##type(L##type* node); 123 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 124#undef DECLARE_DO 125 126 private: 127 enum Status { 128 UNUSED, 129 GENERATING, 130 DONE, 131 ABORTED 132 }; 133 134 bool is_unused() const { return status_ == UNUSED; } 135 bool is_generating() const { return status_ == GENERATING; } 136 bool is_done() const { return status_ == DONE; } 137 bool is_aborted() const { return status_ == ABORTED; } 138 139 int strict_mode_flag() const { 140 return info()->is_strict() ? kStrictMode : kNonStrictMode; 141 } 142 143 LChunk* chunk() const { return chunk_; } 144 Scope* scope() const { return scope_; } 145 HGraph* graph() const { return chunk_->graph(); } 146 147 Register scratch0() { return r9; } 148 DwVfpRegister double_scratch0() { return d0; } 149 150 int GetNextEmittedBlock(int block); 151 LInstruction* GetNextInstruction(); 152 153 void EmitClassOfTest(Label* if_true, 154 Label* if_false, 155 Handle<String> class_name, 156 Register input, 157 Register temporary, 158 Register temporary2); 159 160 int StackSlotCount() const { return chunk()->spill_slot_count(); } 161 int ParameterCount() const { return scope()->num_parameters(); } 162 163 void Abort(const char* format, ...); 164 void Comment(const char* format, ...); 165 166 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } 167 168 // Code generation passes. Returns true if code generation should 169 // continue. 170 bool GeneratePrologue(); 171 bool GenerateBody(); 172 bool GenerateDeferredCode(); 173 bool GenerateSafepointTable(); 174 175 void CallCode(Handle<Code> code, 176 RelocInfo::Mode mode, 177 LInstruction* instr); 178 void CallRuntime(const Runtime::Function* function, 179 int num_arguments, 180 LInstruction* instr); 181 void CallRuntime(Runtime::FunctionId id, 182 int num_arguments, 183 LInstruction* instr) { 184 const Runtime::Function* function = Runtime::FunctionForId(id); 185 CallRuntime(function, num_arguments, instr); 186 } 187 188 // Generate a direct call to a known function. Expects the function 189 // to be in edi. 190 void CallKnownFunction(Handle<JSFunction> function, 191 int arity, 192 LInstruction* instr); 193 194 void LoadHeapObject(Register result, Handle<HeapObject> object); 195 196 void RegisterLazyDeoptimization(LInstruction* instr); 197 void RegisterEnvironmentForDeoptimization(LEnvironment* environment); 198 void DeoptimizeIf(Condition cc, LEnvironment* environment); 199 200 void AddToTranslation(Translation* translation, 201 LOperand* op, 202 bool is_tagged); 203 void PopulateDeoptimizationData(Handle<Code> code); 204 int DefineDeoptimizationLiteral(Handle<Object> literal); 205 206 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 207 208 Register ToRegister(int index) const; 209 DoubleRegister ToDoubleRegister(int index) const; 210 211 // Specific math operations - used from DoUnaryMathOperation. 212 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 213 void DoMathAbs(LUnaryMathOperation* instr); 214 void DoMathFloor(LUnaryMathOperation* instr); 215 void DoMathRound(LUnaryMathOperation* instr); 216 void DoMathSqrt(LUnaryMathOperation* instr); 217 void DoMathPowHalf(LUnaryMathOperation* instr); 218 void DoMathLog(LUnaryMathOperation* instr); 219 void DoMathCos(LUnaryMathOperation* instr); 220 void DoMathSin(LUnaryMathOperation* instr); 221 222 // Support for recording safepoint and position information. 223 void RecordSafepoint(LPointerMap* pointers, 224 Safepoint::Kind kind, 225 int arguments, 226 int deoptimization_index); 227 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); 228 void RecordSafepoint(int deoptimization_index); 229 void RecordSafepointWithRegisters(LPointerMap* pointers, 230 int arguments, 231 int deoptimization_index); 232 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers, 233 int arguments, 234 int deoptimization_index); 235 void RecordPosition(int position); 236 int LastSafepointEnd() { 237 return static_cast<int>(safepoints_.GetPcAfterGap()); 238 } 239 240 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 241 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL); 242 void EmitBranch(int left_block, int right_block, Condition cc); 243 void EmitCmpI(LOperand* left, LOperand* right); 244 void EmitNumberUntagD(Register input, 245 DoubleRegister result, 246 LEnvironment* env); 247 248 // Emits optimized code for typeof x == "y". Modifies input register. 249 // Returns the condition on which a final split to 250 // true and false label should be made, to optimize fallthrough. 251 Condition EmitTypeofIs(Label* true_label, Label* false_label, 252 Register input, Handle<String> type_name); 253 254 // Emits optimized code for %_IsObject(x). Preserves input register. 255 // Returns the condition on which a final split to 256 // true and false label should be made, to optimize fallthrough. 257 Condition EmitIsObject(Register input, 258 Register temp1, 259 Register temp2, 260 Label* is_not_object, 261 Label* is_object); 262 263 // Emits optimized code for %_IsConstructCall(). 264 // Caller should branch on equal condition. 265 void EmitIsConstructCall(Register temp1, Register temp2); 266 267 void EmitLoadField(Register result, 268 Register object, 269 Handle<Map> type, 270 Handle<String> name); 271 272 LChunk* const chunk_; 273 MacroAssembler* const masm_; 274 CompilationInfo* const info_; 275 276 int current_block_; 277 int current_instruction_; 278 const ZoneList<LInstruction*>* instructions_; 279 ZoneList<LEnvironment*> deoptimizations_; 280 ZoneList<Handle<Object> > deoptimization_literals_; 281 int inlined_function_count_; 282 Scope* const scope_; 283 Status status_; 284 TranslationBuffer translations_; 285 ZoneList<LDeferredCode*> deferred_; 286 int osr_pc_offset_; 287 288 // Builder that keeps track of safepoints in the code. The table 289 // itself is emitted at the end of the generated code. 290 SafepointTableBuilder safepoints_; 291 292 // Compiler from a set of parallel moves to a sequential list of moves. 293 LGapResolver resolver_; 294 295 friend class LDeferredCode; 296 friend class LEnvironment; 297 friend class SafepointGenerator; 298 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 299}; 300 301 302class LDeferredCode: public ZoneObject { 303 public: 304 explicit LDeferredCode(LCodeGen* codegen) 305 : codegen_(codegen), external_exit_(NULL) { 306 codegen->AddDeferredCode(this); 307 } 308 309 virtual ~LDeferredCode() { } 310 virtual void Generate() = 0; 311 312 void SetExit(Label *exit) { external_exit_ = exit; } 313 Label* entry() { return &entry_; } 314 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 315 316 protected: 317 LCodeGen* codegen() const { return codegen_; } 318 MacroAssembler* masm() const { return codegen_->masm(); } 319 320 private: 321 LCodeGen* codegen_; 322 Label entry_; 323 Label exit_; 324 Label* external_exit_; 325}; 326 327} } // namespace v8::internal 328 329#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_ 330