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