| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 address, // An input reg. | 402 address, // An input reg. |
| 403 value) { // One scratch reg. | 403 value) { // One scratch reg. |
| 404 } | 404 } |
| 405 | 405 |
| 406 enum Mode { | 406 enum Mode { |
| 407 STORE_BUFFER_ONLY, | 407 STORE_BUFFER_ONLY, |
| 408 INCREMENTAL, | 408 INCREMENTAL, |
| 409 INCREMENTAL_COMPACTION | 409 INCREMENTAL_COMPACTION |
| 410 }; | 410 }; |
| 411 | 411 |
| 412 static void PatchBranchIntoNop(MacroAssembler* masm, int pos) { |
| 413 masm->instr_at_put(pos, (masm->instr_at(pos) & ~B27) | (B24 | B20)); |
| 414 ASSERT(Assembler::IsTstImmediate(masm->instr_at(pos))); |
| 415 } |
| 416 |
| 417 static void PatchNopIntoBranch(MacroAssembler* masm, int pos) { |
| 418 masm->instr_at_put(pos, (masm->instr_at(pos) & ~(B24 | B20)) | B27); |
| 419 ASSERT(Assembler::IsBranch(masm->instr_at(pos))); |
| 420 } |
| 421 |
| 412 static Mode GetMode(Code* stub) { | 422 static Mode GetMode(Code* stub) { |
| 423 Instr first_instruction = Assembler::instr_at(stub->instruction_start()); |
| 424 Instr second_instruction = Assembler::instr_at(stub->instruction_start() + |
| 425 Assembler::kInstrSize); |
| 426 |
| 427 if (Assembler::IsBranch(first_instruction)) { |
| 428 return INCREMENTAL; |
| 429 } |
| 430 |
| 431 ASSERT(Assembler::IsTstImmediate(first_instruction)); |
| 432 |
| 433 if (Assembler::IsBranch(second_instruction)) { |
| 434 return INCREMENTAL_COMPACTION; |
| 435 } |
| 436 |
| 437 ASSERT(Assembler::IsTstImmediate(second_instruction)); |
| 438 |
| 413 return STORE_BUFFER_ONLY; | 439 return STORE_BUFFER_ONLY; |
| 414 } | 440 } |
| 415 | 441 |
| 416 static void Patch(Code* stub, Mode mode) { | 442 static void Patch(Code* stub, Mode mode) { |
| 417 ASSERT(mode == STORE_BUFFER_ONLY); | 443 MacroAssembler masm(NULL, |
| 444 stub->instruction_start(), |
| 445 stub->instruction_size()); |
| 446 switch (mode) { |
| 447 case STORE_BUFFER_ONLY: |
| 448 ASSERT(GetMode(stub) == INCREMENTAL || |
| 449 GetMode(stub) == INCREMENTAL_COMPACTION); |
| 450 PatchBranchIntoNop(&masm, 0); |
| 451 PatchBranchIntoNop(&masm, Assembler::kInstrSize); |
| 452 break; |
| 453 case INCREMENTAL: |
| 454 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); |
| 455 PatchNopIntoBranch(&masm, 0); |
| 456 break; |
| 457 case INCREMENTAL_COMPACTION: |
| 458 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); |
| 459 PatchNopIntoBranch(&masm, Assembler::kInstrSize); |
| 460 break; |
| 461 } |
| 462 ASSERT(GetMode(stub) == mode); |
| 463 CPU::FlushICache(stub->instruction_start(), 2 * Assembler::kInstrSize); |
| 418 } | 464 } |
| 419 | 465 |
| 420 private: | 466 private: |
| 421 // This is a helper class for freeing up 3 scratch registers. The input is | 467 // This is a helper class for freeing up 3 scratch registers. The input is |
| 422 // two registers that must be preserved and one scratch register provided by | 468 // two registers that must be preserved and one scratch register provided by |
| 423 // the caller. | 469 // the caller. |
| 424 class RegisterAllocation { | 470 class RegisterAllocation { |
| 425 public: | 471 public: |
| 426 RegisterAllocation(Register object, | 472 RegisterAllocation(Register object, |
| 427 Register address, | 473 Register address, |
| 428 Register scratch0) | 474 Register scratch0) |
| 429 : object_(object), | 475 : object_(object), |
| 430 address_(address), | 476 address_(address), |
| 431 scratch0_(scratch0) { | 477 scratch0_(scratch0) { |
| 478 ASSERT(!AreAliased(scratch0, object, address, no_reg)); |
| 479 scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_); |
| 432 } | 480 } |
| 481 |
| 482 void Save(MacroAssembler* masm) { |
| 483 ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_)); |
| 484 // We don't have to save scratch0_ because it was given to us as |
| 485 // a scratch register. |
| 486 masm->push(scratch1_); |
| 487 } |
| 488 |
| 489 void Restore(MacroAssembler* masm) { |
| 490 masm->pop(scratch1_); |
| 491 } |
| 492 |
| 493 // If we have to call into C then we need to save and restore all caller- |
| 494 // saved registers that were not already preserved. The scratch registers |
| 495 // will be restored by other means so we don't bother pushing them here. |
| 433 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { | 496 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { |
| 434 UNREACHABLE(); // TODO(gc): Save the caller save registers. | 497 masm->stm(db_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit()); |
| 435 if (mode == kSaveFPRegs) { | 498 if (mode == kSaveFPRegs) { |
| 436 CpuFeatures::Scope scope(SSE2); | 499 CpuFeatures::Scope scope(VFP3); |
| 437 masm->sub(sp, | 500 masm->sub(sp, |
| 438 sp, | 501 sp, |
| 439 Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1))); | 502 Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1))); |
| 440 // Save all VFP registers except d0. | 503 // Save all VFP registers except d0. |
| 441 for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) { | 504 for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) { |
| 442 DwVfpRegister reg = DwVfpRegister::from_code(i); | 505 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 443 masm->vstr(reg, MemOperand(sp, (i - 1) * kDoubleSize)); | 506 masm->vstr(reg, MemOperand(sp, (i - 1) * kDoubleSize)); |
| 444 } | 507 } |
| 445 } | 508 } |
| 446 } | 509 } |
| 447 | 510 |
| 448 inline void RestoreCallerSaveRegisters(MacroAssembler*masm, | 511 inline void RestoreCallerSaveRegisters(MacroAssembler*masm, |
| 449 SaveFPRegsMode mode) { | 512 SaveFPRegsMode mode) { |
| 450 if (mode == kSaveFPRegs) { | 513 if (mode == kSaveFPRegs) { |
| 451 CpuFeatures::Scope scope(SSE2); | 514 CpuFeatures::Scope scope(VFP3); |
| 452 // Restore all VFP registers except d0. | 515 // Restore all VFP registers except d0. |
| 453 for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) { | 516 for (int i = DwVfpRegister::kNumRegisters - 1; i > 0; i--) { |
| 454 DwVfpRegister reg = DwVfpRegister::from_code(i); | 517 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 455 masm->vldr(reg, MemOperand(sp, (i - 1) * kDoubleSize)); | 518 masm->vldr(reg, MemOperand(sp, (i - 1) * kDoubleSize)); |
| 456 } | 519 } |
| 457 masm->add(sp, | 520 masm->add(sp, |
| 458 sp, | 521 sp, |
| 459 Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1))); | 522 Operand(kDoubleSize * (DwVfpRegister::kNumRegisters - 1))); |
| 460 } | 523 } |
| 461 UNREACHABLE(); // TODO(gc): Restore the caller save registers. | 524 masm->ldm(ia_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit()); |
| 462 } | 525 } |
| 463 | 526 |
| 464 inline Register object() { return object_; } | 527 inline Register object() { return object_; } |
| 465 inline Register address() { return address_; } | 528 inline Register address() { return address_; } |
| 466 inline Register scratch0() { return scratch0_; } | 529 inline Register scratch0() { return scratch0_; } |
| 530 inline Register scratch1() { return scratch1_; } |
| 467 | 531 |
| 468 private: | 532 private: |
| 469 Register object_; | 533 Register object_; |
| 470 Register address_; | 534 Register address_; |
| 471 Register scratch0_; | 535 Register scratch0_; |
| 536 Register scratch1_; |
| 472 | 537 |
| 473 Register GetRegThatIsNotOneOf(Register r1, | 538 Register GetRegThatIsNotOneOf(Register r1, |
| 474 Register r2, | 539 Register r2, |
| 475 Register r3) { | 540 Register r3) { |
| 476 for (int i = 0; i < Register::kNumAllocatableRegisters; i++) { | 541 for (int i = 0; i < Register::kNumAllocatableRegisters; i++) { |
| 477 Register candidate = Register::FromAllocationIndex(i); | 542 Register candidate = Register::FromAllocationIndex(i); |
| 478 if (candidate.is(r1)) continue; | 543 if (candidate.is(r1)) continue; |
| 479 if (candidate.is(r2)) continue; | 544 if (candidate.is(r2)) continue; |
| 480 if (candidate.is(r3)) continue; | 545 if (candidate.is(r3)) continue; |
| 481 return candidate; | 546 return candidate; |
| 482 } | 547 } |
| 483 UNREACHABLE(); | 548 UNREACHABLE(); |
| 484 return no_reg; | 549 return no_reg; |
| 485 } | 550 } |
| 486 friend class RecordWriteStub; | 551 friend class RecordWriteStub; |
| 487 }; | 552 }; |
| 488 | 553 |
| 489 enum OnNoNeedToInformIncrementalMarker { | 554 enum OnNoNeedToInformIncrementalMarker { |
| 490 kReturnOnNoNeedToInformIncrementalMarker, | 555 kReturnOnNoNeedToInformIncrementalMarker, |
| 491 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker | 556 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker |
| 492 }; | 557 }; |
| 493 | 558 |
| 494 void Generate(MacroAssembler* masm); | 559 void Generate(MacroAssembler* masm); |
| 495 void GenerateIncremental(MacroAssembler* masm); | 560 void GenerateIncremental(MacroAssembler* masm, Mode mode); |
| 496 void CheckNeedsToInformIncrementalMarker( | 561 void CheckNeedsToInformIncrementalMarker( |
| 497 MacroAssembler* masm, | 562 MacroAssembler* masm, |
| 498 OnNoNeedToInformIncrementalMarker on_no_need); | 563 OnNoNeedToInformIncrementalMarker on_no_need); |
| 499 void InformIncrementalMarker(MacroAssembler* masm); | 564 void InformIncrementalMarker(MacroAssembler* masm, Mode mode); |
| 500 | 565 |
| 501 Major MajorKey() { return RecordWrite; } | 566 Major MajorKey() { return RecordWrite; } |
| 502 | 567 |
| 503 int MinorKey() { | 568 int MinorKey() { |
| 504 return ObjectBits::encode(object_.code()) | | 569 return ObjectBits::encode(object_.code()) | |
| 505 ValueBits::encode(value_.code()) | | 570 ValueBits::encode(value_.code()) | |
| 506 AddressBits::encode(address_.code()) | | 571 AddressBits::encode(address_.code()) | |
| 507 RememberedSetActionBits::encode(remembered_set_action_) | | 572 RememberedSetActionBits::encode(remembered_set_action_) | |
| 508 SaveFPRegsModeBits::encode(save_fp_regs_mode_); | 573 SaveFPRegsModeBits::encode(save_fp_regs_mode_); |
| 509 } | 574 } |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 | 824 |
| 760 class LookupModeBits: public BitField<LookupMode, 0, 1> {}; | 825 class LookupModeBits: public BitField<LookupMode, 0, 1> {}; |
| 761 | 826 |
| 762 LookupMode mode_; | 827 LookupMode mode_; |
| 763 }; | 828 }; |
| 764 | 829 |
| 765 | 830 |
| 766 } } // namespace v8::internal | 831 } } // namespace v8::internal |
| 767 | 832 |
| 768 #endif // V8_ARM_CODE_STUBS_ARM_H_ | 833 #endif // V8_ARM_CODE_STUBS_ARM_H_ |
| OLD | NEW |