| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 5 #ifndef V8_X87_LITHIUM_CODEGEN_X87_H_ |
| 6 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 6 #define V8_X87_LITHIUM_CODEGEN_X87_H_ |
| 7 | 7 |
| 8 #include "ia32/lithium-ia32.h" | 8 #include "x87/lithium-x87.h" |
| 9 | 9 |
| 10 #include "checks.h" | 10 #include "checks.h" |
| 11 #include "deoptimizer.h" | 11 #include "deoptimizer.h" |
| 12 #include "ia32/lithium-gap-resolver-ia32.h" | 12 #include "x87/lithium-gap-resolver-x87.h" |
| 13 #include "lithium-codegen.h" | 13 #include "lithium-codegen.h" |
| 14 #include "safepoint-table.h" | 14 #include "safepoint-table.h" |
| 15 #include "scopes.h" | 15 #include "scopes.h" |
| 16 #include "utils.h" | 16 #include "utils.h" |
| 17 | 17 |
| 18 namespace v8 { | 18 namespace v8 { |
| 19 namespace internal { | 19 namespace internal { |
| 20 | 20 |
| 21 // Forward declarations. | 21 // Forward declarations. |
| 22 class LDeferredCode; | 22 class LDeferredCode; |
| 23 class LGapNode; | 23 class LGapNode; |
| 24 class SafepointGenerator; | 24 class SafepointGenerator; |
| 25 | 25 |
| 26 class LCodeGen: public LCodeGenBase { | 26 class LCodeGen: public LCodeGenBase { |
| 27 public: | 27 public: |
| 28 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) | 28 LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info) |
| 29 : LCodeGenBase(chunk, assembler, info), | 29 : LCodeGenBase(chunk, assembler, info), |
| 30 deoptimizations_(4, info->zone()), | 30 deoptimizations_(4, info->zone()), |
| 31 jump_table_(4, info->zone()), | 31 jump_table_(4, info->zone()), |
| 32 deoptimization_literals_(8, info->zone()), | 32 deoptimization_literals_(8, info->zone()), |
| 33 inlined_function_count_(0), | 33 inlined_function_count_(0), |
| 34 scope_(info->scope()), | 34 scope_(info->scope()), |
| 35 translations_(info->zone()), | 35 translations_(info->zone()), |
| 36 deferred_(8, info->zone()), | 36 deferred_(8, info->zone()), |
| 37 dynamic_frame_alignment_(false), | 37 dynamic_frame_alignment_(false), |
| 38 support_aligned_spilled_doubles_(false), | 38 support_aligned_spilled_doubles_(false), |
| 39 osr_pc_offset_(-1), | 39 osr_pc_offset_(-1), |
| 40 frame_is_built_(false), | 40 frame_is_built_(false), |
| 41 x87_stack_(assembler), |
| 41 safepoints_(info->zone()), | 42 safepoints_(info->zone()), |
| 42 resolver_(this), | 43 resolver_(this), |
| 43 expected_safepoint_kind_(Safepoint::kSimple) { | 44 expected_safepoint_kind_(Safepoint::kSimple) { |
| 44 PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 45 PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| 45 } | 46 } |
| 46 | 47 |
| 47 int LookupDestination(int block_id) const { | 48 int LookupDestination(int block_id) const { |
| 48 return chunk()->LookupDestination(block_id); | 49 return chunk()->LookupDestination(block_id); |
| 49 } | 50 } |
| 50 | 51 |
| 51 bool IsNextEmittedBlock(int block_id) const { | 52 bool IsNextEmittedBlock(int block_id) const { |
| 52 return LookupDestination(block_id) == GetNextEmittedBlock(); | 53 return LookupDestination(block_id) == GetNextEmittedBlock(); |
| 53 } | 54 } |
| 54 | 55 |
| 55 bool NeedsEagerFrame() const { | 56 bool NeedsEagerFrame() const { |
| 56 return GetStackSlotCount() > 0 || | 57 return GetStackSlotCount() > 0 || |
| 57 info()->is_non_deferred_calling() || | 58 info()->is_non_deferred_calling() || |
| 58 !info()->IsStub() || | 59 !info()->IsStub() || |
| 59 info()->requires_frame(); | 60 info()->requires_frame(); |
| 60 } | 61 } |
| 61 bool NeedsDeferredFrame() const { | 62 bool NeedsDeferredFrame() const { |
| 62 return !NeedsEagerFrame() && info()->is_deferred_calling(); | 63 return !NeedsEagerFrame() && info()->is_deferred_calling(); |
| 63 } | 64 } |
| 64 | 65 |
| 65 // Support for converting LOperands to assembler types. | 66 // Support for converting LOperands to assembler types. |
| 66 Operand ToOperand(LOperand* op) const; | 67 Operand ToOperand(LOperand* op) const; |
| 67 Register ToRegister(LOperand* op) const; | 68 Register ToRegister(LOperand* op) const; |
| 68 XMMRegister ToDoubleRegister(LOperand* op) const; | 69 X87Register ToX87Register(LOperand* op) const; |
| 69 | 70 |
| 70 bool IsInteger32(LConstantOperand* op) const; | 71 bool IsInteger32(LConstantOperand* op) const; |
| 71 bool IsSmi(LConstantOperand* op) const; | 72 bool IsSmi(LConstantOperand* op) const; |
| 72 Immediate ToImmediate(LOperand* op, const Representation& r) const { | 73 Immediate ToImmediate(LOperand* op, const Representation& r) const { |
| 73 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); | 74 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); |
| 74 } | 75 } |
| 75 double ToDouble(LConstantOperand* op) const; | 76 double ToDouble(LConstantOperand* op) const; |
| 76 | 77 |
| 78 // Support for non-sse2 (x87) floating point stack handling. |
| 79 // These functions maintain the mapping of physical stack registers to our |
| 80 // virtual registers between instructions. |
| 81 enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand }; |
| 82 |
| 83 void X87Mov(X87Register reg, Operand src, |
| 84 X87OperandType operand = kX87DoubleOperand); |
| 85 void X87Mov(Operand src, X87Register reg, |
| 86 X87OperandType operand = kX87DoubleOperand); |
| 87 |
| 88 void X87PrepareBinaryOp( |
| 89 X87Register left, X87Register right, X87Register result); |
| 90 |
| 91 void X87LoadForUsage(X87Register reg); |
| 92 void X87LoadForUsage(X87Register reg1, X87Register reg2); |
| 93 void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); } |
| 94 void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); } |
| 95 |
| 96 void X87Fxch(X87Register reg, int other_slot = 0) { |
| 97 x87_stack_.Fxch(reg, other_slot); |
| 98 } |
| 99 void X87Free(X87Register reg) { |
| 100 x87_stack_.Free(reg); |
| 101 } |
| 102 |
| 103 |
| 104 bool X87StackEmpty() { |
| 105 return x87_stack_.depth() == 0; |
| 106 } |
| 107 |
| 77 Handle<Object> ToHandle(LConstantOperand* op) const; | 108 Handle<Object> ToHandle(LConstantOperand* op) const; |
| 78 | 109 |
| 79 // The operand denoting the second word (the one with a higher address) of | 110 // The operand denoting the second word (the one with a higher address) of |
| 80 // a double stack slot. | 111 // a double stack slot. |
| 81 Operand HighOperand(LOperand* op); | 112 Operand HighOperand(LOperand* op); |
| 82 | 113 |
| 83 // Try to generate code for the entire chunk, but it may fail if the | 114 // Try to generate code for the entire chunk, but it may fail if the |
| 84 // chunk contains constructs we cannot handle. Returns true if the | 115 // chunk contains constructs we cannot handle. Returns true if the |
| 85 // code generation attempt succeeded. | 116 // code generation attempt succeeded. |
| 86 bool GenerateCode(); | 117 bool GenerateCode(); |
| 87 | 118 |
| 88 // Finish the code by setting stack height, safepoint, and bailout | 119 // Finish the code by setting stack height, safepoint, and bailout |
| 89 // information on it. | 120 // information on it. |
| 90 void FinishCode(Handle<Code> code); | 121 void FinishCode(Handle<Code> code); |
| 91 | 122 |
| 92 // Deferred code support. | 123 // Deferred code support. |
| 93 void DoDeferredNumberTagD(LNumberTagD* instr); | 124 void DoDeferredNumberTagD(LNumberTagD* instr); |
| 94 | 125 |
| 95 enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 }; | 126 enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 }; |
| 96 void DoDeferredNumberTagIU(LInstruction* instr, | 127 void DoDeferredNumberTagIU(LInstruction* instr, |
| 97 LOperand* value, | 128 LOperand* value, |
| 98 LOperand* temp1, | 129 LOperand* temp, |
| 99 LOperand* temp2, | |
| 100 IntegerSignedness signedness); | 130 IntegerSignedness signedness); |
| 101 | 131 |
| 102 void DoDeferredTaggedToI(LTaggedToI* instr, Label* done); | 132 void DoDeferredTaggedToI(LTaggedToI* instr, Label* done); |
| 103 void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr); | 133 void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr); |
| 104 void DoDeferredStackCheck(LStackCheck* instr); | 134 void DoDeferredStackCheck(LStackCheck* instr); |
| 105 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); | 135 void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr); |
| 106 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); | 136 void DoDeferredStringCharFromCode(LStringCharFromCode* instr); |
| 107 void DoDeferredAllocate(LAllocate* instr); | 137 void DoDeferredAllocate(LAllocate* instr); |
| 108 void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 138 void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 109 Label* map_check); | 139 Label* map_check); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 124 // Declare methods that deal with the individual node types. | 154 // Declare methods that deal with the individual node types. |
| 125 #define DECLARE_DO(type) void Do##type(L##type* node); | 155 #define DECLARE_DO(type) void Do##type(L##type* node); |
| 126 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) | 156 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO) |
| 127 #undef DECLARE_DO | 157 #undef DECLARE_DO |
| 128 | 158 |
| 129 private: | 159 private: |
| 130 StrictMode strict_mode() const { return info()->strict_mode(); } | 160 StrictMode strict_mode() const { return info()->strict_mode(); } |
| 131 | 161 |
| 132 Scope* scope() const { return scope_; } | 162 Scope* scope() const { return scope_; } |
| 133 | 163 |
| 134 XMMRegister double_scratch0() const { return xmm0; } | |
| 135 | |
| 136 void EmitClassOfTest(Label* if_true, | 164 void EmitClassOfTest(Label* if_true, |
| 137 Label* if_false, | 165 Label* if_false, |
| 138 Handle<String> class_name, | 166 Handle<String> class_name, |
| 139 Register input, | 167 Register input, |
| 140 Register temporary, | 168 Register temporary, |
| 141 Register temporary2); | 169 Register temporary2); |
| 142 | 170 |
| 143 int GetStackSlotCount() const { return chunk()->spill_slot_count(); } | 171 int GetStackSlotCount() const { return chunk()->spill_slot_count(); } |
| 144 | 172 |
| 145 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); } | 173 void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); } |
| 146 | 174 |
| 147 void SaveCallerDoubles(); | |
| 148 void RestoreCallerDoubles(); | |
| 149 | |
| 150 // Code generation passes. Returns true if code generation should | 175 // Code generation passes. Returns true if code generation should |
| 151 // continue. | 176 // continue. |
| 152 void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE; | 177 void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE; |
| 153 void GenerateBodyInstructionPost(LInstruction* instr) V8_OVERRIDE; | 178 void GenerateBodyInstructionPost(LInstruction* instr) V8_OVERRIDE; |
| 154 bool GeneratePrologue(); | 179 bool GeneratePrologue(); |
| 155 bool GenerateDeferredCode(); | 180 bool GenerateDeferredCode(); |
| 156 bool GenerateJumpTable(); | 181 bool GenerateJumpTable(); |
| 157 bool GenerateSafepointTable(); | 182 bool GenerateSafepointTable(); |
| 158 | 183 |
| 159 // Generates the custom OSR entrypoint and sets the osr_pc_offset. | 184 // Generates the custom OSR entrypoint and sets the osr_pc_offset. |
| 160 void GenerateOsrPrologue(); | 185 void GenerateOsrPrologue(); |
| 161 | 186 |
| 162 enum SafepointMode { | 187 enum SafepointMode { |
| 163 RECORD_SIMPLE_SAFEPOINT, | 188 RECORD_SIMPLE_SAFEPOINT, |
| 164 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS | 189 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS |
| 165 }; | 190 }; |
| 166 | 191 |
| 167 void CallCode(Handle<Code> code, | 192 void CallCode(Handle<Code> code, |
| 168 RelocInfo::Mode mode, | 193 RelocInfo::Mode mode, |
| 169 LInstruction* instr); | 194 LInstruction* instr); |
| 170 | 195 |
| 171 void CallCodeGeneric(Handle<Code> code, | 196 void CallCodeGeneric(Handle<Code> code, |
| 172 RelocInfo::Mode mode, | 197 RelocInfo::Mode mode, |
| 173 LInstruction* instr, | 198 LInstruction* instr, |
| 174 SafepointMode safepoint_mode); | 199 SafepointMode safepoint_mode); |
| 175 | 200 |
| 176 void CallRuntime(const Runtime::Function* fun, | 201 void CallRuntime(const Runtime::Function* fun, |
| 177 int argc, | 202 int argc, |
| 178 LInstruction* instr, | 203 LInstruction* instr); |
| 179 SaveFPRegsMode save_doubles = kDontSaveFPRegs); | |
| 180 | 204 |
| 181 void CallRuntime(Runtime::FunctionId id, | 205 void CallRuntime(Runtime::FunctionId id, |
| 182 int argc, | 206 int argc, |
| 183 LInstruction* instr) { | 207 LInstruction* instr) { |
| 184 const Runtime::Function* function = Runtime::FunctionForId(id); | 208 const Runtime::Function* function = Runtime::FunctionForId(id); |
| 185 CallRuntime(function, argc, instr); | 209 CallRuntime(function, argc, instr); |
| 186 } | 210 } |
| 187 | 211 |
| 188 void CallRuntimeFromDeferred(Runtime::FunctionId id, | 212 void CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 189 int argc, | 213 int argc, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 bool is_tagged, | 249 bool is_tagged, |
| 226 bool is_uint32, | 250 bool is_uint32, |
| 227 int* object_index_pointer, | 251 int* object_index_pointer, |
| 228 int* dematerialized_index_pointer); | 252 int* dematerialized_index_pointer); |
| 229 void PopulateDeoptimizationData(Handle<Code> code); | 253 void PopulateDeoptimizationData(Handle<Code> code); |
| 230 int DefineDeoptimizationLiteral(Handle<Object> literal); | 254 int DefineDeoptimizationLiteral(Handle<Object> literal); |
| 231 | 255 |
| 232 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 256 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| 233 | 257 |
| 234 Register ToRegister(int index) const; | 258 Register ToRegister(int index) const; |
| 235 XMMRegister ToDoubleRegister(int index) const; | 259 X87Register ToX87Register(int index) const; |
| 236 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; | 260 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; |
| 237 int32_t ToInteger32(LConstantOperand* op) const; | 261 int32_t ToInteger32(LConstantOperand* op) const; |
| 238 ExternalReference ToExternalReference(LConstantOperand* op) const; | 262 ExternalReference ToExternalReference(LConstantOperand* op) const; |
| 239 | 263 |
| 240 Operand BuildFastArrayOperand(LOperand* elements_pointer, | 264 Operand BuildFastArrayOperand(LOperand* elements_pointer, |
| 241 LOperand* key, | 265 LOperand* key, |
| 242 Representation key_representation, | 266 Representation key_representation, |
| 243 ElementsKind elements_kind, | 267 ElementsKind elements_kind, |
| 244 uint32_t base_offset); | 268 uint32_t base_offset); |
| 245 | 269 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 263 void RecordAndWritePosition(int position) V8_OVERRIDE; | 287 void RecordAndWritePosition(int position) V8_OVERRIDE; |
| 264 | 288 |
| 265 static Condition TokenToCondition(Token::Value op, bool is_unsigned); | 289 static Condition TokenToCondition(Token::Value op, bool is_unsigned); |
| 266 void EmitGoto(int block); | 290 void EmitGoto(int block); |
| 267 | 291 |
| 268 // EmitBranch expects to be the last instruction of a block. | 292 // EmitBranch expects to be the last instruction of a block. |
| 269 template<class InstrType> | 293 template<class InstrType> |
| 270 void EmitBranch(InstrType instr, Condition cc); | 294 void EmitBranch(InstrType instr, Condition cc); |
| 271 template<class InstrType> | 295 template<class InstrType> |
| 272 void EmitFalseBranch(InstrType instr, Condition cc); | 296 void EmitFalseBranch(InstrType instr, Condition cc); |
| 273 void EmitNumberUntagD( | 297 void EmitNumberUntagDNoSSE2( |
| 274 Register input, | 298 Register input, |
| 275 Register temp, | 299 Register temp, |
| 276 XMMRegister result, | 300 X87Register res_reg, |
| 277 bool allow_undefined_as_nan, | 301 bool allow_undefined_as_nan, |
| 278 bool deoptimize_on_minus_zero, | 302 bool deoptimize_on_minus_zero, |
| 279 LEnvironment* env, | 303 LEnvironment* env, |
| 280 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); | 304 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); |
| 281 | 305 |
| 282 // Emits optimized code for typeof x == "y". Modifies input register. | 306 // Emits optimized code for typeof x == "y". Modifies input register. |
| 283 // Returns the condition on which a final split to | 307 // Returns the condition on which a final split to |
| 284 // true and false label should be made, to optimize fallthrough. | 308 // true and false label should be made, to optimize fallthrough. |
| 285 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); | 309 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); |
| 286 | 310 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 void DoStoreKeyedExternalArray(LStoreKeyed* instr); | 343 void DoStoreKeyedExternalArray(LStoreKeyed* instr); |
| 320 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); | 344 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); |
| 321 void DoStoreKeyedFixedArray(LStoreKeyed* instr); | 345 void DoStoreKeyedFixedArray(LStoreKeyed* instr); |
| 322 | 346 |
| 323 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); | 347 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); |
| 324 | 348 |
| 325 // Emits code for pushing either a tagged constant, a (non-double) | 349 // Emits code for pushing either a tagged constant, a (non-double) |
| 326 // register, or a stack slot operand. | 350 // register, or a stack slot operand. |
| 327 void EmitPushTaggedOperand(LOperand* operand); | 351 void EmitPushTaggedOperand(LOperand* operand); |
| 328 | 352 |
| 353 void X87Fld(Operand src, X87OperandType opts); |
| 354 |
| 355 void EmitFlushX87ForDeopt(); |
| 356 void FlushX87StackIfNecessary(LInstruction* instr) { |
| 357 x87_stack_.FlushIfNecessary(instr, this); |
| 358 } |
| 329 friend class LGapResolver; | 359 friend class LGapResolver; |
| 330 | 360 |
| 331 #ifdef _MSC_VER | 361 #ifdef _MSC_VER |
| 332 // On windows, you may not access the stack more than one page below | 362 // On windows, you may not access the stack more than one page below |
| 333 // the most recently mapped page. To make the allocated area randomly | 363 // the most recently mapped page. To make the allocated area randomly |
| 334 // accessible, we write an arbitrary value to each page in range | 364 // accessible, we write an arbitrary value to each page in range |
| 335 // esp + offset - page_size .. esp in turn. | 365 // esp + offset - page_size .. esp in turn. |
| 336 void MakeSureStackPagesMapped(int offset); | 366 void MakeSureStackPagesMapped(int offset); |
| 337 #endif | 367 #endif |
| 338 | 368 |
| 339 ZoneList<LEnvironment*> deoptimizations_; | 369 ZoneList<LEnvironment*> deoptimizations_; |
| 340 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; | 370 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; |
| 341 ZoneList<Handle<Object> > deoptimization_literals_; | 371 ZoneList<Handle<Object> > deoptimization_literals_; |
| 342 int inlined_function_count_; | 372 int inlined_function_count_; |
| 343 Scope* const scope_; | 373 Scope* const scope_; |
| 344 TranslationBuffer translations_; | 374 TranslationBuffer translations_; |
| 345 ZoneList<LDeferredCode*> deferred_; | 375 ZoneList<LDeferredCode*> deferred_; |
| 346 bool dynamic_frame_alignment_; | 376 bool dynamic_frame_alignment_; |
| 347 bool support_aligned_spilled_doubles_; | 377 bool support_aligned_spilled_doubles_; |
| 348 int osr_pc_offset_; | 378 int osr_pc_offset_; |
| 349 bool frame_is_built_; | 379 bool frame_is_built_; |
| 350 | 380 |
| 381 class X87Stack { |
| 382 public: |
| 383 explicit X87Stack(MacroAssembler* masm) |
| 384 : stack_depth_(0), is_mutable_(true), masm_(masm) { } |
| 385 explicit X87Stack(const X87Stack& other) |
| 386 : stack_depth_(other.stack_depth_), is_mutable_(false), masm_(masm()) { |
| 387 for (int i = 0; i < stack_depth_; i++) { |
| 388 stack_[i] = other.stack_[i]; |
| 389 } |
| 390 } |
| 391 bool operator==(const X87Stack& other) const { |
| 392 if (stack_depth_ != other.stack_depth_) return false; |
| 393 for (int i = 0; i < stack_depth_; i++) { |
| 394 if (!stack_[i].is(other.stack_[i])) return false; |
| 395 } |
| 396 return true; |
| 397 } |
| 398 bool Contains(X87Register reg); |
| 399 void Fxch(X87Register reg, int other_slot = 0); |
| 400 void Free(X87Register reg); |
| 401 void PrepareToWrite(X87Register reg); |
| 402 void CommitWrite(X87Register reg); |
| 403 void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen); |
| 404 void LeavingBlock(int current_block_id, LGoto* goto_instr); |
| 405 int depth() const { return stack_depth_; } |
| 406 void pop() { |
| 407 ASSERT(is_mutable_); |
| 408 stack_depth_--; |
| 409 } |
| 410 void push(X87Register reg) { |
| 411 ASSERT(is_mutable_); |
| 412 ASSERT(stack_depth_ < X87Register::kMaxNumAllocatableRegisters); |
| 413 stack_[stack_depth_] = reg; |
| 414 stack_depth_++; |
| 415 } |
| 416 |
| 417 MacroAssembler* masm() const { return masm_; } |
| 418 Isolate* isolate() const { return masm_->isolate(); } |
| 419 |
| 420 private: |
| 421 int ArrayIndex(X87Register reg); |
| 422 int st2idx(int pos); |
| 423 |
| 424 X87Register stack_[X87Register::kMaxNumAllocatableRegisters]; |
| 425 int stack_depth_; |
| 426 bool is_mutable_; |
| 427 MacroAssembler* masm_; |
| 428 }; |
| 429 X87Stack x87_stack_; |
| 430 |
| 351 // Builder that keeps track of safepoints in the code. The table | 431 // Builder that keeps track of safepoints in the code. The table |
| 352 // itself is emitted at the end of the generated code. | 432 // itself is emitted at the end of the generated code. |
| 353 SafepointTableBuilder safepoints_; | 433 SafepointTableBuilder safepoints_; |
| 354 | 434 |
| 355 // Compiler from a set of parallel moves to a sequential list of moves. | 435 // Compiler from a set of parallel moves to a sequential list of moves. |
| 356 LGapResolver resolver_; | 436 LGapResolver resolver_; |
| 357 | 437 |
| 358 Safepoint::Kind expected_safepoint_kind_; | 438 Safepoint::Kind expected_safepoint_kind_; |
| 359 | 439 |
| 360 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { | 440 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 379 | 459 |
| 380 friend class LDeferredCode; | 460 friend class LDeferredCode; |
| 381 friend class LEnvironment; | 461 friend class LEnvironment; |
| 382 friend class SafepointGenerator; | 462 friend class SafepointGenerator; |
| 383 DISALLOW_COPY_AND_ASSIGN(LCodeGen); | 463 DISALLOW_COPY_AND_ASSIGN(LCodeGen); |
| 384 }; | 464 }; |
| 385 | 465 |
| 386 | 466 |
| 387 class LDeferredCode : public ZoneObject { | 467 class LDeferredCode : public ZoneObject { |
| 388 public: | 468 public: |
| 389 explicit LDeferredCode(LCodeGen* codegen) | 469 explicit LDeferredCode(LCodeGen* codegen, const LCodeGen::X87Stack& x87_stack) |
| 390 : codegen_(codegen), | 470 : codegen_(codegen), |
| 391 external_exit_(NULL), | 471 external_exit_(NULL), |
| 392 instruction_index_(codegen->current_instruction_) { | 472 instruction_index_(codegen->current_instruction_), |
| 473 x87_stack_(x87_stack) { |
| 393 codegen->AddDeferredCode(this); | 474 codegen->AddDeferredCode(this); |
| 394 } | 475 } |
| 395 | 476 |
| 396 virtual ~LDeferredCode() {} | 477 virtual ~LDeferredCode() {} |
| 397 virtual void Generate() = 0; | 478 virtual void Generate() = 0; |
| 398 virtual LInstruction* instr() = 0; | 479 virtual LInstruction* instr() = 0; |
| 399 | 480 |
| 400 void SetExit(Label* exit) { external_exit_ = exit; } | 481 void SetExit(Label* exit) { external_exit_ = exit; } |
| 401 Label* entry() { return &entry_; } | 482 Label* entry() { return &entry_; } |
| 402 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } | 483 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } |
| 403 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } | 484 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } |
| 404 int instruction_index() const { return instruction_index_; } | 485 int instruction_index() const { return instruction_index_; } |
| 486 const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; } |
| 405 | 487 |
| 406 protected: | 488 protected: |
| 407 LCodeGen* codegen() const { return codegen_; } | 489 LCodeGen* codegen() const { return codegen_; } |
| 408 MacroAssembler* masm() const { return codegen_->masm(); } | 490 MacroAssembler* masm() const { return codegen_->masm(); } |
| 409 | 491 |
| 410 private: | 492 private: |
| 411 LCodeGen* codegen_; | 493 LCodeGen* codegen_; |
| 412 Label entry_; | 494 Label entry_; |
| 413 Label exit_; | 495 Label exit_; |
| 414 Label* external_exit_; | 496 Label* external_exit_; |
| 415 Label done_; | 497 Label done_; |
| 416 int instruction_index_; | 498 int instruction_index_; |
| 499 LCodeGen::X87Stack x87_stack_; |
| 417 }; | 500 }; |
| 418 | 501 |
| 419 } } // namespace v8::internal | 502 } } // namespace v8::internal |
| 420 | 503 |
| 421 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 504 #endif // V8_X87_LITHIUM_CODEGEN_X87_H_ |
| OLD | NEW |