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_IA32_LITHIUM_CODEGEN_IA32_H_ 29 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ 30 31 #include "ia32/lithium-ia32.h" 32 33 #include "checks.h" 34 #include "deoptimizer.h" 35 #include "safepoint-table.h" 36 #include "scopes.h" 37 #include "ia32/lithium-gap-resolver-ia32.h" 38 39 namespace v8 { 40 namespace internal { 41 42 // Forward declarations. 43 class LDeferredCode; 44 class LGapNode; 45 class SafepointGenerator; 46 47 class LCodeGen BASE_EMBEDDED { 48 public: 49 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) 50 : chunk_(chunk), 51 masm_(assembler), 52 info_(info), 53 current_block_(-1), 54 current_instruction_(-1), 55 instructions_(chunk->instructions()), 56 deoptimizations_(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 deoptimization_reloc_size(), 64 resolver_(this), 65 expected_safepoint_kind_(Safepoint::kSimple) { 66 PopulateDeoptimizationLiteralsWithInlinedFunctions(); 67 } 68 69 // Simple accessors. 70 MacroAssembler* masm() const { return masm_; } 71 CompilationInfo* info() const { return info_; } 72 Isolate* isolate() const { return info_->isolate(); } 73 Factory* factory() const { return isolate()->factory(); } 74 Heap* heap() const { return isolate()->heap(); } 75 76 // Support for converting LOperands to assembler types. 77 Operand ToOperand(LOperand* op) const; 78 Register ToRegister(LOperand* op) const; 79 XMMRegister ToDoubleRegister(LOperand* op) const; 80 Immediate ToImmediate(LOperand* op); 81 82 // The operand denoting the second word (the one with a higher address) of 83 // a double stack slot. 84 Operand HighOperand(LOperand* op); 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 void DoDeferredNumberTagD(LNumberTagD* instr); 97 void DoDeferredNumberTagI(LNumberTagI* instr); 98 void DoDeferredTaggedToI(LTaggedToI* instr); 99 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); 100 void DoDeferredStackCheck(LGoto* instr); 101 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 102 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); 103 void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 104 Label* map_check); 105 106 // Parallel move support. 107 void DoParallelMove(LParallelMove* move); 108 109 // Emit frame translation commands for an environment. 110 void WriteTranslation(LEnvironment* environment, Translation* translation); 111 112 void EnsureRelocSpaceForDeoptimization(); 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 int strict_mode_flag() const { 133 return info()->is_strict_mode() ? kStrictMode : kNonStrictMode; 134 } 135 136 LChunk* chunk() const { return chunk_; } 137 Scope* scope() const { return scope_; } 138 HGraph* graph() const { return chunk_->graph(); } 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 // Pad the reloc info to ensure that we have enough space to patch during 164 // deoptimization. 165 bool GenerateRelocPadding(); 166 bool GenerateSafepointTable(); 167 168 enum ContextMode { 169 RESTORE_CONTEXT, 170 CONTEXT_ADJUSTED 171 }; 172 173 enum SafepointMode { 174 RECORD_SIMPLE_SAFEPOINT, 175 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS 176 }; 177 178 void CallCode(Handle<Code> code, 179 RelocInfo::Mode mode, 180 LInstruction* instr, 181 ContextMode context_mode); 182 183 void CallCodeGeneric(Handle<Code> code, 184 RelocInfo::Mode mode, 185 LInstruction* instr, 186 ContextMode context_mode, 187 SafepointMode safepoint_mode); 188 189 void CallRuntime(const Runtime::Function* fun, 190 int argc, 191 LInstruction* instr, 192 ContextMode context_mode); 193 194 void CallRuntime(Runtime::FunctionId id, 195 int argc, 196 LInstruction* instr, 197 ContextMode context_mode) { 198 const Runtime::Function* function = Runtime::FunctionForId(id); 199 CallRuntime(function, argc, instr, context_mode); 200 } 201 202 void CallRuntimeFromDeferred(Runtime::FunctionId id, 203 int argc, 204 LInstruction* instr); 205 206 // Generate a direct call to a known function. Expects the function 207 // to be in edi. 208 void CallKnownFunction(Handle<JSFunction> function, 209 int arity, 210 LInstruction* instr); 211 212 void LoadHeapObject(Register result, Handle<HeapObject> object); 213 214 void RegisterLazyDeoptimization(LInstruction* instr, 215 SafepointMode safepoint_mode); 216 217 void RegisterEnvironmentForDeoptimization(LEnvironment* environment); 218 void DeoptimizeIf(Condition cc, LEnvironment* environment); 219 220 void AddToTranslation(Translation* translation, 221 LOperand* op, 222 bool is_tagged); 223 void PopulateDeoptimizationData(Handle<Code> code); 224 int DefineDeoptimizationLiteral(Handle<Object> literal); 225 226 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 227 228 Register ToRegister(int index) const; 229 XMMRegister ToDoubleRegister(int index) const; 230 int ToInteger32(LConstantOperand* op) const; 231 232 // Specific math operations - used from DoUnaryMathOperation. 233 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 234 void DoMathAbs(LUnaryMathOperation* instr); 235 void DoMathFloor(LUnaryMathOperation* instr); 236 void DoMathRound(LUnaryMathOperation* instr); 237 void DoMathSqrt(LUnaryMathOperation* instr); 238 void DoMathPowHalf(LUnaryMathOperation* instr); 239 void DoMathLog(LUnaryMathOperation* instr); 240 void DoMathCos(LUnaryMathOperation* instr); 241 void DoMathSin(LUnaryMathOperation* instr); 242 243 // Support for recording safepoint and position information. 244 void RecordSafepoint(LPointerMap* pointers, 245 Safepoint::Kind kind, 246 int arguments, 247 int deoptimization_index); 248 void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); 249 void RecordSafepoint(int deoptimization_index); 250 void RecordSafepointWithRegisters(LPointerMap* pointers, 251 int arguments, 252 int deoptimization_index); 253 void RecordPosition(int position); 254 255 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 256 void EmitGoto(int block, LDeferredCode* deferred_stack_check = NULL); 257 void EmitBranch(int left_block, int right_block, Condition cc); 258 void EmitCmpI(LOperand* left, LOperand* right); 259 void EmitNumberUntagD(Register input, 260 XMMRegister result, 261 bool deoptimize_on_undefined, 262 LEnvironment* env); 263 264 // Emits optimized code for typeof x == "y". Modifies input register. 265 // Returns the condition on which a final split to 266 // true and false label should be made, to optimize fallthrough. 267 Condition EmitTypeofIs(Label* true_label, Label* false_label, 268 Register input, Handle<String> type_name); 269 270 // Emits optimized code for %_IsObject(x). Preserves input register. 271 // Returns the condition on which a final split to 272 // true and false label should be made, to optimize fallthrough. 273 Condition EmitIsObject(Register input, 274 Register temp1, 275 Register temp2, 276 Label* is_not_object, 277 Label* is_object); 278 279 // Emits optimized code for %_IsConstructCall(). 280 // Caller should branch on equal condition. 281 void EmitIsConstructCall(Register temp); 282 283 void EmitLoadField(Register result, 284 Register object, 285 Handle<Map> type, 286 Handle<String> name); 287 288 LChunk* const chunk_; 289 MacroAssembler* const masm_; 290 CompilationInfo* const info_; 291 292 int current_block_; 293 int current_instruction_; 294 const ZoneList<LInstruction*>* instructions_; 295 ZoneList<LEnvironment*> deoptimizations_; 296 ZoneList<Handle<Object> > deoptimization_literals_; 297 int inlined_function_count_; 298 Scope* const scope_; 299 Status status_; 300 TranslationBuffer translations_; 301 ZoneList<LDeferredCode*> deferred_; 302 int osr_pc_offset_; 303 304 struct DeoptimizationRelocSize { 305 int min_size; 306 int last_pc_offset; 307 }; 308 309 DeoptimizationRelocSize deoptimization_reloc_size; 310 311 // Builder that keeps track of safepoints in the code. The table 312 // itself is emitted at the end of the generated code. 313 SafepointTableBuilder safepoints_; 314 315 // Compiler from a set of parallel moves to a sequential list of moves. 316 LGapResolver resolver_; 317 318 Safepoint::Kind expected_safepoint_kind_; 319 320 class PushSafepointRegistersScope BASE_EMBEDDED { 321 public: 322 explicit PushSafepointRegistersScope(LCodeGen* codegen) 323 : codegen_(codegen) { 324 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); 325 codegen_->masm_->PushSafepointRegisters(); 326 codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters; 327 } 328 329 ~PushSafepointRegistersScope() { 330 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters); 331 codegen_->masm_->PopSafepointRegisters(); 332 codegen_->expected_safepoint_kind_ = Safepoint::kSimple; 333 } 334 335 private: 336 LCodeGen* codegen_; 337 }; 338 339 friend class LDeferredCode; 340 friend class LEnvironment; 341 friend class SafepointGenerator; 342 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 343 }; 344 345 346 class LDeferredCode: public ZoneObject { 347 public: 348 explicit LDeferredCode(LCodeGen* codegen) 349 : codegen_(codegen), external_exit_(NULL) { 350 codegen->AddDeferredCode(this); 351 } 352 353 virtual ~LDeferredCode() { } 354 virtual void Generate() = 0; 355 356 void SetExit(Label *exit) { external_exit_ = exit; } 357 Label* entry() { return &entry_; } 358 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 359 360 protected: 361 LCodeGen* codegen() const { return codegen_; } 362 MacroAssembler* masm() const { return codegen_->masm(); } 363 364 private: 365 LCodeGen* codegen_; 366 Label entry_; 367 Label exit_; 368 Label* external_exit_; 369 }; 370 371 } } // namespace v8::internal 372 373 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ 374