Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 namespace v8 { namespace internal { | 33 namespace v8 { namespace internal { |
| 34 | 34 |
| 35 // ------------------------------------------------------------------------- | 35 // ------------------------------------------------------------------------- |
| 36 // Result implementation. | 36 // Result implementation. |
| 37 | 37 |
| 38 Result::Result(Register reg, CodeGenerator* cgen) | 38 Result::Result(Register reg, CodeGenerator* cgen) |
| 39 : type_(REGISTER), | 39 : type_(REGISTER), |
| 40 cgen_(cgen) { | 40 cgen_(cgen) { |
| 41 data_.reg_ = reg; | 41 data_.reg_ = reg; |
| 42 ASSERT(!reg.is(no_reg)); | 42 ASSERT(reg.is_valid()); |
| 43 cgen_->allocator()->Use(reg); | 43 cgen_->allocator()->Use(reg); |
| 44 } | 44 } |
| 45 | 45 |
| 46 | 46 |
| 47 void Result::CopyTo(Result* destination) const { | 47 void Result::CopyTo(Result* destination) const { |
| 48 destination->type_ = type(); | 48 destination->type_ = type(); |
| 49 destination->cgen_ = cgen_; | 49 destination->cgen_ = cgen_; |
| 50 | 50 |
| 51 if (is_register()) { | 51 if (is_register()) { |
| 52 destination->data_.reg_ = reg(); | 52 destination->data_.reg_ = reg(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 void Result::ToRegister() { | 70 void Result::ToRegister() { |
| 71 ASSERT(is_valid()); | 71 ASSERT(is_valid()); |
| 72 if (is_constant()) { | 72 if (is_constant()) { |
| 73 Result fresh = cgen_->allocator()->Allocate(); | 73 Result fresh = cgen_->allocator()->Allocate(); |
| 74 ASSERT(fresh.is_valid()); | 74 ASSERT(fresh.is_valid()); |
| 75 cgen_->masm()->Set(fresh.reg(), Immediate(handle())); | 75 cgen_->masm()->Set(fresh.reg(), Immediate(handle())); |
| 76 // This result becomes a copy of the fresh one. | 76 // This result becomes a copy of the fresh one. |
| 77 cgen_->allocator()->Use(fresh.reg()); | 77 *this = fresh; |
| 78 type_ = REGISTER; | |
| 79 data_.reg_ = fresh.reg(); | |
| 80 } | 78 } |
| 81 ASSERT(is_register()); | 79 ASSERT(is_register()); |
| 82 } | 80 } |
| 83 | 81 |
| 84 | 82 |
| 83 void Result::ToRegister(Register target) { | |
| 84 ASSERT(is_valid()); | |
| 85 if (!is_register() || !reg().is(target)) { | |
| 86 Result fresh = cgen_->allocator()->Allocate(target); | |
| 87 ASSERT(fresh.is_valid()); | |
| 88 if (is_register()) { | |
| 89 cgen_->masm()->mov(fresh.reg(), reg()); | |
| 90 } else { | |
| 91 ASSERT(is_constant()); | |
| 92 cgen_->masm()->Set(fresh.reg(), Immediate(handle())); | |
| 93 } | |
| 94 *this = fresh; | |
| 95 } | |
|
William Hesse
2008/12/22 13:55:21
I think we are missing the case where this.reg() i
Kevin Millikin (Chromium)
2008/12/22 14:40:00
Yes, according to the comment in the header we do.
| |
| 96 ASSERT(is_register()); | |
| 97 ASSERT(reg().is(target)); | |
| 98 } | |
| 99 | |
| 100 | |
| 85 // ------------------------------------------------------------------------- | 101 // ------------------------------------------------------------------------- |
| 86 // RegisterAllocator implementation. | 102 // RegisterAllocator implementation. |
| 87 | 103 |
| 88 void RegisterAllocator::Initialize() { | 104 void RegisterAllocator::Initialize() { |
| 89 registers_.Reset(); | 105 registers_.Reset(); |
| 90 Use(esp); | 106 Use(esp); |
| 91 Use(ebp); | 107 Use(ebp); |
| 92 Use(esi); | 108 Use(esi); |
| 93 Use(edi); | 109 Use(edi); |
|
William Hesse
2008/12/22 13:55:21
Aren't we going to need to unuse edi before the Va
Kevin Millikin (Chromium)
2008/12/22 14:40:00
We can't jump before Enter is called on the frame.
| |
| 94 } | 110 } |
| 95 | 111 |
| 96 | 112 |
| 97 Result RegisterAllocator::AllocateWithoutSpilling() { | 113 Result RegisterAllocator::AllocateWithoutSpilling() { |
| 98 // Return the first free register, if any. | 114 // Return the first free register, if any. |
| 99 for (int i = 0; i < num_registers(); i++) { | 115 for (int i = 0; i < num_registers(); i++) { |
| 100 if (!is_used(i)) { | 116 if (!is_used(i)) { |
| 101 Register free_reg = { i }; | 117 Register free_reg = { i }; |
| 102 return Result(free_reg, cgen_); | 118 return Result(free_reg, cgen_); |
| 103 } | 119 } |
| 104 } | 120 } |
| 105 return Result(cgen_); | 121 return Result(cgen_); |
| 106 } | 122 } |
| 107 | 123 |
| 108 | 124 |
| 109 Result RegisterAllocator::Allocate() { | 125 Result RegisterAllocator::Allocate() { |
| 110 Result result = AllocateWithoutSpilling(); | 126 Result result = AllocateWithoutSpilling(); |
| 111 if (!result.is_valid()) { | 127 if (!result.is_valid()) { |
| 112 // Ask the current frame to spill a register. | 128 // Ask the current frame to spill a register. |
| 113 ASSERT(cgen_->frame() != NULL); | 129 ASSERT(cgen_->frame() != NULL); |
| 114 Register free_reg = cgen_->frame()->SpillAnyRegister(); | 130 Register free_reg = cgen_->frame()->SpillAnyRegister(); |
| 115 if (free_reg.is_valid()) { | 131 if (free_reg.is_valid()) { |
| 116 ASSERT(!is_used(free_reg.code())); | 132 ASSERT(!is_used(free_reg)); |
| 117 return Result(free_reg, cgen_); | 133 return Result(free_reg, cgen_); |
| 118 } | 134 } |
| 119 } | 135 } |
| 120 return result; | 136 return result; |
| 121 } | 137 } |
| 122 | 138 |
| 123 | 139 |
| 140 Result RegisterAllocator::Allocate(Register target) { | |
| 141 // If the target is not referenced, it can simply be allocated. | |
| 142 if (!is_used(target)) { | |
| 143 return Result(target, cgen_); | |
| 144 } | |
| 145 // If the target is only referenced in the frame, it can be spilled and | |
| 146 // then allocated. | |
| 147 ASSERT(cgen_->frame() != NULL); | |
| 148 if (count(target) == cgen_->frame()->register_count(target)) { | |
| 149 cgen_->frame()->Spill(target); | |
| 150 ASSERT(!is_used(target)); | |
| 151 return Result(target, cgen_); | |
| 152 } | |
| 153 // Otherwise (if it's referenced outside the frame) we cannot allocate it. | |
| 154 return Result(cgen_); | |
| 155 } | |
| 156 | |
| 157 | |
| 124 } } // namespace v8::internal | 158 } } // namespace v8::internal |
| OLD | NEW |