| 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_IA32_LITHIUM_CODEGEN_IA32_H_ |
| 6 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 6 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ |
| 7 | 7 |
| 8 #include "ia32/lithium-ia32.h" | 8 #include "ia32/lithium-ia32.h" |
| 9 | 9 |
| 10 #include "checks.h" | 10 #include "checks.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 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), | |
| 42 safepoints_(info->zone()), | 41 safepoints_(info->zone()), |
| 43 resolver_(this), | 42 resolver_(this), |
| 44 expected_safepoint_kind_(Safepoint::kSimple) { | 43 expected_safepoint_kind_(Safepoint::kSimple) { |
| 45 PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 44 PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| 46 } | 45 } |
| 47 | 46 |
| 48 int LookupDestination(int block_id) const { | 47 int LookupDestination(int block_id) const { |
| 49 return chunk()->LookupDestination(block_id); | 48 return chunk()->LookupDestination(block_id); |
| 50 } | 49 } |
| 51 | 50 |
| 52 bool IsNextEmittedBlock(int block_id) const { | 51 bool IsNextEmittedBlock(int block_id) const { |
| 53 return LookupDestination(block_id) == GetNextEmittedBlock(); | 52 return LookupDestination(block_id) == GetNextEmittedBlock(); |
| 54 } | 53 } |
| 55 | 54 |
| 56 bool NeedsEagerFrame() const { | 55 bool NeedsEagerFrame() const { |
| 57 return GetStackSlotCount() > 0 || | 56 return GetStackSlotCount() > 0 || |
| 58 info()->is_non_deferred_calling() || | 57 info()->is_non_deferred_calling() || |
| 59 !info()->IsStub() || | 58 !info()->IsStub() || |
| 60 info()->requires_frame(); | 59 info()->requires_frame(); |
| 61 } | 60 } |
| 62 bool NeedsDeferredFrame() const { | 61 bool NeedsDeferredFrame() const { |
| 63 return !NeedsEagerFrame() && info()->is_deferred_calling(); | 62 return !NeedsEagerFrame() && info()->is_deferred_calling(); |
| 64 } | 63 } |
| 65 | 64 |
| 66 // Support for converting LOperands to assembler types. | 65 // Support for converting LOperands to assembler types. |
| 67 Operand ToOperand(LOperand* op) const; | 66 Operand ToOperand(LOperand* op) const; |
| 68 Register ToRegister(LOperand* op) const; | 67 Register ToRegister(LOperand* op) const; |
| 69 XMMRegister ToDoubleRegister(LOperand* op) const; | 68 XMMRegister ToDoubleRegister(LOperand* op) const; |
| 70 X87Register ToX87Register(LOperand* op) const; | |
| 71 | 69 |
| 72 bool IsInteger32(LConstantOperand* op) const; | 70 bool IsInteger32(LConstantOperand* op) const; |
| 73 bool IsSmi(LConstantOperand* op) const; | 71 bool IsSmi(LConstantOperand* op) const; |
| 74 Immediate ToImmediate(LOperand* op, const Representation& r) const { | 72 Immediate ToImmediate(LOperand* op, const Representation& r) const { |
| 75 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); | 73 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); |
| 76 } | 74 } |
| 77 double ToDouble(LConstantOperand* op) const; | 75 double ToDouble(LConstantOperand* op) const; |
| 78 | 76 |
| 79 // Support for non-sse2 (x87) floating point stack handling. | |
| 80 // These functions maintain the mapping of physical stack registers to our | |
| 81 // virtual registers between instructions. | |
| 82 enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand }; | |
| 83 | |
| 84 void X87Mov(X87Register reg, Operand src, | |
| 85 X87OperandType operand = kX87DoubleOperand); | |
| 86 void X87Mov(Operand src, X87Register reg, | |
| 87 X87OperandType operand = kX87DoubleOperand); | |
| 88 | |
| 89 void X87PrepareBinaryOp( | |
| 90 X87Register left, X87Register right, X87Register result); | |
| 91 | |
| 92 void X87LoadForUsage(X87Register reg); | |
| 93 void X87LoadForUsage(X87Register reg1, X87Register reg2); | |
| 94 void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); } | |
| 95 void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); } | |
| 96 | |
| 97 void X87Fxch(X87Register reg, int other_slot = 0) { | |
| 98 x87_stack_.Fxch(reg, other_slot); | |
| 99 } | |
| 100 void X87Free(X87Register reg) { | |
| 101 x87_stack_.Free(reg); | |
| 102 } | |
| 103 | |
| 104 | |
| 105 bool X87StackEmpty() { | |
| 106 return x87_stack_.depth() == 0; | |
| 107 } | |
| 108 | |
| 109 Handle<Object> ToHandle(LConstantOperand* op) const; | 77 Handle<Object> ToHandle(LConstantOperand* op) const; |
| 110 | 78 |
| 111 // The operand denoting the second word (the one with a higher address) of | 79 // The operand denoting the second word (the one with a higher address) of |
| 112 // a double stack slot. | 80 // a double stack slot. |
| 113 Operand HighOperand(LOperand* op); | 81 Operand HighOperand(LOperand* op); |
| 114 | 82 |
| 115 // Try to generate code for the entire chunk, but it may fail if the | 83 // Try to generate code for the entire chunk, but it may fail if the |
| 116 // chunk contains constructs we cannot handle. Returns true if the | 84 // chunk contains constructs we cannot handle. Returns true if the |
| 117 // code generation attempt succeeded. | 85 // code generation attempt succeeded. |
| 118 bool GenerateCode(); | 86 bool GenerateCode(); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 bool is_uint32, | 226 bool is_uint32, |
| 259 int* object_index_pointer, | 227 int* object_index_pointer, |
| 260 int* dematerialized_index_pointer); | 228 int* dematerialized_index_pointer); |
| 261 void PopulateDeoptimizationData(Handle<Code> code); | 229 void PopulateDeoptimizationData(Handle<Code> code); |
| 262 int DefineDeoptimizationLiteral(Handle<Object> literal); | 230 int DefineDeoptimizationLiteral(Handle<Object> literal); |
| 263 | 231 |
| 264 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 232 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
| 265 | 233 |
| 266 Register ToRegister(int index) const; | 234 Register ToRegister(int index) const; |
| 267 XMMRegister ToDoubleRegister(int index) const; | 235 XMMRegister ToDoubleRegister(int index) const; |
| 268 X87Register ToX87Register(int index) const; | |
| 269 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; | 236 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; |
| 270 int32_t ToInteger32(LConstantOperand* op) const; | 237 int32_t ToInteger32(LConstantOperand* op) const; |
| 271 ExternalReference ToExternalReference(LConstantOperand* op) const; | 238 ExternalReference ToExternalReference(LConstantOperand* op) const; |
| 272 | 239 |
| 273 Operand BuildFastArrayOperand(LOperand* elements_pointer, | 240 Operand BuildFastArrayOperand(LOperand* elements_pointer, |
| 274 LOperand* key, | 241 LOperand* key, |
| 275 Representation key_representation, | 242 Representation key_representation, |
| 276 ElementsKind elements_kind, | 243 ElementsKind elements_kind, |
| 277 uint32_t offset, | 244 uint32_t offset, |
| 278 uint32_t additional_index = 0); | 245 uint32_t additional_index = 0); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 306 void EmitFalseBranch(InstrType instr, Condition cc); | 273 void EmitFalseBranch(InstrType instr, Condition cc); |
| 307 void EmitNumberUntagD( | 274 void EmitNumberUntagD( |
| 308 Register input, | 275 Register input, |
| 309 Register temp, | 276 Register temp, |
| 310 XMMRegister result, | 277 XMMRegister result, |
| 311 bool allow_undefined_as_nan, | 278 bool allow_undefined_as_nan, |
| 312 bool deoptimize_on_minus_zero, | 279 bool deoptimize_on_minus_zero, |
| 313 LEnvironment* env, | 280 LEnvironment* env, |
| 314 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); | 281 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); |
| 315 | 282 |
| 316 void EmitNumberUntagDNoSSE2( | |
| 317 Register input, | |
| 318 Register temp, | |
| 319 X87Register res_reg, | |
| 320 bool allow_undefined_as_nan, | |
| 321 bool deoptimize_on_minus_zero, | |
| 322 LEnvironment* env, | |
| 323 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 324 | |
| 325 // Emits optimized code for typeof x == "y". Modifies input register. | 283 // Emits optimized code for typeof x == "y". Modifies input register. |
| 326 // Returns the condition on which a final split to | 284 // Returns the condition on which a final split to |
| 327 // true and false label should be made, to optimize fallthrough. | 285 // true and false label should be made, to optimize fallthrough. |
| 328 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); | 286 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); |
| 329 | 287 |
| 330 // Emits optimized code for %_IsObject(x). Preserves input register. | 288 // Emits optimized code for %_IsObject(x). Preserves input register. |
| 331 // Returns the condition on which a final split to | 289 // Returns the condition on which a final split to |
| 332 // true and false label should be made, to optimize fallthrough. | 290 // true and false label should be made, to optimize fallthrough. |
| 333 Condition EmitIsObject(Register input, | 291 Condition EmitIsObject(Register input, |
| 334 Register temp1, | 292 Register temp1, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 362 void DoStoreKeyedExternalArray(LStoreKeyed* instr); | 320 void DoStoreKeyedExternalArray(LStoreKeyed* instr); |
| 363 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); | 321 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); |
| 364 void DoStoreKeyedFixedArray(LStoreKeyed* instr); | 322 void DoStoreKeyedFixedArray(LStoreKeyed* instr); |
| 365 | 323 |
| 366 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); | 324 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); |
| 367 | 325 |
| 368 // Emits code for pushing either a tagged constant, a (non-double) | 326 // Emits code for pushing either a tagged constant, a (non-double) |
| 369 // register, or a stack slot operand. | 327 // register, or a stack slot operand. |
| 370 void EmitPushTaggedOperand(LOperand* operand); | 328 void EmitPushTaggedOperand(LOperand* operand); |
| 371 | 329 |
| 372 void X87Fld(Operand src, X87OperandType opts); | |
| 373 | |
| 374 void EmitFlushX87ForDeopt(); | |
| 375 void FlushX87StackIfNecessary(LInstruction* instr) { | |
| 376 x87_stack_.FlushIfNecessary(instr, this); | |
| 377 } | |
| 378 friend class LGapResolver; | 330 friend class LGapResolver; |
| 379 | 331 |
| 380 #ifdef _MSC_VER | 332 #ifdef _MSC_VER |
| 381 // On windows, you may not access the stack more than one page below | 333 // On windows, you may not access the stack more than one page below |
| 382 // the most recently mapped page. To make the allocated area randomly | 334 // the most recently mapped page. To make the allocated area randomly |
| 383 // accessible, we write an arbitrary value to each page in range | 335 // accessible, we write an arbitrary value to each page in range |
| 384 // esp + offset - page_size .. esp in turn. | 336 // esp + offset - page_size .. esp in turn. |
| 385 void MakeSureStackPagesMapped(int offset); | 337 void MakeSureStackPagesMapped(int offset); |
| 386 #endif | 338 #endif |
| 387 | 339 |
| 388 ZoneList<LEnvironment*> deoptimizations_; | 340 ZoneList<LEnvironment*> deoptimizations_; |
| 389 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; | 341 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; |
| 390 ZoneList<Handle<Object> > deoptimization_literals_; | 342 ZoneList<Handle<Object> > deoptimization_literals_; |
| 391 int inlined_function_count_; | 343 int inlined_function_count_; |
| 392 Scope* const scope_; | 344 Scope* const scope_; |
| 393 TranslationBuffer translations_; | 345 TranslationBuffer translations_; |
| 394 ZoneList<LDeferredCode*> deferred_; | 346 ZoneList<LDeferredCode*> deferred_; |
| 395 bool dynamic_frame_alignment_; | 347 bool dynamic_frame_alignment_; |
| 396 bool support_aligned_spilled_doubles_; | 348 bool support_aligned_spilled_doubles_; |
| 397 int osr_pc_offset_; | 349 int osr_pc_offset_; |
| 398 bool frame_is_built_; | 350 bool frame_is_built_; |
| 399 | 351 |
| 400 class X87Stack { | |
| 401 public: | |
| 402 explicit X87Stack(MacroAssembler* masm) | |
| 403 : stack_depth_(0), is_mutable_(true), masm_(masm) { } | |
| 404 explicit X87Stack(const X87Stack& other) | |
| 405 : stack_depth_(other.stack_depth_), is_mutable_(false), masm_(masm()) { | |
| 406 for (int i = 0; i < stack_depth_; i++) { | |
| 407 stack_[i] = other.stack_[i]; | |
| 408 } | |
| 409 } | |
| 410 bool operator==(const X87Stack& other) const { | |
| 411 if (stack_depth_ != other.stack_depth_) return false; | |
| 412 for (int i = 0; i < stack_depth_; i++) { | |
| 413 if (!stack_[i].is(other.stack_[i])) return false; | |
| 414 } | |
| 415 return true; | |
| 416 } | |
| 417 bool Contains(X87Register reg); | |
| 418 void Fxch(X87Register reg, int other_slot = 0); | |
| 419 void Free(X87Register reg); | |
| 420 void PrepareToWrite(X87Register reg); | |
| 421 void CommitWrite(X87Register reg); | |
| 422 void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen); | |
| 423 void LeavingBlock(int current_block_id, LGoto* goto_instr); | |
| 424 int depth() const { return stack_depth_; } | |
| 425 void pop() { | |
| 426 ASSERT(is_mutable_); | |
| 427 stack_depth_--; | |
| 428 } | |
| 429 void push(X87Register reg) { | |
| 430 ASSERT(is_mutable_); | |
| 431 ASSERT(stack_depth_ < X87Register::kNumAllocatableRegisters); | |
| 432 stack_[stack_depth_] = reg; | |
| 433 stack_depth_++; | |
| 434 } | |
| 435 | |
| 436 MacroAssembler* masm() const { return masm_; } | |
| 437 Isolate* isolate() const { return masm_->isolate(); } | |
| 438 | |
| 439 private: | |
| 440 int ArrayIndex(X87Register reg); | |
| 441 int st2idx(int pos); | |
| 442 | |
| 443 X87Register stack_[X87Register::kNumAllocatableRegisters]; | |
| 444 int stack_depth_; | |
| 445 bool is_mutable_; | |
| 446 MacroAssembler* masm_; | |
| 447 }; | |
| 448 X87Stack x87_stack_; | |
| 449 | |
| 450 // Builder that keeps track of safepoints in the code. The table | 352 // Builder that keeps track of safepoints in the code. The table |
| 451 // itself is emitted at the end of the generated code. | 353 // itself is emitted at the end of the generated code. |
| 452 SafepointTableBuilder safepoints_; | 354 SafepointTableBuilder safepoints_; |
| 453 | 355 |
| 454 // Compiler from a set of parallel moves to a sequential list of moves. | 356 // Compiler from a set of parallel moves to a sequential list of moves. |
| 455 LGapResolver resolver_; | 357 LGapResolver resolver_; |
| 456 | 358 |
| 457 Safepoint::Kind expected_safepoint_kind_; | 359 Safepoint::Kind expected_safepoint_kind_; |
| 458 | 360 |
| 459 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { | 361 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 478 | 380 |
| 479 friend class LDeferredCode; | 381 friend class LDeferredCode; |
| 480 friend class LEnvironment; | 382 friend class LEnvironment; |
| 481 friend class SafepointGenerator; | 383 friend class SafepointGenerator; |
| 482 DISALLOW_COPY_AND_ASSIGN(LCodeGen); | 384 DISALLOW_COPY_AND_ASSIGN(LCodeGen); |
| 483 }; | 385 }; |
| 484 | 386 |
| 485 | 387 |
| 486 class LDeferredCode : public ZoneObject { | 388 class LDeferredCode : public ZoneObject { |
| 487 public: | 389 public: |
| 488 explicit LDeferredCode(LCodeGen* codegen, const LCodeGen::X87Stack& x87_stack) | 390 explicit LDeferredCode(LCodeGen* codegen) |
| 489 : codegen_(codegen), | 391 : codegen_(codegen), |
| 490 external_exit_(NULL), | 392 external_exit_(NULL), |
| 491 instruction_index_(codegen->current_instruction_), | 393 instruction_index_(codegen->current_instruction_) { |
| 492 x87_stack_(x87_stack) { | |
| 493 codegen->AddDeferredCode(this); | 394 codegen->AddDeferredCode(this); |
| 494 } | 395 } |
| 495 | 396 |
| 496 virtual ~LDeferredCode() {} | 397 virtual ~LDeferredCode() {} |
| 497 virtual void Generate() = 0; | 398 virtual void Generate() = 0; |
| 498 virtual LInstruction* instr() = 0; | 399 virtual LInstruction* instr() = 0; |
| 499 | 400 |
| 500 void SetExit(Label* exit) { external_exit_ = exit; } | 401 void SetExit(Label* exit) { external_exit_ = exit; } |
| 501 Label* entry() { return &entry_; } | 402 Label* entry() { return &entry_; } |
| 502 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } | 403 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } |
| 503 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } | 404 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } |
| 504 int instruction_index() const { return instruction_index_; } | 405 int instruction_index() const { return instruction_index_; } |
| 505 const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; } | |
| 506 | 406 |
| 507 protected: | 407 protected: |
| 508 LCodeGen* codegen() const { return codegen_; } | 408 LCodeGen* codegen() const { return codegen_; } |
| 509 MacroAssembler* masm() const { return codegen_->masm(); } | 409 MacroAssembler* masm() const { return codegen_->masm(); } |
| 510 | 410 |
| 511 private: | 411 private: |
| 512 LCodeGen* codegen_; | 412 LCodeGen* codegen_; |
| 513 Label entry_; | 413 Label entry_; |
| 514 Label exit_; | 414 Label exit_; |
| 515 Label* external_exit_; | 415 Label* external_exit_; |
| 516 Label done_; | 416 Label done_; |
| 517 int instruction_index_; | 417 int instruction_index_; |
| 518 LCodeGen::X87Stack x87_stack_; | |
| 519 }; | 418 }; |
| 520 | 419 |
| 521 } } // namespace v8::internal | 420 } } // namespace v8::internal |
| 522 | 421 |
| 523 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 422 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ |
| OLD | NEW |