lithium-codegen-x64.h revision 69a99ed0b2b2ef69d393c371b03db3a98aaf880e
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 39namespace v8 { 40namespace internal { 41 42// Forward declarations. 43class LDeferredCode; 44class SafepointGenerator; 45 46class LCodeGen BASE_EMBEDDED { 47 public: 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. 69 MacroAssembler* masm() const { return masm_; } 70 CompilationInfo* info() const { return info_; } 71 Isolate* isolate() const { return info_->isolate(); } 72 Factory* factory() const { return isolate()->factory(); } 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(LStackCheck* 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 void DoGap(LGap* instr); 106 107 // Emit frame translation commands for an environment. 108 void WriteTranslation(LEnvironment* environment, Translation* translation); 109 110 // Declare methods that deal with the individual node types. 111#define DECLARE_DO(type) void Do##type(L##type* node); 112 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 113#undef DECLARE_DO 114 115 private: 116 enum Status { 117 UNUSED, 118 GENERATING, 119 DONE, 120 ABORTED 121 }; 122 123 bool is_unused() const { return status_ == UNUSED; } 124 bool is_generating() const { return status_ == GENERATING; } 125 bool is_done() const { return status_ == DONE; } 126 bool is_aborted() const { return status_ == ABORTED; } 127 128 int strict_mode_flag() const { 129 return info()->is_strict_mode() ? kStrictMode : kNonStrictMode; 130 } 131 132 LChunk* chunk() const { return chunk_; } 133 Scope* scope() const { return scope_; } 134 HGraph* graph() const { return chunk_->graph(); } 135 136 int GetNextEmittedBlock(int block); 137 LInstruction* GetNextInstruction(); 138 139 void EmitClassOfTest(Label* if_true, 140 Label* if_false, 141 Handle<String> class_name, 142 Register input, 143 Register temporary); 144 145 int GetStackSlotCount() const { return chunk()->spill_slot_count(); } 146 int GetParameterCount() const { return scope()->num_parameters(); } 147 148 void Abort(const char* format, ...); 149 void Comment(const char* format, ...); 150 151 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } 152 153 // Code generation passes. Returns true if code generation should 154 // continue. 155 bool GeneratePrologue(); 156 bool GenerateBody(); 157 bool GenerateDeferredCode(); 158 bool GenerateJumpTable(); 159 bool GenerateSafepointTable(); 160 161 enum SafepointMode { 162 RECORD_SIMPLE_SAFEPOINT, 163 RECORD_SAFEPOINT_WITH_REGISTERS 164 }; 165 166 void CallCodeGeneric(Handle<Code> code, 167 RelocInfo::Mode mode, 168 LInstruction* instr, 169 SafepointMode safepoint_mode, 170 int argc); 171 172 173 void CallCode(Handle<Code> code, 174 RelocInfo::Mode mode, 175 LInstruction* instr); 176 177 void CallRuntime(const Runtime::Function* function, 178 int num_arguments, 179 LInstruction* instr); 180 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 void CallRuntimeFromDeferred(Runtime::FunctionId id, 189 int argc, 190 LInstruction* instr); 191 192 193 // Generate a direct call to a known function. Expects the function 194 // to be in edi. 195 void CallKnownFunction(Handle<JSFunction> function, 196 int arity, 197 LInstruction* instr, 198 CallKind call_kind); 199 200 void LoadHeapObject(Register result, Handle<HeapObject> object); 201 202 void RegisterLazyDeoptimization(LInstruction* instr, 203 SafepointMode safepoint_mode, 204 int argc); 205 void RegisterEnvironmentForDeoptimization(LEnvironment* environment); 206 void DeoptimizeIf(Condition cc, LEnvironment* environment); 207 208 void AddToTranslation(Translation* translation, 209 LOperand* op, 210 bool is_tagged); 211 void PopulateDeoptimizationData(Handle<Code> code); 212 int DefineDeoptimizationLiteral(Handle<Object> literal); 213 214 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 215 216 Register ToRegister(int index) const; 217 XMMRegister ToDoubleRegister(int index) const; 218 Operand BuildFastArrayOperand( 219 LOperand* elements_pointer, 220 LOperand* key, 221 JSObject::ElementsKind elements_kind, 222 uint32_t offset); 223 224 // Specific math operations - used from DoUnaryMathOperation. 225 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 226 void DoMathAbs(LUnaryMathOperation* instr); 227 void DoMathFloor(LUnaryMathOperation* instr); 228 void DoMathRound(LUnaryMathOperation* instr); 229 void DoMathSqrt(LUnaryMathOperation* instr); 230 void DoMathPowHalf(LUnaryMathOperation* instr); 231 void DoMathLog(LUnaryMathOperation* instr); 232 void DoMathCos(LUnaryMathOperation* instr); 233 void DoMathSin(LUnaryMathOperation* instr); 234 235 // Support for recording safepoint and position information. 236 void RecordSafepoint(LPointerMap* pointers, 237 Safepoint::Kind kind, 238 int arguments, 239 int deoptimization_index); 240 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); 241 void RecordSafepoint(int deoptimization_index); 242 void RecordSafepointWithRegisters(LPointerMap* pointers, 243 int arguments, 244 int deoptimization_index); 245 void RecordPosition(int position); 246 int LastSafepointEnd() { 247 return static_cast<int>(safepoints_.GetPcAfterGap()); 248 } 249 250 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 251 void EmitGoto(int block); 252 void EmitBranch(int left_block, int right_block, Condition cc); 253 void EmitCmpI(LOperand* left, LOperand* right); 254 void EmitNumberUntagD(Register input, 255 XMMRegister result, 256 bool deoptimize_on_undefined, 257 LEnvironment* env); 258 259 // Emits optimized code for typeof x == "y". Modifies input register. 260 // Returns the condition on which a final split to 261 // true and false label should be made, to optimize fallthrough. 262 Condition EmitTypeofIs(Label* true_label, Label* false_label, 263 Register input, Handle<String> type_name); 264 265 // Emits optimized code for %_IsObject(x). Preserves input register. 266 // Returns the condition on which a final split to 267 // true and false label should be made, to optimize fallthrough. 268 Condition EmitIsObject(Register input, 269 Label* is_not_object, 270 Label* is_object); 271 272 // Emits optimized code for %_IsConstructCall(). 273 // Caller should branch on equal condition. 274 void EmitIsConstructCall(Register temp); 275 276 void EmitLoadFieldOrConstantFunction(Register result, 277 Register object, 278 Handle<Map> type, 279 Handle<String> name); 280 281 // Emits code for pushing either a tagged constant, a (non-double) 282 // register, or a stack slot operand. 283 void EmitPushTaggedOperand(LOperand* operand); 284 285 struct JumpTableEntry { 286 explicit inline JumpTableEntry(Address entry) 287 : label(), 288 address(entry) { } 289 Label label; 290 Address address; 291 }; 292 293 LChunk* const chunk_; 294 MacroAssembler* const masm_; 295 CompilationInfo* const info_; 296 297 int current_block_; 298 int current_instruction_; 299 const ZoneList<LInstruction*>* instructions_; 300 ZoneList<LEnvironment*> deoptimizations_; 301 ZoneList<JumpTableEntry> jump_table_; 302 ZoneList<Handle<Object> > deoptimization_literals_; 303 int inlined_function_count_; 304 Scope* const scope_; 305 Status status_; 306 TranslationBuffer translations_; 307 ZoneList<LDeferredCode*> deferred_; 308 int osr_pc_offset_; 309 310 // Builder that keeps track of safepoints in the code. The table 311 // itself is emitted at the end of the generated code. 312 SafepointTableBuilder safepoints_; 313 314 // Compiler from a set of parallel moves to a sequential list of moves. 315 LGapResolver resolver_; 316 317 Safepoint::Kind expected_safepoint_kind_; 318 319 class PushSafepointRegistersScope BASE_EMBEDDED { 320 public: 321 explicit PushSafepointRegistersScope(LCodeGen* codegen) 322 : codegen_(codegen) { 323 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); 324 codegen_->masm_->PushSafepointRegisters(); 325 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters; 326 } 327 328 ~PushSafepointRegistersScope() { 329 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters); 330 codegen_->masm_->PopSafepointRegisters(); 331 codegen_->expected_safepoint_kind_ = Safepoint::kSimple; 332 } 333 334 private: 335 LCodeGen* codegen_; 336 }; 337 338 friend class LDeferredCode; 339 friend class LEnvironment; 340 friend class SafepointGenerator; 341 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 342}; 343 344 345class LDeferredCode: public ZoneObject { 346 public: 347 explicit LDeferredCode(LCodeGen* codegen) 348 : codegen_(codegen), external_exit_(NULL) { 349 codegen->AddDeferredCode(this); 350 } 351 352 virtual ~LDeferredCode() { } 353 virtual void Generate() = 0; 354 355 void SetExit(Label *exit) { external_exit_ = exit; } 356 Label* entry() { return &entry_; } 357 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 358 359 protected: 360 LCodeGen* codegen() const { return codegen_; } 361 MacroAssembler* masm() const { return codegen_->masm(); } 362 363 private: 364 LCodeGen* codegen_; 365 Label entry_; 366 Label exit_; 367 Label* external_exit_; 368}; 369 370} } // namespace v8::internal 371 372#endif // V8_X64_LITHIUM_CODEGEN_X64_H_ 373