lithium-codegen-arm.h revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
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 deopt_jump_table_(4), 55 deoptimization_literals_(8), 56 inlined_function_count_(0), 57 scope_(info->scope()), 58 status_(UNUSED), 59 deferred_(8), 60 osr_pc_offset_(-1), 61 last_lazy_deopt_pc_(0), 62 resolver_(this), 63 expected_safepoint_kind_(Safepoint::kSimple) { 64 PopulateDeoptimizationLiteralsWithInlinedFunctions(); 65 } 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 // LOperand must be a register. 77 Register ToRegister(LOperand* op) const; 78 79 // LOperand is loaded into scratch, unless already a register. 80 Register EmitLoadRegister(LOperand* op, Register scratch); 81 82 // LOperand must be a double register. 83 DoubleRegister ToDoubleRegister(LOperand* op) const; 84 85 // LOperand is loaded into dbl_scratch, unless already a double register. 86 DoubleRegister EmitLoadDoubleRegister(LOperand* op, 87 SwVfpRegister flt_scratch, 88 DoubleRegister dbl_scratch); 89 int ToInteger32(LConstantOperand* op) const; 90 double ToDouble(LConstantOperand* op) const; 91 Operand ToOperand(LOperand* op); 92 MemOperand ToMemOperand(LOperand* op) const; 93 // Returns a MemOperand pointing to the high word of a DoubleStackSlot. 94 MemOperand ToHighMemOperand(LOperand* op) const; 95 96 // Try to generate code for the entire chunk, but it may fail if the 97 // chunk contains constructs we cannot handle. Returns true if the 98 // code generation attempt succeeded. 99 bool GenerateCode(); 100 101 // Finish the code by setting stack height, safepoint, and bailout 102 // information on it. 103 void FinishCode(Handle<Code> code); 104 105 // Deferred code support. 106 template<int T> 107 void DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, 108 Token::Value op); 109 void DoDeferredNumberTagD(LNumberTagD* instr); 110 void DoDeferredNumberTagI(LNumberTagI* instr); 111 void DoDeferredTaggedToI(LTaggedToI* instr); 112 void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr); 113 void DoDeferredStackCheck(LStackCheck* instr); 114 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 115 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); 116 void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 117 Label* map_check); 118 119 // Parallel move support. 120 void DoParallelMove(LParallelMove* move); 121 void DoGap(LGap* instr); 122 123 // Emit frame translation commands for an environment. 124 void WriteTranslation(LEnvironment* environment, Translation* translation); 125 126 // Declare methods that deal with the individual node types. 127#define DECLARE_DO(type) void Do##type(L##type* node); 128 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 129#undef DECLARE_DO 130 131 private: 132 enum Status { 133 UNUSED, 134 GENERATING, 135 DONE, 136 ABORTED 137 }; 138 139 bool is_unused() const { return status_ == UNUSED; } 140 bool is_generating() const { return status_ == GENERATING; } 141 bool is_done() const { return status_ == DONE; } 142 bool is_aborted() const { return status_ == ABORTED; } 143 144 StrictModeFlag strict_mode_flag() const { 145 return info()->is_classic_mode() ? kNonStrictMode : kStrictMode; 146 } 147 148 LChunk* chunk() const { return chunk_; } 149 Scope* scope() const { return scope_; } 150 HGraph* graph() const { return chunk_->graph(); } 151 152 Register scratch0() { return r9; } 153 DwVfpRegister double_scratch0() { return kScratchDoubleReg; } 154 155 int GetNextEmittedBlock(int block); 156 LInstruction* GetNextInstruction(); 157 158 void EmitClassOfTest(Label* if_true, 159 Label* if_false, 160 Handle<String> class_name, 161 Register input, 162 Register temporary, 163 Register temporary2); 164 165 int GetStackSlotCount() const { return chunk()->spill_slot_count(); } 166 int GetParameterCount() const { return scope()->num_parameters(); } 167 168 void Abort(const char* format, ...); 169 void Comment(const char* format, ...); 170 171 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code); } 172 173 // Code generation passes. Returns true if code generation should 174 // continue. 175 bool GeneratePrologue(); 176 bool GenerateBody(); 177 bool GenerateDeferredCode(); 178 bool GenerateDeoptJumpTable(); 179 bool GenerateSafepointTable(); 180 181 enum SafepointMode { 182 RECORD_SIMPLE_SAFEPOINT, 183 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS 184 }; 185 186 void CallCode(Handle<Code> code, 187 RelocInfo::Mode mode, 188 LInstruction* instr); 189 190 void CallCodeGeneric(Handle<Code> code, 191 RelocInfo::Mode mode, 192 LInstruction* instr, 193 SafepointMode safepoint_mode); 194 195 void CallRuntime(const Runtime::Function* function, 196 int num_arguments, 197 LInstruction* instr); 198 199 void CallRuntime(Runtime::FunctionId id, 200 int num_arguments, 201 LInstruction* instr) { 202 const Runtime::Function* function = Runtime::FunctionForId(id); 203 CallRuntime(function, num_arguments, instr); 204 } 205 206 void CallRuntimeFromDeferred(Runtime::FunctionId id, 207 int argc, 208 LInstruction* instr); 209 210 // Generate a direct call to a known function. Expects the function 211 // to be in r1. 212 void CallKnownFunction(Handle<JSFunction> function, 213 int arity, 214 LInstruction* instr, 215 CallKind call_kind); 216 217 void LoadHeapObject(Register result, Handle<HeapObject> object); 218 219 void RecordSafepointWithLazyDeopt(LInstruction* instr, 220 SafepointMode safepoint_mode); 221 222 void RegisterEnvironmentForDeoptimization(LEnvironment* environment, 223 Safepoint::DeoptMode mode); 224 void DeoptimizeIf(Condition cc, LEnvironment* environment); 225 226 void AddToTranslation(Translation* translation, 227 LOperand* op, 228 bool is_tagged); 229 void PopulateDeoptimizationData(Handle<Code> code); 230 int DefineDeoptimizationLiteral(Handle<Object> literal); 231 232 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 233 234 Register ToRegister(int index) const; 235 DoubleRegister ToDoubleRegister(int index) const; 236 237 // Specific math operations - used from DoUnaryMathOperation. 238 void EmitIntegerMathAbs(LUnaryMathOperation* instr); 239 void DoMathAbs(LUnaryMathOperation* instr); 240 void DoMathFloor(LUnaryMathOperation* instr); 241 void DoMathRound(LUnaryMathOperation* instr); 242 void DoMathSqrt(LUnaryMathOperation* instr); 243 void DoMathPowHalf(LUnaryMathOperation* instr); 244 void DoMathLog(LUnaryMathOperation* instr); 245 void DoMathTan(LUnaryMathOperation* instr); 246 void DoMathCos(LUnaryMathOperation* instr); 247 void DoMathSin(LUnaryMathOperation* instr); 248 249 // Support for recording safepoint and position information. 250 void RecordSafepoint(LPointerMap* pointers, 251 Safepoint::Kind kind, 252 int arguments, 253 Safepoint::DeoptMode mode); 254 void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode); 255 void RecordSafepoint(Safepoint::DeoptMode mode); 256 void RecordSafepointWithRegisters(LPointerMap* pointers, 257 int arguments, 258 Safepoint::DeoptMode mode); 259 void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers, 260 int arguments, 261 Safepoint::DeoptMode mode); 262 void RecordPosition(int position); 263 264 static Condition TokenToCondition(Token::Value op, bool is_unsigned); 265 void EmitGoto(int block); 266 void EmitBranch(int left_block, int right_block, Condition cc); 267 void EmitNumberUntagD(Register input, 268 DoubleRegister result, 269 bool deoptimize_on_undefined, 270 LEnvironment* env); 271 272 // Emits optimized code for typeof x == "y". Modifies input register. 273 // Returns the condition on which a final split to 274 // true and false label should be made, to optimize fallthrough. 275 Condition EmitTypeofIs(Label* true_label, 276 Label* false_label, 277 Register input, 278 Handle<String> type_name); 279 280 // Emits optimized code for %_IsObject(x). Preserves input register. 281 // Returns the condition on which a final split to 282 // true and false label should be made, to optimize fallthrough. 283 Condition EmitIsObject(Register input, 284 Register temp1, 285 Label* is_not_object, 286 Label* is_object); 287 288 // Emits optimized code for %_IsString(x). Preserves input register. 289 // Returns the condition on which a final split to 290 // true and false label should be made, to optimize fallthrough. 291 Condition EmitIsString(Register input, 292 Register temp1, 293 Label* is_not_string); 294 295 // Emits optimized code for %_IsConstructCall(). 296 // Caller should branch on equal condition. 297 void EmitIsConstructCall(Register temp1, Register temp2); 298 299 void EmitLoadFieldOrConstantFunction(Register result, 300 Register object, 301 Handle<Map> type, 302 Handle<String> name); 303 304 // Emits optimized code to deep-copy the contents of statically known 305 // object graphs (e.g. object literal boilerplate). 306 void EmitDeepCopy(Handle<JSObject> object, 307 Register result, 308 Register source, 309 int* offset); 310 311 struct JumpTableEntry { 312 explicit inline JumpTableEntry(Address entry) 313 : label(), 314 address(entry) { } 315 Label label; 316 Address address; 317 }; 318 319 void EnsureSpaceForLazyDeopt(); 320 321 LChunk* const chunk_; 322 MacroAssembler* const masm_; 323 CompilationInfo* const info_; 324 325 int current_block_; 326 int current_instruction_; 327 const ZoneList<LInstruction*>* instructions_; 328 ZoneList<LEnvironment*> deoptimizations_; 329 ZoneList<JumpTableEntry> deopt_jump_table_; 330 ZoneList<Handle<Object> > deoptimization_literals_; 331 int inlined_function_count_; 332 Scope* const scope_; 333 Status status_; 334 TranslationBuffer translations_; 335 ZoneList<LDeferredCode*> deferred_; 336 int osr_pc_offset_; 337 int last_lazy_deopt_pc_; 338 339 // Builder that keeps track of safepoints in the code. The table 340 // itself is emitted at the end of the generated code. 341 SafepointTableBuilder safepoints_; 342 343 // Compiler from a set of parallel moves to a sequential list of moves. 344 LGapResolver resolver_; 345 346 Safepoint::Kind expected_safepoint_kind_; 347 348 class PushSafepointRegistersScope BASE_EMBEDDED { 349 public: 350 PushSafepointRegistersScope(LCodeGen* codegen, 351 Safepoint::Kind kind) 352 : codegen_(codegen) { 353 ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); 354 codegen_->expected_safepoint_kind_ = kind; 355 356 switch (codegen_->expected_safepoint_kind_) { 357 case Safepoint::kWithRegisters: 358 codegen_->masm_->PushSafepointRegisters(); 359 break; 360 case Safepoint::kWithRegistersAndDoubles: 361 codegen_->masm_->PushSafepointRegistersAndDoubles(); 362 break; 363 default: 364 UNREACHABLE(); 365 } 366 } 367 368 ~PushSafepointRegistersScope() { 369 Safepoint::Kind kind = codegen_->expected_safepoint_kind_; 370 ASSERT((kind & Safepoint::kWithRegisters) != 0); 371 switch (kind) { 372 case Safepoint::kWithRegisters: 373 codegen_->masm_->PopSafepointRegisters(); 374 break; 375 case Safepoint::kWithRegistersAndDoubles: 376 codegen_->masm_->PopSafepointRegistersAndDoubles(); 377 break; 378 default: 379 UNREACHABLE(); 380 } 381 codegen_->expected_safepoint_kind_ = Safepoint::kSimple; 382 } 383 384 private: 385 LCodeGen* codegen_; 386 }; 387 388 friend class LDeferredCode; 389 friend class LEnvironment; 390 friend class SafepointGenerator; 391 DISALLOW_COPY_AND_ASSIGN(LCodeGen); 392}; 393 394 395class LDeferredCode: public ZoneObject { 396 public: 397 explicit LDeferredCode(LCodeGen* codegen) 398 : codegen_(codegen), 399 external_exit_(NULL), 400 instruction_index_(codegen->current_instruction_) { 401 codegen->AddDeferredCode(this); 402 } 403 404 virtual ~LDeferredCode() { } 405 virtual void Generate() = 0; 406 virtual LInstruction* instr() = 0; 407 408 void SetExit(Label *exit) { external_exit_ = exit; } 409 Label* entry() { return &entry_; } 410 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } 411 int instruction_index() const { return instruction_index_; } 412 413 protected: 414 LCodeGen* codegen() const { return codegen_; } 415 MacroAssembler* masm() const { return codegen_->masm(); } 416 417 private: 418 LCodeGen* codegen_; 419 Label entry_; 420 Label exit_; 421 Label* external_exit_; 422 int instruction_index_; 423}; 424 425} } // namespace v8::internal 426 427#endif // V8_ARM_LITHIUM_CODEGEN_ARM_H_ 428