OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 class KindField : public BitField<Kind, 0, kKindFieldWidth> { }; | 85 class KindField : public BitField<Kind, 0, kKindFieldWidth> { }; |
86 | 86 |
87 LOperand(Kind kind, int index) { ConvertTo(kind, index); } | 87 LOperand(Kind kind, int index) { ConvertTo(kind, index); } |
88 | 88 |
89 unsigned value_; | 89 unsigned value_; |
90 }; | 90 }; |
91 | 91 |
92 | 92 |
93 class LUnallocated: public LOperand { | 93 class LUnallocated: public LOperand { |
94 public: | 94 public: |
95 enum Policy { | 95 enum BasicPolicy { |
| 96 FIXED_SLOT, |
| 97 EXTENDED_POLICY |
| 98 }; |
| 99 |
| 100 enum ExtendedPolicy { |
96 NONE, | 101 NONE, |
97 ANY, | 102 ANY, |
98 FIXED_REGISTER, | 103 FIXED_REGISTER, |
99 FIXED_DOUBLE_REGISTER, | 104 FIXED_DOUBLE_REGISTER, |
100 FIXED_SLOT, | |
101 MUST_HAVE_REGISTER, | 105 MUST_HAVE_REGISTER, |
102 WRITABLE_REGISTER, | 106 WRITABLE_REGISTER, |
103 SAME_AS_FIRST_INPUT | 107 SAME_AS_FIRST_INPUT |
104 }; | 108 }; |
105 | 109 |
106 // Lifetime of operand inside the instruction. | 110 // Lifetime of operand inside the instruction. |
107 enum Lifetime { | 111 enum Lifetime { |
108 // USED_AT_START operand is guaranteed to be live only at | 112 // USED_AT_START operand is guaranteed to be live only at |
109 // instruction start. Register allocator is free to assign the same register | 113 // instruction start. Register allocator is free to assign the same register |
110 // to some other operand used inside instruction (i.e. temporary or | 114 // to some other operand used inside instruction (i.e. temporary or |
111 // output). | 115 // output). |
112 USED_AT_START, | 116 USED_AT_START, |
113 | 117 |
114 // USED_AT_END operand is treated as live until the end of | 118 // USED_AT_END operand is treated as live until the end of |
115 // instruction. This means that register allocator will not reuse it's | 119 // instruction. This means that register allocator will not reuse it's |
116 // register for any other operand inside instruction. | 120 // register for any other operand inside instruction. |
117 USED_AT_END | 121 USED_AT_END |
118 }; | 122 }; |
119 | 123 |
120 explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) { | 124 explicit LUnallocated(ExtendedPolicy policy) : LOperand(UNALLOCATED, 0) { |
121 Initialize(policy, 0, USED_AT_END); | 125 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 126 value_ |= ExtendedPolicyField::encode(policy); |
| 127 value_ |= LifetimeField::encode(USED_AT_END); |
122 } | 128 } |
123 | 129 |
124 LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) { | 130 LUnallocated(BasicPolicy policy, int index) : LOperand(UNALLOCATED, 0) { |
125 Initialize(policy, fixed_index, USED_AT_END); | 131 ASSERT(policy == FIXED_SLOT); |
| 132 value_ |= BasicPolicyField::encode(policy); |
| 133 value_ |= index << FixedSlotIndexField::kShift; |
| 134 ASSERT(this->fixed_slot_index() == index); |
126 } | 135 } |
127 | 136 |
128 LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) { | 137 LUnallocated(ExtendedPolicy policy, int index) : LOperand(UNALLOCATED, 0) { |
129 Initialize(policy, 0, lifetime); | 138 ASSERT(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); |
| 139 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 140 value_ |= ExtendedPolicyField::encode(policy); |
| 141 value_ |= LifetimeField::encode(USED_AT_END); |
| 142 value_ |= FixedRegisterField::encode(index); |
130 } | 143 } |
131 | 144 |
132 // The superclass has a KindField. Some policies have a signed fixed | 145 LUnallocated(ExtendedPolicy policy, Lifetime lifetime) |
133 // index in the upper bits. | 146 : LOperand(UNALLOCATED, 0) { |
134 static const int kPolicyWidth = 3; | 147 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
135 static const int kLifetimeWidth = 1; | 148 value_ |= ExtendedPolicyField::encode(policy); |
136 static const int kVirtualRegisterWidth = 15; | 149 value_ |= LifetimeField::encode(lifetime); |
137 | |
138 static const int kPolicyShift = kKindFieldWidth; | |
139 static const int kLifetimeShift = kPolicyShift + kPolicyWidth; | |
140 static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth; | |
141 static const int kFixedIndexShift = | |
142 kVirtualRegisterShift + kVirtualRegisterWidth; | |
143 static const int kFixedIndexWidth = 32 - kFixedIndexShift; | |
144 STATIC_ASSERT(kFixedIndexWidth > 5); | |
145 | |
146 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { }; | |
147 | |
148 class LifetimeField | |
149 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> { | |
150 }; | |
151 | |
152 class VirtualRegisterField | |
153 : public BitField<unsigned, | |
154 kVirtualRegisterShift, | |
155 kVirtualRegisterWidth> { | |
156 }; | |
157 | |
158 static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth; | |
159 static const int kMaxFixedIndex = (1 << (kFixedIndexWidth - 1)) - 1; | |
160 static const int kMinFixedIndex = -(1 << (kFixedIndexWidth - 1)); | |
161 | |
162 bool HasAnyPolicy() const { | |
163 return policy() == ANY; | |
164 } | |
165 bool HasFixedPolicy() const { | |
166 return policy() == FIXED_REGISTER || | |
167 policy() == FIXED_DOUBLE_REGISTER || | |
168 policy() == FIXED_SLOT; | |
169 } | |
170 bool HasRegisterPolicy() const { | |
171 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; | |
172 } | |
173 bool HasSameAsInputPolicy() const { | |
174 return policy() == SAME_AS_FIRST_INPUT; | |
175 } | |
176 Policy policy() const { return PolicyField::decode(value_); } | |
177 void set_policy(Policy policy) { | |
178 value_ = PolicyField::update(value_, policy); | |
179 } | |
180 int fixed_index() const { | |
181 return static_cast<int>(value_) >> kFixedIndexShift; | |
182 } | |
183 | |
184 int virtual_register() const { | |
185 return VirtualRegisterField::decode(value_); | |
186 } | |
187 | |
188 void set_virtual_register(unsigned id) { | |
189 value_ = VirtualRegisterField::update(value_, id); | |
190 } | 150 } |
191 | 151 |
192 LUnallocated* CopyUnconstrained(Zone* zone) { | 152 LUnallocated* CopyUnconstrained(Zone* zone) { |
193 LUnallocated* result = new(zone) LUnallocated(ANY); | 153 LUnallocated* result = new(zone) LUnallocated(ANY); |
194 result->set_virtual_register(virtual_register()); | 154 result->set_virtual_register(virtual_register()); |
195 return result; | 155 return result; |
196 } | 156 } |
197 | 157 |
198 static LUnallocated* cast(LOperand* op) { | 158 static LUnallocated* cast(LOperand* op) { |
199 ASSERT(op->IsUnallocated()); | 159 ASSERT(op->IsUnallocated()); |
200 return reinterpret_cast<LUnallocated*>(op); | 160 return reinterpret_cast<LUnallocated*>(op); |
201 } | 161 } |
202 | 162 |
203 bool IsUsedAtStart() { | 163 // The encoding used for LUnallocated operands depends on the policy that is |
204 return LifetimeField::decode(value_) == USED_AT_START; | 164 // stored within the operand. The FIXED_SLOT policy uses a compact encoding |
| 165 // because it accommodates a larger pay-load. |
| 166 // |
| 167 // For FIXED_SLOT policy: |
| 168 // +------------------------------------------+ |
| 169 // | slot_index | vreg | 0 | 001 | |
| 170 // +------------------------------------------+ |
| 171 // |
| 172 // For all other (extended) policies: |
| 173 // +------------------------------------------+ |
| 174 // | reg_index | L | PPP | vreg | 1 | 001 | L ... Lifetime |
| 175 // +------------------------------------------+ P ... Policy |
| 176 // |
| 177 // The slot index is a signed value which requires us to decode it manually |
| 178 // instead of using the BitField utility class. |
| 179 |
| 180 // The superclass has a KindField. |
| 181 STATIC_ASSERT(kKindFieldWidth == 3); |
| 182 |
| 183 // BitFields for all unallocated operands. |
| 184 class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {}; |
| 185 // TODO(mstarzinger): Bump this from 15 bit to 18 bit in a follow-up CL. |
| 186 class VirtualRegisterField : public BitField<unsigned, 4, 15> {}; |
| 187 |
| 188 // BitFields specific to BasicPolicy::FIXED_SLOT. |
| 189 class FixedSlotIndexField : public BitField<int, 22, 10> {}; |
| 190 |
| 191 // BitFields specific to BasicPolicy::EXTENDED_POLICY. |
| 192 class ExtendedPolicyField : public BitField<ExtendedPolicy, 22, 3> {}; |
| 193 class LifetimeField : public BitField<Lifetime, 25, 1> {}; |
| 194 class FixedRegisterField : public BitField<int, 26, 6> {}; |
| 195 |
| 196 static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1; |
| 197 static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize; |
| 198 static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1; |
| 199 static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1)); |
| 200 |
| 201 // Predicates for the operand policy. |
| 202 bool HasAnyPolicy() const { |
| 203 return basic_policy() == EXTENDED_POLICY && |
| 204 extended_policy() == ANY; |
| 205 } |
| 206 bool HasFixedPolicy() const { |
| 207 return basic_policy() == FIXED_SLOT || |
| 208 extended_policy() == FIXED_REGISTER || |
| 209 extended_policy() == FIXED_DOUBLE_REGISTER; |
| 210 } |
| 211 bool HasRegisterPolicy() const { |
| 212 return basic_policy() == EXTENDED_POLICY && ( |
| 213 extended_policy() == WRITABLE_REGISTER || |
| 214 extended_policy() == MUST_HAVE_REGISTER); |
| 215 } |
| 216 bool HasSameAsInputPolicy() const { |
| 217 return basic_policy() == EXTENDED_POLICY && |
| 218 extended_policy() == SAME_AS_FIRST_INPUT; |
| 219 } |
| 220 bool HasFixedSlotPolicy() const { |
| 221 return basic_policy() == FIXED_SLOT; |
| 222 } |
| 223 bool HasFixedRegisterPolicy() const { |
| 224 return basic_policy() == EXTENDED_POLICY && |
| 225 extended_policy() == FIXED_REGISTER; |
| 226 } |
| 227 bool HasFixedDoubleRegisterPolicy() const { |
| 228 return basic_policy() == EXTENDED_POLICY && |
| 229 extended_policy() == FIXED_DOUBLE_REGISTER; |
| 230 } |
| 231 bool HasWritableRegisterPolicy() const { |
| 232 return basic_policy() == EXTENDED_POLICY && |
| 233 extended_policy() == WRITABLE_REGISTER; |
205 } | 234 } |
206 | 235 |
207 private: | 236 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. |
208 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) { | 237 BasicPolicy basic_policy() const { |
209 value_ |= PolicyField::encode(policy); | 238 return BasicPolicyField::decode(value_); |
210 value_ |= LifetimeField::encode(lifetime); | 239 } |
211 value_ |= fixed_index << kFixedIndexShift; | 240 |
212 ASSERT(this->fixed_index() == fixed_index); | 241 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. |
| 242 ExtendedPolicy extended_policy() const { |
| 243 ASSERT(basic_policy() == EXTENDED_POLICY); |
| 244 return ExtendedPolicyField::decode(value_); |
| 245 } |
| 246 |
| 247 // [fixed_slot_index]: Only for FIXED_SLOT. |
| 248 int fixed_slot_index() const { |
| 249 ASSERT(HasFixedSlotPolicy()); |
| 250 return static_cast<int>(value_) >> FixedSlotIndexField::kShift; |
| 251 } |
| 252 |
| 253 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. |
| 254 int fixed_register_index() const { |
| 255 ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); |
| 256 return FixedRegisterField::decode(value_); |
| 257 } |
| 258 |
| 259 // [virtual_register]: The virtual register ID for this operand. |
| 260 int virtual_register() const { |
| 261 return VirtualRegisterField::decode(value_); |
| 262 } |
| 263 void set_virtual_register(unsigned id) { |
| 264 value_ = VirtualRegisterField::update(value_, id); |
| 265 } |
| 266 |
| 267 // [lifetime]: Only for non-FIXED_SLOT. |
| 268 bool IsUsedAtStart() { |
| 269 ASSERT(basic_policy() == EXTENDED_POLICY); |
| 270 return LifetimeField::decode(value_) == USED_AT_START; |
213 } | 271 } |
214 }; | 272 }; |
215 | 273 |
216 | 274 |
217 class LMoveOperands BASE_EMBEDDED { | 275 class LMoveOperands BASE_EMBEDDED { |
218 public: | 276 public: |
219 LMoveOperands(LOperand* source, LOperand* destination) | 277 LMoveOperands(LOperand* source, LOperand* destination) |
220 : source_(source), destination_(destination) { | 278 : source_(source), destination_(destination) { |
221 } | 279 } |
222 | 280 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 NUMBER_CANDIDATE_IS_SMI, | 772 NUMBER_CANDIDATE_IS_SMI, |
715 NUMBER_CANDIDATE_IS_SMI_OR_HOLE, | 773 NUMBER_CANDIDATE_IS_SMI_OR_HOLE, |
716 NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE, | 774 NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE, |
717 NUMBER_CANDIDATE_IS_ANY_TAGGED | 775 NUMBER_CANDIDATE_IS_ANY_TAGGED |
718 }; | 776 }; |
719 | 777 |
720 | 778 |
721 } } // namespace v8::internal | 779 } } // namespace v8::internal |
722 | 780 |
723 #endif // V8_LITHIUM_H_ | 781 #endif // V8_LITHIUM_H_ |
OLD | NEW |