1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_ARM64_LITHIUM_CODEGEN_ARM64_H_ 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_ARM64_LITHIUM_CODEGEN_ARM64_H_ 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/lithium-arm64.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/lithium-gap-resolver-arm64.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/lithium-codegen.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/safepoint-table.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Forward declarations. 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LDeferredCode; 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SafepointGenerator; 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BranchGenerator; 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LCodeGen: public LCodeGenBase { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LCodeGenBase(chunk, assembler, info), 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deoptimizations_(4, info->zone()), 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jump_table_(4, info->zone()), 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deoptimization_literals_(8, info->zone()), 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inlined_function_count_(0), 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scope_(info->scope()), 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translations_(info->zone()), 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred_(8, info->zone()), 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch osr_pc_offset_(-1), 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_is_built_(false), 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_(info->zone()), 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolver_(this), 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expected_safepoint_kind_(Safepoint::kSimple), 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch after_push_argument_(false), 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inlined_arguments_(false) { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PopulateDeoptimizationLiteralsWithInlinedFunctions(); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~LCodeGen() { 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!after_push_argument_ || inlined_arguments_); 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Simple accessors. 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Scope* scope() const { return scope_; } 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int LookupDestination(int block_id) const { 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return chunk()->LookupDestination(block_id); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsNextEmittedBlock(int block_id) const { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LookupDestination(block_id) == GetNextEmittedBlock(); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool NeedsEagerFrame() const { 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetStackSlotCount() > 0 || 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info()->is_non_deferred_calling() || 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !info()->IsStub() || 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info()->requires_frame(); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool NeedsDeferredFrame() const { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !NeedsEagerFrame() && info()->is_deferred_calling(); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LinkRegisterStatus GetLinkRegisterState() const { 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved; 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try to generate code for the entire chunk, but it may fail if the 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // chunk contains constructs we cannot handle. Returns true if the 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code generation attempt succeeded. 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool GenerateCode(); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Finish the code by setting stack height, safepoint, and bailout 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // information on it. 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FinishCode(Handle<Code> code); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 }; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Support for converting LOperands to assembler types. 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register ToRegister(LOperand* op) const; 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register ToRegister32(LOperand* op) const; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand ToOperand(LOperand* op); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand ToOperand32(LOperand* op); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum StackMode { kMustUseFramePointer, kCanUseStackPointer }; 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand ToMemOperand(LOperand* op, 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackMode stack_mode = kCanUseStackPointer) const; 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> ToHandle(LConstantOperand* op) const; 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <class LI> 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand ToShiftedRightOperand32(LOperand* right, LI* shift_info); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int JSShiftAmountFromLConstant(LOperand* constant) { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ToInteger32(LConstantOperand::cast(constant)) & 0x1f; 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): Examine these helpers and check that they make sense. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // IsInteger32Constant returns true for smi constants, for example. 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsInteger32Constant(LConstantOperand* op) const; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsSmi(LConstantOperand* op) const; 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t ToInteger32(LConstantOperand* op) const; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi* ToSmi(LConstantOperand* op) const; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double ToDouble(LConstantOperand* op) const; 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoubleRegister ToDoubleRegister(LOperand* op) const; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Declare methods that deal with the individual node types. 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DECLARE_DO(type) void Do##type(L##type* node); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DECLARE_DO 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return a double scratch register which can be used locally 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // when generating code for a lithium instruction. 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoubleRegister double_scratch() { return crankshaft_fp_scratch; } 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deferred code support. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredNumberTagD(LNumberTagD* instr); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredStackCheck(LStackCheck* instr); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredStringCharFromCode(LStringCharFromCode* instr); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredMathAbsTagged(LMathAbsTagged* instr, 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* exit, 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* allocation_entry); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredNumberTagU(LInstruction* instr, 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* value, 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp1, 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp2); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredTaggedToI(LTaggedToI* instr, 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* value, 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp1, 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp2); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredAllocate(LAllocate* instr); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredInstanceMigration(LCheckMaps* instr, Register object); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Condition TokenToCondition(Token::Value op, bool is_unsigned); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitGoto(int block); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DoGap(LGap* instr); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generic version of EmitBranch. It contains some code to avoid emitting a 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // branch on the next emitted basic block where we could just fall-through. 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // You shouldn't use that directly but rather consider one of the helper like 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LCodeGen::EmitBranch, LCodeGen::EmitCompareAndBranch... 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitBranchGeneric(InstrType instr, 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const BranchGenerator& branch); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitBranch(InstrType instr, Condition condition); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitCompareAndBranch(InstrType instr, 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition, 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& lhs, 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& rhs); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitTestAndBranch(InstrType instr, 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition, 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& value, 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t mask); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitBranchIfNonZeroNumber(InstrType instr, 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& value, 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& scratch); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitBranchIfHeapNumber(InstrType instr, 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& value); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InstrType> 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitBranchIfRoot(InstrType instr, 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& value, 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex index); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emits optimized code to deep-copy the contents of statically known object 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // graphs (e.g. object literal boilerplate). Expects a pointer to the 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // allocated destination object in the result register, and a pointer to the 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // source object in the source register. 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitDeepCopy(Handle<JSObject> object, 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register source, 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* offset, 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <class T> 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitVectorLoadICRegisters(T* instr); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emits optimized code for %_IsString(x). Preserves input register. 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the condition on which a final split to 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // true and false label should be made, to optimize fallthrough. 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition EmitIsString(Register input, Register temp1, Label* is_not_string, 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck check_needed); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int DefineDeoptimizationLiteral(Handle<Object> literal); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PopulateDeoptimizationData(Handle<Code> code); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PopulateDeoptimizationLiteralsWithInlinedFunctions(); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand BuildSeqStringOperand(Register string, 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp, 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* index, 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeBranch(LInstruction* instr, const char* detail, 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchType branch_type, Register reg = NoReg, 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int bit = -1, 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType* override_bailout_type = NULL); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Deoptimize(LInstruction* instr, 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType* override_bailout_type = NULL, 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIf(Condition cond, LInstruction* instr, 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfZero(Register rt, LInstruction* instr, 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfNotZero(Register rt, LInstruction* instr, 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfNegative(Register rt, LInstruction* instr, 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfSmi(Register rt, LInstruction* instr, 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfNotSmi(Register rt, LInstruction* instr, 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfRoot(Register rt, Heap::RootListIndex index, 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, const char* detail = NULL); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfNotRoot(Register rt, Heap::RootListIndex index, 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, const char* detail = NULL); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfMinusZero(DoubleRegister input, LInstruction* instr, 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfBitSet(Register rt, int bit, LInstruction* instr, 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeoptimizeIfBitClear(Register rt, int bit, LInstruction* instr, 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail = NULL); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand PrepareKeyedExternalArrayOperand(Register key, 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register base, 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool key_is_smi, 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool key_is_constant, 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_key, 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind, 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int base_offset); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand PrepareKeyedArrayOperand(Register base, 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool key_is_tagged, 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind, 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation representation, 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int base_offset); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RegisterEnvironmentForDeoptimization(LEnvironment* environment, 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode mode); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int GetStackSlotCount() const { return chunk()->spill_slot_count(); } 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); } 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit frame translation commands for an environment. 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void WriteTranslation(LEnvironment* environment, Translation* translation); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddToTranslation(LEnvironment* environment, 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Translation* translation, 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* op, 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_tagged, 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_uint32, 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* object_index_pointer, 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* dematerialized_index_pointer); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SaveCallerDoubles(); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RestoreCallerDoubles(); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code generation steps. Returns true if code generation should continue. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenerateBodyInstructionPre(LInstruction* instr) OVERRIDE; 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool GeneratePrologue(); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool GenerateDeferredCode(); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool GenerateJumpTable(); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool GenerateSafepointTable(); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generates the custom OSR entrypoint and sets the osr_pc_offset. 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GenerateOsrPrologue(); 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum SafepointMode { 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RECORD_SIMPLE_SAFEPOINT, 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallCode(Handle<Code> code, 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode mode, 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallCodeGeneric(Handle<Code> code, 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode mode, 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointMode safepoint_mode); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallRuntime(const Runtime::Function* function, 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_arguments, 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles = kDontSaveFPRegs); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallRuntime(Runtime::FunctionId id, 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_arguments, 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr) { 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Runtime::Function* function = Runtime::FunctionForId(id); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(function, num_arguments, instr); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadContextFromDeferred(LOperand* context); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallRuntimeFromDeferred(Runtime::FunctionId id, 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc, 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* context); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate a direct call to a known function. 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the function is already loaded into x1 by the caller, function_reg may 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be set to x1. Otherwise, it must be NoReg, and CallKnownFunction will 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // automatically load it. 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallKnownFunction(Handle<JSFunction> function, 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int formal_parameter_count, 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arity, 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function_reg = NoReg); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Support for recording safepoint and position information. 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordAndWritePosition(int position) OVERRIDE; 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordSafepoint(LPointerMap* pointers, 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::Kind kind, 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arguments, 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode mode); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordSafepoint(Safepoint::DeoptMode mode); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordSafepointWithRegisters(LPointerMap* pointers, 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arguments, 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode mode); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordSafepointWithLazyDeopt(LInstruction* instr, 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointMode safepoint_mode); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EnsureSpaceForLazyDeopt(int space_needed) OVERRIDE; 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<LEnvironment*> deoptimizations_; 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Deoptimizer::JumpTableEntry*> jump_table_; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Handle<Object> > deoptimization_literals_; 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int inlined_function_count_; 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Scope* const scope_; 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TranslationBuffer translations_; 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<LDeferredCode*> deferred_; 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int osr_pc_offset_; 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool frame_is_built_; 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Builder that keeps track of safepoints in the code. The table itself is 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // emitted at the end of the generated code. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointTableBuilder safepoints_; 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compiler from a set of parallel moves to a sequential list of moves. 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LGapResolver resolver_; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::Kind expected_safepoint_kind_; 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This flag is true when we are after a push (but before a call). 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In this situation, jssp no longer references the end of the stack slots so, 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can only reference a stack slot via fp. 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool after_push_argument_; 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we have inlined arguments, we are no longer able to use jssp because 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jssp is modified and we never know if we are in a block after or before 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the pop of the arguments (which restores jssp). 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool inlined_arguments_; 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int old_position_; 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class PushSafepointRegistersScope BASE_EMBEDDED { 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit PushSafepointRegistersScope(LCodeGen* codegen) 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : codegen_(codegen) { 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(codegen_->info()->is_calling()); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters; 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UseScratchRegisterScope temps(codegen_->masm_); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of lr which must be saved on the stack (the call to 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the stub will clobber it). 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register to_be_pushed_lr = 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch temps.UnsafeAcquire(StoreRegistersStateStub::to_be_pushed_lr()); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen_->masm_->Mov(to_be_pushed_lr, lr); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreRegistersStateStub stub(codegen_->isolate()); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen_->masm_->CallStub(&stub); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~PushSafepointRegistersScope() { 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters); 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RestoreRegistersStateStub stub(codegen_->isolate()); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen_->masm_->CallStub(&stub); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen_->expected_safepoint_kind_ = Safepoint::kSimple; 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen* codegen_; 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class LDeferredCode; 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class SafepointGenerator; 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_COPY_AND_ASSIGN(LCodeGen); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LDeferredCode: public ZoneObject { 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit LDeferredCode(LCodeGen* codegen) 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : codegen_(codegen), 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch external_exit_(NULL), 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instruction_index_(codegen->current_instruction_) { 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen->AddDeferredCode(this); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~LDeferredCode() { } 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() = 0; 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() = 0; 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetExit(Label* exit) { external_exit_ = exit; } 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* entry() { return &entry_; } 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* exit() { return (external_exit_ != NULL) ? external_exit_ : &exit_; } 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int instruction_index() const { return instruction_index_; } 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen* codegen() const { return codegen_; } 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm() const { return codegen_->masm(); } 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen* codegen_; 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label entry_; 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label exit_; 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* external_exit_; 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int instruction_index_; 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This is the abstract class used by EmitBranchGeneric. 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It is used to emit code for conditional branching. The Emit() function 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// emits code to branch when the condition holds and EmitInverted() emits 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the branch when the inverted condition is verified. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For actual examples of condition see the concrete implementation in 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// lithium-codegen-arm64.cc (e.g. BranchOnCondition, CompareAndBranch). 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BranchGenerator BASE_EMBEDDED { 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BranchGenerator(LCodeGen* codegen) 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : codegen_(codegen) { } 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~BranchGenerator() { } 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Emit(Label* label) const = 0; 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void EmitInverted(Label* label) const = 0; 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm() const { return codegen_->masm(); } 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen* codegen_; 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_ARM64_LITHIUM_CODEGEN_ARM64_H_ 474