Home | History | Annotate | Download | only in ia32
      1 // Copyright 2012 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 "ia32/lithium-gap-resolver-ia32.h"
     36 #include "safepoint-table.h"
     37 #include "scopes.h"
     38 #include "v8utils.h"
     39 
     40 namespace v8 {
     41 namespace internal {
     42 
     43 // Forward declarations.
     44 class LDeferredCode;
     45 class LGapNode;
     46 class SafepointGenerator;
     47 
     48 class LCodeGen BASE_EMBEDDED {
     49  public:
     50   LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
     51       : zone_(info->zone()),
     52         chunk_(static_cast<LPlatformChunk*>(chunk)),
     53         masm_(assembler),
     54         info_(info),
     55         current_block_(-1),
     56         current_instruction_(-1),
     57         instructions_(chunk->instructions()),
     58         deoptimizations_(4, info->zone()),
     59         jump_table_(4, info->zone()),
     60         deoptimization_literals_(8, info->zone()),
     61         inlined_function_count_(0),
     62         scope_(info->scope()),
     63         status_(UNUSED),
     64         translations_(info->zone()),
     65         deferred_(8, info->zone()),
     66         dynamic_frame_alignment_(false),
     67         support_aligned_spilled_doubles_(false),
     68         osr_pc_offset_(-1),
     69         last_lazy_deopt_pc_(0),
     70         frame_is_built_(false),
     71         x87_stack_depth_(0),
     72         safepoints_(info->zone()),
     73         resolver_(this),
     74         expected_safepoint_kind_(Safepoint::kSimple),
     75         old_position_(RelocInfo::kNoPosition) {
     76     PopulateDeoptimizationLiteralsWithInlinedFunctions();
     77   }
     78 
     79   // Simple accessors.
     80   MacroAssembler* masm() const { return masm_; }
     81   CompilationInfo* info() const { return info_; }
     82   Isolate* isolate() const { return info_->isolate(); }
     83   Factory* factory() const { return isolate()->factory(); }
     84   Heap* heap() const { return isolate()->heap(); }
     85   Zone* zone() const { return zone_; }
     86 
     87   int LookupDestination(int block_id) const {
     88     return chunk()->LookupDestination(block_id);
     89   }
     90 
     91   bool IsNextEmittedBlock(int block_id) const {
     92     return LookupDestination(block_id) == GetNextEmittedBlock();
     93   }
     94 
     95   bool NeedsEagerFrame() const {
     96     return GetStackSlotCount() > 0 ||
     97         info()->is_non_deferred_calling() ||
     98         !info()->IsStub() ||
     99         info()->requires_frame();
    100   }
    101   bool NeedsDeferredFrame() const {
    102     return !NeedsEagerFrame() && info()->is_deferred_calling();
    103   }
    104 
    105   // Support for converting LOperands to assembler types.
    106   Operand ToOperand(LOperand* op) const;
    107   Register ToRegister(LOperand* op) const;
    108   XMMRegister ToDoubleRegister(LOperand* op) const;
    109   X87Register ToX87Register(LOperand* op) const;
    110 
    111   bool IsInteger32(LConstantOperand* op) const;
    112   bool IsSmi(LConstantOperand* op) const;
    113   Immediate ToImmediate(LOperand* op, const Representation& r) const {
    114     return Immediate(ToRepresentation(LConstantOperand::cast(op), r));
    115   }
    116   double ToDouble(LConstantOperand* op) const;
    117 
    118   // Support for non-sse2 (x87) floating point stack handling.
    119   // These functions maintain the mapping of physical stack registers to our
    120   // virtual registers between instructions.
    121   enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand };
    122 
    123   void X87Mov(X87Register reg, Operand src,
    124       X87OperandType operand = kX87DoubleOperand);
    125   void X87Mov(Operand src, X87Register reg);
    126 
    127   void X87PrepareBinaryOp(
    128       X87Register left, X87Register right, X87Register result);
    129 
    130   void X87LoadForUsage(X87Register reg);
    131   void X87PrepareToWrite(X87Register reg);
    132   void X87CommitWrite(X87Register reg);
    133 
    134   Handle<Object> ToHandle(LConstantOperand* op) const;
    135 
    136   // The operand denoting the second word (the one with a higher address) of
    137   // a double stack slot.
    138   Operand HighOperand(LOperand* op);
    139 
    140   // Try to generate code for the entire chunk, but it may fail if the
    141   // chunk contains constructs we cannot handle. Returns true if the
    142   // code generation attempt succeeded.
    143   bool GenerateCode();
    144 
    145   // Finish the code by setting stack height, safepoint, and bailout
    146   // information on it.
    147   void FinishCode(Handle<Code> code);
    148 
    149   // Deferred code support.
    150   void DoDeferredNumberTagD(LNumberTagD* instr);
    151 
    152   enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
    153   void DoDeferredNumberTagI(LInstruction* instr,
    154                             LOperand* value,
    155                             IntegerSignedness signedness);
    156 
    157   void DoDeferredTaggedToI(LTaggedToI* instr);
    158   void DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr);
    159   void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
    160   void DoDeferredStackCheck(LStackCheck* instr);
    161   void DoDeferredRandom(LRandom* instr);
    162   void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
    163   void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
    164   void DoDeferredAllocate(LAllocate* instr);
    165   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
    166                                        Label* map_check);
    167   void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
    168 
    169   // Parallel move support.
    170   void DoParallelMove(LParallelMove* move);
    171   void DoGap(LGap* instr);
    172 
    173   // Emit frame translation commands for an environment.
    174   void WriteTranslation(LEnvironment* environment, Translation* translation);
    175 
    176   void EnsureRelocSpaceForDeoptimization();
    177 
    178   // Declare methods that deal with the individual node types.
    179 #define DECLARE_DO(type) void Do##type(L##type* node);
    180   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
    181 #undef DECLARE_DO
    182 
    183  private:
    184   enum Status {
    185     UNUSED,
    186     GENERATING,
    187     DONE,
    188     ABORTED
    189   };
    190 
    191   bool is_unused() const { return status_ == UNUSED; }
    192   bool is_generating() const { return status_ == GENERATING; }
    193   bool is_done() const { return status_ == DONE; }
    194   bool is_aborted() const { return status_ == ABORTED; }
    195 
    196   StrictModeFlag strict_mode_flag() const {
    197     return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
    198   }
    199 
    200   LPlatformChunk* chunk() const { return chunk_; }
    201   Scope* scope() const { return scope_; }
    202   HGraph* graph() const { return chunk()->graph(); }
    203 
    204   int GetNextEmittedBlock() const;
    205 
    206   void EmitClassOfTest(Label* if_true,
    207                        Label* if_false,
    208                        Handle<String> class_name,
    209                        Register input,
    210                        Register temporary,
    211                        Register temporary2);
    212 
    213   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
    214 
    215   void Abort(BailoutReason reason);
    216   void FPRINTF_CHECKING Comment(const char* format, ...);
    217 
    218   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
    219 
    220   // Code generation passes.  Returns true if code generation should
    221   // continue.
    222   bool GeneratePrologue();
    223   bool GenerateBody();
    224   bool GenerateDeferredCode();
    225   bool GenerateJumpTable();
    226   bool GenerateSafepointTable();
    227 
    228   enum SafepointMode {
    229     RECORD_SIMPLE_SAFEPOINT,
    230     RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
    231   };
    232 
    233   void CallCode(Handle<Code> code,
    234                 RelocInfo::Mode mode,
    235                 LInstruction* instr);
    236 
    237   void CallCodeGeneric(Handle<Code> code,
    238                        RelocInfo::Mode mode,
    239                        LInstruction* instr,
    240                        SafepointMode safepoint_mode);
    241 
    242   void CallRuntime(const Runtime::Function* fun,
    243                    int argc,
    244                    LInstruction* instr);
    245 
    246   void CallRuntime(Runtime::FunctionId id,
    247                    int argc,
    248                    LInstruction* instr) {
    249     const Runtime::Function* function = Runtime::FunctionForId(id);
    250     CallRuntime(function, argc, instr);
    251   }
    252 
    253   void CallRuntimeFromDeferred(Runtime::FunctionId id,
    254                                int argc,
    255                                LInstruction* instr,
    256                                LOperand* context);
    257 
    258   void LoadContextFromDeferred(LOperand* context);
    259 
    260   enum EDIState {
    261     EDI_UNINITIALIZED,
    262     EDI_CONTAINS_TARGET
    263   };
    264 
    265   // Generate a direct call to a known function.  Expects the function
    266   // to be in edi.
    267   void CallKnownFunction(Handle<JSFunction> function,
    268                          int formal_parameter_count,
    269                          int arity,
    270                          LInstruction* instr,
    271                          CallKind call_kind,
    272                          EDIState edi_state);
    273 
    274   void RecordSafepointWithLazyDeopt(LInstruction* instr,
    275                                     SafepointMode safepoint_mode);
    276 
    277   void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
    278                                             Safepoint::DeoptMode mode);
    279   void DeoptimizeIf(Condition cc,
    280                     LEnvironment* environment,
    281                     Deoptimizer::BailoutType bailout_type);
    282   void DeoptimizeIf(Condition cc, LEnvironment* environment);
    283   void ApplyCheckIf(Condition cc, LBoundsCheck* check);
    284 
    285   void AddToTranslation(LEnvironment* environment,
    286                         Translation* translation,
    287                         LOperand* op,
    288                         bool is_tagged,
    289                         bool is_uint32,
    290                         int* object_index_pointer,
    291                         int* dematerialized_index_pointer);
    292   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
    293   void PopulateDeoptimizationData(Handle<Code> code);
    294   int DefineDeoptimizationLiteral(Handle<Object> literal);
    295 
    296   void PopulateDeoptimizationLiteralsWithInlinedFunctions();
    297 
    298   Register ToRegister(int index) const;
    299   XMMRegister ToDoubleRegister(int index) const;
    300   X87Register ToX87Register(int index) const;
    301   int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
    302   int32_t ToInteger32(LConstantOperand* op) const;
    303   ExternalReference ToExternalReference(LConstantOperand* op) const;
    304 
    305   Operand BuildFastArrayOperand(LOperand* elements_pointer,
    306                                 LOperand* key,
    307                                 Representation key_representation,
    308                                 ElementsKind elements_kind,
    309                                 uint32_t offset,
    310                                 uint32_t additional_index = 0);
    311 
    312   void EmitIntegerMathAbs(LMathAbs* instr);
    313 
    314   // Support for recording safepoint and position information.
    315   void RecordSafepoint(LPointerMap* pointers,
    316                        Safepoint::Kind kind,
    317                        int arguments,
    318                        Safepoint::DeoptMode mode);
    319   void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
    320   void RecordSafepoint(Safepoint::DeoptMode mode);
    321   void RecordSafepointWithRegisters(LPointerMap* pointers,
    322                                     int arguments,
    323                                     Safepoint::DeoptMode mode);
    324   void RecordPosition(int position);
    325 
    326   void RecordAndUpdatePosition(int position);
    327 
    328   static Condition TokenToCondition(Token::Value op, bool is_unsigned);
    329   void EmitGoto(int block);
    330   template<class InstrType>
    331   void EmitBranch(InstrType instr, Condition cc);
    332   template<class InstrType>
    333   void EmitFalseBranch(InstrType instr, Condition cc);
    334   void EmitNumberUntagD(
    335       Register input,
    336       Register temp,
    337       XMMRegister result,
    338       bool allow_undefined_as_nan,
    339       bool deoptimize_on_minus_zero,
    340       LEnvironment* env,
    341       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
    342 
    343   void EmitNumberUntagDNoSSE2(
    344       Register input,
    345       Register temp,
    346       X87Register res_reg,
    347       bool allow_undefined_as_nan,
    348       bool deoptimize_on_minus_zero,
    349       LEnvironment* env,
    350       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
    351 
    352   // Emits optimized code for typeof x == "y".  Modifies input register.
    353   // Returns the condition on which a final split to
    354   // true and false label should be made, to optimize fallthrough.
    355   Condition EmitTypeofIs(Label* true_label,
    356                          Label* false_label,
    357                          Register input,
    358                          Handle<String> type_name);
    359 
    360   // Emits optimized code for %_IsObject(x).  Preserves input register.
    361   // Returns the condition on which a final split to
    362   // true and false label should be made, to optimize fallthrough.
    363   Condition EmitIsObject(Register input,
    364                          Register temp1,
    365                          Label* is_not_object,
    366                          Label* is_object);
    367 
    368   // Emits optimized code for %_IsString(x).  Preserves input register.
    369   // Returns the condition on which a final split to
    370   // true and false label should be made, to optimize fallthrough.
    371   Condition EmitIsString(Register input,
    372                          Register temp1,
    373                          Label* is_not_string,
    374                          SmiCheck check_needed);
    375 
    376   // Emits optimized code for %_IsConstructCall().
    377   // Caller should branch on equal condition.
    378   void EmitIsConstructCall(Register temp);
    379 
    380   // Emits optimized code to deep-copy the contents of statically known
    381   // object graphs (e.g. object literal boilerplate).
    382   void EmitDeepCopy(Handle<JSObject> object,
    383                     Register result,
    384                     Register source,
    385                     int* offset,
    386                     AllocationSiteMode mode);
    387 
    388   void EnsureSpaceForLazyDeopt();
    389   void DoLoadKeyedExternalArray(LLoadKeyed* instr);
    390   void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
    391   void DoLoadKeyedFixedArray(LLoadKeyed* instr);
    392   void DoStoreKeyedExternalArray(LStoreKeyed* instr);
    393   void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
    394   void DoStoreKeyedFixedArray(LStoreKeyed* instr);
    395 
    396   void EmitReturn(LReturn* instr, bool dynamic_frame_alignment);
    397 
    398   // Emits code for pushing either a tagged constant, a (non-double)
    399   // register, or a stack slot operand.
    400   void EmitPushTaggedOperand(LOperand* operand);
    401 
    402   void X87Fxch(X87Register reg, int other_slot = 0);
    403   void X87Fld(Operand src, X87OperandType opts);
    404   void X87Free(X87Register reg);
    405 
    406   void FlushX87StackIfNecessary(LInstruction* instr);
    407   void EmitFlushX87ForDeopt();
    408   bool X87StackContains(X87Register reg);
    409   int X87ArrayIndex(X87Register reg);
    410   int x87_st2idx(int pos);
    411 
    412 #ifdef _MSC_VER
    413   // On windows, you may not access the stack more than one page below
    414   // the most recently mapped page. To make the allocated area randomly
    415   // accessible, we write an arbitrary value to each page in range
    416   // esp + offset - page_size .. esp in turn.
    417   void MakeSureStackPagesMapped(int offset);
    418 #endif
    419 
    420   Zone* zone_;
    421   LPlatformChunk* const chunk_;
    422   MacroAssembler* const masm_;
    423   CompilationInfo* const info_;
    424 
    425   int current_block_;
    426   int current_instruction_;
    427   const ZoneList<LInstruction*>* instructions_;
    428   ZoneList<LEnvironment*> deoptimizations_;
    429   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
    430   ZoneList<Handle<Object> > deoptimization_literals_;
    431   int inlined_function_count_;
    432   Scope* const scope_;
    433   Status status_;
    434   TranslationBuffer translations_;
    435   ZoneList<LDeferredCode*> deferred_;
    436   bool dynamic_frame_alignment_;
    437   bool support_aligned_spilled_doubles_;
    438   int osr_pc_offset_;
    439   int last_lazy_deopt_pc_;
    440   bool frame_is_built_;
    441   X87Register x87_stack_[X87Register::kNumAllocatableRegisters];
    442   int x87_stack_depth_;
    443 
    444   // Builder that keeps track of safepoints in the code. The table
    445   // itself is emitted at the end of the generated code.
    446   SafepointTableBuilder safepoints_;
    447 
    448   // Compiler from a set of parallel moves to a sequential list of moves.
    449   LGapResolver resolver_;
    450 
    451   Safepoint::Kind expected_safepoint_kind_;
    452 
    453   int old_position_;
    454 
    455   class PushSafepointRegistersScope BASE_EMBEDDED {
    456    public:
    457     explicit PushSafepointRegistersScope(LCodeGen* codegen)
    458         : codegen_(codegen) {
    459       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
    460       codegen_->masm_->PushSafepointRegisters();
    461       codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
    462       ASSERT(codegen_->info()->is_calling());
    463     }
    464 
    465     ~PushSafepointRegistersScope() {
    466       ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
    467       codegen_->masm_->PopSafepointRegisters();
    468       codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
    469     }
    470 
    471    private:
    472     LCodeGen* codegen_;
    473   };
    474 
    475   friend class LDeferredCode;
    476   friend class LEnvironment;
    477   friend class SafepointGenerator;
    478   DISALLOW_COPY_AND_ASSIGN(LCodeGen);
    479 };
    480 
    481 
    482 class LDeferredCode: public ZoneObject {
    483  public:
    484   explicit LDeferredCode(LCodeGen* codegen)
    485       : codegen_(codegen),
    486         external_exit_(NULL),
    487         instruction_index_(codegen->current_instruction_) {
    488     codegen->AddDeferredCode(this);
    489   }
    490 
    491   virtual ~LDeferredCode() { }
    492   virtual void Generate() = 0;
    493   virtual LInstruction* instr() = 0;
    494 
    495   void SetExit(Label* exit) { external_exit_ = exit; }
    496   Label* entry() { return &entry_; }
    497   Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
    498   int instruction_index() const { return instruction_index_; }
    499 
    500  protected:
    501   LCodeGen* codegen() const { return codegen_; }
    502   MacroAssembler* masm() const { return codegen_->masm(); }
    503 
    504  private:
    505   LCodeGen* codegen_;
    506   Label entry_;
    507   Label exit_;
    508   Label* external_exit_;
    509   int instruction_index_;
    510 };
    511 
    512 } }  // namespace v8::internal
    513 
    514 #endif  // V8_IA32_LITHIUM_CODEGEN_IA32_H_
    515