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_X64_LITHIUM_CODEGEN_X64_H_ 29 #define V8_X64_LITHIUM_CODEGEN_X64_H_ 30 31 #include "x64/lithium-x64.h" 32 33 #include "checks.h" 34 #include "deoptimizer.h" 35 #include "safepoint-table.h" 36 #include "scopes.h" 37 #include "x64/lithium-gap-resolver-x64.h" 38 39 namespace v8 { 40 namespace internal { 41 42 // Forward declarations. 43 class LDeferredCode; 44 class SafepointGenerator; 45 46 class LCodeGen BASE_EMBEDDED { 47 public: LCodeGen(LChunk * chunk,MacroAssembler * assembler,CompilationInfo * info)48 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) 49 : chunk_(chunk), 50 masm_(assembler), 51 info_(info), 52 current_block_(-1), 53 current_instruction_(-1), 54 instructions_(chunk->instructions()), 55 deoptimizations_(4), 56 jump_table_(4), 57 deoptimization_literals_(8), 58 inlined_function_count_(0), 59 scope_(info->scope()), 60 status_(UNUSED), 61 deferred_(8), 62 osr_pc_offset_(-1), 63 resolver_(this), 64 expected_safepoint_kind_(Safepoint::kSimple) { 65 PopulateDeoptimizationLiteralsWithInlinedFunctions(); 66 } 67 68 // Simple accessors. masm()69 MacroAssembler* masm() const { return masm_; } info()70 CompilationInfo* info() const { return info_; } isolate()71 Isolate* isolate() const { return info_->isolate(); } factory()72 Factory* factory() const { return isolate()->factory(); } heap()73 Heap* heap() const { return isolate()->heap(); } 74 75 // Support for converting LOperands to assembler types. 76 Register ToRegister(LOperand* op) const; 77 XMMRegister ToDoubleRegister(LOperand* op) const; 78 bool IsInteger32Constant(LConstantOperand* op) const; 79 int ToInteger32(LConstantOperand* op) const; 80 bool IsTaggedConstant(LConstantOperand* op) const; 81 Handle<Object> ToHandle(LConstantOperand* op) const; 82 Operand ToOperand(LOperand* op) const; 83 84 // Try to generate code for the entire chunk, but it may fail if the 85 // chunk contains constructs we cannot handle. Returns true if the 86 // code generation attempt succeeded. 87 bool GenerateCode(); 88 89 // Finish the code by setting stack height, safepoint, and bailout 90 // information on it. 91 void FinishCode(Handle<Code> code); 92 93 // Deferred code support. 94 void DoDeferredNumberTagD(LNumberTagD* instr); 95 void DoDeferredTaggedToI(LTaggedToI* instr); 96 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); 97 void DoDeferredStackCheck(LGoto* instr); 98 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 99 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); 100 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 101 Label* map_check); 102 103 // Parallel move support. 104 void DoParallelMove(LParallelMove* move); 105 106 // Emit frame translation commands for an environment. 107 void WriteTranslation(LEnvironment* environment, Translation* translation); 108 109 // Declare methods that deal with the individual node types. 110 #define DECLARE_DO(type) void Do##type(L##type* node); 111 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 112 #undef DECLARE_DO 113 114 private: 115 enum Status { 116 UNUSED, 117 GENERATING, 118 DONE, 119 ABORTED 120 }; 121 is_unused()122 bool is_unused() const { return status_ == UNUSED; } is_generating()123 bool is_generating() const { return status_ == GENERATING; } is_done()124 bool is_done() const { return status_ == DONE; } is_aborted()125 bool is_aborted() const { return status_ == ABORTED; } 126 strict_mode_flag()127 int strict_mode_flag() const { 128 return info()->is_strict_mode() ? kStrictMode : kNonStrictMode; 129 } 130 chunk()131 LChunk* chunk() const { return chunk_; } scope()132 Scope* scope() const { return scope_; } graph()133 HGraph* graph() const { return chunk_->graph(); } 134 135 int GetNextEmittedBlock(int block); 136 LInstruction* GetNextInstruction(); 137 138 void EmitClassOfTest(Label* if_true, 139 Label* if_false, 140 Handle<String> class_name, 141 Register input, 142 Register temporary); 143 StackSlotCount()144 int StackSlotCount() const { return chunk()->spill_slot_count(); } ParameterCount()145 int ParameterCount() const { return scope()->num_parameters(); } 146 147 void Abort(const char* format, ...); 148 void Comment(const char* format, ...); 149 AddDeferredCode(LDeferredCode * code)150 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } 151 152 // Code generation passes. Returns true if code generation should 153 // continue. 154 bool GeneratePrologue(); 155 bool GenerateBody(); 156 bool GenerateDeferredCode(); 157 bool GenerateJumpTable(); 158 bool GenerateSafepointTable(); 159 160 enum SafepointMode { 161 RECORD_SIMPLE_SAFEPOINT, 162 RECORD_SAFEPOINT_WITH_REGISTERS 163 }; 164 165 void CallCodeGeneric(Handle<Code> code, 166 RelocInfo::Mode mode, 167 LInstruction* instr, 168 SafepointMode safepoint_mode, 169 int argc); 170 171 172 void CallCode(Handle<Code> code, 173 RelocInfo::Mode mode, 174 LInstruction* instr); 175 176 void CallRuntime(const Runtime::Function* function, 177 int num_arguments, 178 LInstruction* instr); 179 CallRuntime(Runtime::FunctionId id,int num_arguments,LInstruction * instr)180 void CallRuntime(Runtime::FunctionId id, 181 int num_arguments, 182 LInstruction* instr) { 183 const Runtime::Function* function = Runtime::FunctionForId(id); 184 CallRuntime(function, num_arguments, instr); 185 } 186 187 void CallRuntimeFromDeferred(Runtime::FunctionId id, 188 int argc, 189 LInstruction* instr); 190 191 192 // Generate a direct call to a known function. Expects the function 193 // to be in edi. 194 void CallKnownFunction(Handle<JSFunction> function, 195 int arity, 196 LInstruction* instr); 197 198 void LoadHeapObject(Register result, Handle<HeapObject> object); 199 200 void RegisterLazyDeoptimization(LInstruction* instr, 201 SafepointMode safepoint_mode, 202 int argc); 203 void RegisterEnvironmentForDeoptimization(LEnvironment* environment); 204 void DeoptimizeIf(Condition cc, LEnvironment* environment); 205 206 void AddToTranslation(Translation* translation, 207 LOperand* op, 208 bool is_tagged); 209 void PopulateDeoptimizationData(Handle<Code> code); 210 int DefineDeoptimizationLiteral(Handle<Object> literal); 211 212 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 213 214 Register ToRegister(int index) const; 215 XMMRegister ToDoubleRegister(int index) const; 216 217 // Specific math operations - used from DoUnaryMathOperation. 218 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 219 void DoMathAbs(LUnaryMathOperation* instr); 220 void DoMathFloor(LUnaryMathOperation* instr); 221 void DoMathRound(LUnaryMathOperation* instr); 222 void DoMathSqrt(LUnaryMathOperation* instr); 223 void DoMathPowHalf(LUnaryMathOperation* instr); 224 void DoMathLog(LUnaryMathOperation* instr); 225 void DoMathCos(LUnaryMathOperation* instr); 226 void DoMathSin(LUnaryMathOperation* instr); 227 228 // Support for recording safepoint and position information. 229 void RecordSafepoint(LPointerMap* pointers, 230 Safepoint::Kind kind, 231 int arguments, 232 int deoptimization_index); 233 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); 234 void RecordSafepoint(int deoptimization_index); 235 void RecordSafepointWithRegisters(LPointerMap* pointers, 236 int arguments, 237 int deoptimization_index); 238 void RecordPosition(int position); LastSafepointEnd()239 int LastSafepointEnd() { 240 return static_cast<int>(safepoints_.GetPcAfterGap()); 241 } 242 243 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 244 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL); 245 void EmitBranch(int left_block, int right_block, Condition cc); 246 void EmitCmpI(LOperand* left, LOperand* right); 247 void EmitNumberUntagD(Register input, 248 XMMRegister result, 249 bool deoptimize_on_undefined, 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 Label* is_not_object, 263 Label* is_object); 264 265 // Emits optimized code for %_IsConstructCall(). 266 // Caller should branch on equal condition. 267 void EmitIsConstructCall(Register temp); 268 269 void EmitLoadField(Register result, 270 Register object, 271 Handle<Map> type, 272 Handle<String> name); 273 274 // Emits code for pushing a constant operand. 275 void EmitPushConstantOperand(LOperand* operand); 276 277 struct JumpTableEntry { JumpTableEntryJumpTableEntry278 explicit inline JumpTableEntry(Address entry) 279 : label(), 280 address(entry) { } 281 Label label; 282 Address address; 283 }; 284 285 LChunk* const chunk_; 286 MacroAssembler* const masm_; 287 CompilationInfo* const info_; 288 289 int current_block_; 290 int current_instruction_; 291 const ZoneList<LInstruction*>* instructions_; 292 ZoneList<LEnvironment*> deoptimizations_; 293 ZoneList<JumpTableEntry> jump_table_; 294 ZoneList<Handle<Object> > deoptimization_literals_; 295 int inlined_function_count_; 296 Scope* const scope_; 297 Status status_; 298 TranslationBuffer translations_; 299 ZoneList<LDeferredCode*> deferred_; 300 int osr_pc_offset_; 301 302 // Builder that keeps track of safepoints in the code. The table 303 // itself is emitted at the end of the generated code. 304 SafepointTableBuilder safepoints_; 305 306 // Compiler from a set of parallel moves to a sequential list of moves. 307 LGapResolver resolver_; 308 309 Safepoint::Kind expected_safepoint_kind_; 310 311 class PushSafepointRegistersScope BASE_EMBEDDED { 312 public: PushSafepointRegistersScope(LCodeGen * codegen)313 explicit PushSafepointRegistersScope(LCodeGen* codegen) 314 : codegen_(codegen) { 315 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); 316 codegen_->masm_->PushSafepointRegisters(); 317 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters; 318 } 319 ~PushSafepointRegistersScope()320 ~PushSafepointRegistersScope() { 321 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters); 322 codegen_->masm_->PopSafepointRegisters(); 323 codegen_->expected_safepoint_kind_ = Safepoint::kSimple; 324 } 325 326 private: 327 LCodeGen* codegen_; 328 }; 329 330 friend class LDeferredCode; 331 friend class LEnvironment; 332 friend class SafepointGenerator; 333 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 334 }; 335 336 337 class LDeferredCode: public ZoneObject { 338 public: LDeferredCode(LCodeGen * codegen)339 explicit LDeferredCode(LCodeGen* codegen) 340 : codegen_(codegen), external_exit_(NULL) { 341 codegen->AddDeferredCode(this); 342 } 343 ~LDeferredCode()344 virtual ~LDeferredCode() { } 345 virtual void Generate() = 0; 346 SetExit(Label * exit)347 void SetExit(Label *exit) { external_exit_ = exit; } entry()348 Label* entry() { return &entry_; } exit()349 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 350 351 protected: codegen()352 LCodeGen* codegen() const { return codegen_; } masm()353 MacroAssembler* masm() const { return codegen_->masm(); } 354 355 private: 356 LCodeGen* codegen_; 357 Label entry_; 358 Label exit_; 359 Label* external_exit_; 360 }; 361 362 } } // namespace v8::internal 363 364 #endif // V8_X64_LITHIUM_CODEGEN_X64_H_ 365