| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef RUNTIME_VM_LOCATIONS_H_ | 5 #ifndef RUNTIME_VM_LOCATIONS_H_ |
| 6 #define RUNTIME_VM_LOCATIONS_H_ | 6 #define RUNTIME_VM_LOCATIONS_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/bitfield.h" | 10 #include "vm/bitfield.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 kPairLocationTag = 2, | 80 kPairLocationTag = 2, |
| 81 | 81 |
| 82 // Unallocated location represents a location that is not fixed and can be | 82 // Unallocated location represents a location that is not fixed and can be |
| 83 // allocated by a register allocator. Each unallocated location has | 83 // allocated by a register allocator. Each unallocated location has |
| 84 // a policy that specifies what kind of location is suitable. Payload | 84 // a policy that specifies what kind of location is suitable. Payload |
| 85 // contains register allocation policy. | 85 // contains register allocation policy. |
| 86 kUnallocated = 3, | 86 kUnallocated = 3, |
| 87 | 87 |
| 88 // Spill slots allocated by the register allocator. Payload contains | 88 // Spill slots allocated by the register allocator. Payload contains |
| 89 // a spill index. | 89 // a spill index. |
| 90 kStackSlot = 4, // Word size slot. | 90 kStackSlot = 4, // Word size slot. |
| 91 kDoubleStackSlot = 7, // 64bit stack slot. | 91 kDoubleStackSlot = 7, // 64bit stack slot. |
| 92 kQuadStackSlot = 11, // 128bit stack slot. | 92 kQuadStackSlot = 11, // 128bit stack slot. |
| 93 | 93 |
| 94 // Register location represents a fixed register. Payload contains | 94 // Register location represents a fixed register. Payload contains |
| 95 // register code. | 95 // register code. |
| 96 kRegister = 8, | 96 kRegister = 8, |
| 97 | 97 |
| 98 // FpuRegister location represents a fixed fpu register. Payload contains | 98 // FpuRegister location represents a fixed fpu register. Payload contains |
| 99 // its code. | 99 // its code. |
| 100 kFpuRegister = 12, | 100 kFpuRegister = 12, |
| 101 }; | 101 }; |
| 102 | 102 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 125 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag); | 125 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag); |
| 126 | 126 |
| 127 // Verify tags and tagmask. | 127 // Verify tags and tagmask. |
| 128 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag); | 128 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag); |
| 129 | 129 |
| 130 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag); | 130 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag); |
| 131 | 131 |
| 132 ASSERT(IsInvalid()); | 132 ASSERT(IsInvalid()); |
| 133 } | 133 } |
| 134 | 134 |
| 135 Location(const Location& other) : ValueObject(), value_(other.value_) { } | 135 Location(const Location& other) : ValueObject(), value_(other.value_) {} |
| 136 | 136 |
| 137 Location& operator=(const Location& other) { | 137 Location& operator=(const Location& other) { |
| 138 value_ = other.value_; | 138 value_ = other.value_; |
| 139 return *this; | 139 return *this; |
| 140 } | 140 } |
| 141 | 141 |
| 142 bool IsInvalid() const { | 142 bool IsInvalid() const { return value_ == kInvalidLocation; } |
| 143 return value_ == kInvalidLocation; | |
| 144 } | |
| 145 | 143 |
| 146 // Constants. | 144 // Constants. |
| 147 bool IsConstant() const { | 145 bool IsConstant() const { |
| 148 return (value_ & kLocationTagMask) == kConstantTag; | 146 return (value_ & kLocationTagMask) == kConstantTag; |
| 149 } | 147 } |
| 150 | 148 |
| 151 static Location Constant(const ConstantInstr* obj) { | 149 static Location Constant(const ConstantInstr* obj) { |
| 152 Location loc(reinterpret_cast<uword>(obj) | kConstantTag); | 150 Location loc(reinterpret_cast<uword>(obj) | kConstantTag); |
| 153 ASSERT(obj == loc.constant_instruction()); | 151 ASSERT(obj == loc.constant_instruction()); |
| 154 return loc; | 152 return loc; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 172 // Unallocated locations. | 170 // Unallocated locations. |
| 173 enum Policy { | 171 enum Policy { |
| 174 kAny, | 172 kAny, |
| 175 kPrefersRegister, | 173 kPrefersRegister, |
| 176 kRequiresRegister, | 174 kRequiresRegister, |
| 177 kRequiresFpuRegister, | 175 kRequiresFpuRegister, |
| 178 kWritableRegister, | 176 kWritableRegister, |
| 179 kSameAsFirstInput, | 177 kSameAsFirstInput, |
| 180 }; | 178 }; |
| 181 | 179 |
| 182 bool IsUnallocated() const { | 180 bool IsUnallocated() const { return kind() == kUnallocated; } |
| 183 return kind() == kUnallocated; | |
| 184 } | |
| 185 | 181 |
| 186 bool IsRegisterBeneficial() { | 182 bool IsRegisterBeneficial() { return !Equals(Any()); } |
| 187 return !Equals(Any()); | |
| 188 } | |
| 189 | 183 |
| 190 static Location UnallocatedLocation(Policy policy) { | 184 static Location UnallocatedLocation(Policy policy) { |
| 191 return Location(kUnallocated, PolicyField::encode(policy)); | 185 return Location(kUnallocated, PolicyField::encode(policy)); |
| 192 } | 186 } |
| 193 | 187 |
| 194 // Any free register is suitable to replace this unallocated location. | 188 // Any free register is suitable to replace this unallocated location. |
| 195 static Location Any() { | 189 static Location Any() { return UnallocatedLocation(kAny); } |
| 196 return UnallocatedLocation(kAny); | |
| 197 } | |
| 198 | 190 |
| 199 static Location PrefersRegister() { | 191 static Location PrefersRegister() { |
| 200 return UnallocatedLocation(kPrefersRegister); | 192 return UnallocatedLocation(kPrefersRegister); |
| 201 } | 193 } |
| 202 | 194 |
| 203 static Location RequiresRegister() { | 195 static Location RequiresRegister() { |
| 204 return UnallocatedLocation(kRequiresRegister); | 196 return UnallocatedLocation(kRequiresRegister); |
| 205 } | 197 } |
| 206 | 198 |
| 207 static Location RequiresFpuRegister() { | 199 static Location RequiresFpuRegister() { |
| 208 return UnallocatedLocation(kRequiresFpuRegister); | 200 return UnallocatedLocation(kRequiresFpuRegister); |
| 209 } | 201 } |
| 210 | 202 |
| 211 static Location WritableRegister() { | 203 static Location WritableRegister() { |
| 212 return UnallocatedLocation(kWritableRegister); | 204 return UnallocatedLocation(kWritableRegister); |
| 213 } | 205 } |
| 214 | 206 |
| 215 // The location of the first input to the instruction will be | 207 // The location of the first input to the instruction will be |
| 216 // used to replace this unallocated location. | 208 // used to replace this unallocated location. |
| 217 static Location SameAsFirstInput() { | 209 static Location SameAsFirstInput() { |
| 218 return UnallocatedLocation(kSameAsFirstInput); | 210 return UnallocatedLocation(kSameAsFirstInput); |
| 219 } | 211 } |
| 220 | 212 |
| 221 // Empty location. Used if there the location should be ignored. | 213 // Empty location. Used if there the location should be ignored. |
| 222 static Location NoLocation() { | 214 static Location NoLocation() { return Location(); } |
| 223 return Location(); | |
| 224 } | |
| 225 | 215 |
| 226 Policy policy() const { | 216 Policy policy() const { |
| 227 ASSERT(IsUnallocated()); | 217 ASSERT(IsUnallocated()); |
| 228 return PolicyField::decode(payload()); | 218 return PolicyField::decode(payload()); |
| 229 } | 219 } |
| 230 | 220 |
| 231 // Register locations. | 221 // Register locations. |
| 232 static Location RegisterLocation(Register reg) { | 222 static Location RegisterLocation(Register reg) { |
| 233 return Location(kRegister, reg); | 223 return Location(kRegister, reg); |
| 234 } | 224 } |
| 235 | 225 |
| 236 bool IsRegister() const { | 226 bool IsRegister() const { return kind() == kRegister; } |
| 237 return kind() == kRegister; | |
| 238 } | |
| 239 | 227 |
| 240 Register reg() const { | 228 Register reg() const { |
| 241 ASSERT(IsRegister()); | 229 ASSERT(IsRegister()); |
| 242 return static_cast<Register>(payload()); | 230 return static_cast<Register>(payload()); |
| 243 } | 231 } |
| 244 | 232 |
| 245 // FpuRegister locations. | 233 // FpuRegister locations. |
| 246 static Location FpuRegisterLocation(FpuRegister reg) { | 234 static Location FpuRegisterLocation(FpuRegister reg) { |
| 247 return Location(kFpuRegister, reg); | 235 return Location(kFpuRegister, reg); |
| 248 } | 236 } |
| 249 | 237 |
| 250 bool IsFpuRegister() const { | 238 bool IsFpuRegister() const { return kind() == kFpuRegister; } |
| 251 return kind() == kFpuRegister; | |
| 252 } | |
| 253 | 239 |
| 254 FpuRegister fpu_reg() const { | 240 FpuRegister fpu_reg() const { |
| 255 ASSERT(IsFpuRegister()); | 241 ASSERT(IsFpuRegister()); |
| 256 return static_cast<FpuRegister>(payload()); | 242 return static_cast<FpuRegister>(payload()); |
| 257 } | 243 } |
| 258 | 244 |
| 259 static bool IsMachineRegisterKind(Kind kind) { | 245 static bool IsMachineRegisterKind(Kind kind) { |
| 260 return (kind == kRegister) || (kind == kFpuRegister); | 246 return (kind == kRegister) || (kind == kFpuRegister); |
| 261 } | 247 } |
| 262 | 248 |
| 263 static Location MachineRegisterLocation(Kind kind, | 249 static Location MachineRegisterLocation(Kind kind, intptr_t reg) { |
| 264 intptr_t reg) { | |
| 265 if (kind == kRegister) { | 250 if (kind == kRegister) { |
| 266 return RegisterLocation(static_cast<Register>(reg)); | 251 return RegisterLocation(static_cast<Register>(reg)); |
| 267 } else { | 252 } else { |
| 268 ASSERT(kind == kFpuRegister); | 253 ASSERT(kind == kFpuRegister); |
| 269 return FpuRegisterLocation(static_cast<FpuRegister>(reg)); | 254 return FpuRegisterLocation(static_cast<FpuRegister>(reg)); |
| 270 } | 255 } |
| 271 } | 256 } |
| 272 | 257 |
| 273 bool IsMachineRegister() const { | 258 bool IsMachineRegister() const { return IsMachineRegisterKind(kind()); } |
| 274 return IsMachineRegisterKind(kind()); | |
| 275 } | |
| 276 | 259 |
| 277 intptr_t register_code() const { | 260 intptr_t register_code() const { |
| 278 ASSERT(IsMachineRegister()); | 261 ASSERT(IsMachineRegister()); |
| 279 return static_cast<intptr_t>(payload()); | 262 return static_cast<intptr_t>(payload()); |
| 280 } | 263 } |
| 281 | 264 |
| 282 static uword EncodeStackIndex(intptr_t stack_index) { | 265 static uword EncodeStackIndex(intptr_t stack_index) { |
| 283 ASSERT((-kStackIndexBias <= stack_index) && | 266 ASSERT((-kStackIndexBias <= stack_index) && |
| 284 (stack_index < kStackIndexBias)); | 267 (stack_index < kStackIndexBias)); |
| 285 return static_cast<uword>(kStackIndexBias + stack_index); | 268 return static_cast<uword>(kStackIndexBias + stack_index); |
| 286 } | 269 } |
| 287 | 270 |
| 288 // Spill slots. | 271 // Spill slots. |
| 289 static Location StackSlot(intptr_t stack_index, | 272 static Location StackSlot(intptr_t stack_index, Register base = FPREG) { |
| 290 Register base = FPREG) { | 273 uword payload = StackSlotBaseField::encode(base) | |
| 291 uword payload = StackSlotBaseField::encode(base) | 274 StackIndexField::encode(EncodeStackIndex(stack_index)); |
| 292 | StackIndexField::encode(EncodeStackIndex(stack_index)); | |
| 293 Location loc(kStackSlot, payload); | 275 Location loc(kStackSlot, payload); |
| 294 // Ensure that sign is preserved. | 276 // Ensure that sign is preserved. |
| 295 ASSERT(loc.stack_index() == stack_index); | 277 ASSERT(loc.stack_index() == stack_index); |
| 296 return loc; | 278 return loc; |
| 297 } | 279 } |
| 298 | 280 |
| 299 bool IsStackSlot() const { | 281 bool IsStackSlot() const { return kind() == kStackSlot; } |
| 300 return kind() == kStackSlot; | |
| 301 } | |
| 302 | 282 |
| 303 static Location DoubleStackSlot(intptr_t stack_index) { | 283 static Location DoubleStackSlot(intptr_t stack_index) { |
| 304 uword payload = StackSlotBaseField::encode(FPREG) | 284 uword payload = StackSlotBaseField::encode(FPREG) | |
| 305 | StackIndexField::encode(EncodeStackIndex(stack_index)); | 285 StackIndexField::encode(EncodeStackIndex(stack_index)); |
| 306 Location loc(kDoubleStackSlot, payload); | 286 Location loc(kDoubleStackSlot, payload); |
| 307 // Ensure that sign is preserved. | 287 // Ensure that sign is preserved. |
| 308 ASSERT(loc.stack_index() == stack_index); | 288 ASSERT(loc.stack_index() == stack_index); |
| 309 return loc; | 289 return loc; |
| 310 } | 290 } |
| 311 | 291 |
| 312 bool IsDoubleStackSlot() const { | 292 bool IsDoubleStackSlot() const { return kind() == kDoubleStackSlot; } |
| 313 return kind() == kDoubleStackSlot; | |
| 314 } | |
| 315 | 293 |
| 316 static Location QuadStackSlot(intptr_t stack_index) { | 294 static Location QuadStackSlot(intptr_t stack_index) { |
| 317 uword payload = StackSlotBaseField::encode(FPREG) | 295 uword payload = StackSlotBaseField::encode(FPREG) | |
| 318 | StackIndexField::encode(EncodeStackIndex(stack_index)); | 296 StackIndexField::encode(EncodeStackIndex(stack_index)); |
| 319 Location loc(kQuadStackSlot, payload); | 297 Location loc(kQuadStackSlot, payload); |
| 320 // Ensure that sign is preserved. | 298 // Ensure that sign is preserved. |
| 321 ASSERT(loc.stack_index() == stack_index); | 299 ASSERT(loc.stack_index() == stack_index); |
| 322 return loc; | 300 return loc; |
| 323 } | 301 } |
| 324 | 302 |
| 325 bool IsQuadStackSlot() const { | 303 bool IsQuadStackSlot() const { return kind() == kQuadStackSlot; } |
| 326 return kind() == kQuadStackSlot; | |
| 327 } | |
| 328 | 304 |
| 329 Register base_reg() const { | 305 Register base_reg() const { |
| 330 ASSERT(HasStackIndex()); | 306 ASSERT(HasStackIndex()); |
| 331 return StackSlotBaseField::decode(payload()); | 307 return StackSlotBaseField::decode(payload()); |
| 332 } | 308 } |
| 333 | 309 |
| 334 intptr_t stack_index() const { | 310 intptr_t stack_index() const { |
| 335 ASSERT(HasStackIndex()); | 311 ASSERT(HasStackIndex()); |
| 336 // Decode stack index manually to preserve sign. | 312 // Decode stack index manually to preserve sign. |
| 337 return StackIndexField::decode(payload()) - kStackIndexBias; | 313 return StackIndexField::decode(payload()) - kStackIndexBias; |
| 338 } | 314 } |
| 339 | 315 |
| 340 bool HasStackIndex() const { | 316 bool HasStackIndex() const { |
| 341 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot(); | 317 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot(); |
| 342 } | 318 } |
| 343 | 319 |
| 344 // DBC does not have an notion of 'address' in its instruction set. | 320 // DBC does not have an notion of 'address' in its instruction set. |
| 345 #if !defined(TARGET_ARCH_DBC) | 321 #if !defined(TARGET_ARCH_DBC) |
| 346 // Return a memory operand for stack slot locations. | 322 // Return a memory operand for stack slot locations. |
| 347 Address ToStackSlotAddress() const; | 323 Address ToStackSlotAddress() const; |
| 348 #endif | 324 #endif |
| 349 | 325 |
| 350 // Returns the offset from the frame pointer for stack slot locations. | 326 // Returns the offset from the frame pointer for stack slot locations. |
| 351 intptr_t ToStackSlotOffset() const; | 327 intptr_t ToStackSlotOffset() const; |
| 352 | 328 |
| 353 // Constants. | 329 // Constants. |
| 354 static Location RegisterOrConstant(Value* value); | 330 static Location RegisterOrConstant(Value* value); |
| 355 static Location RegisterOrSmiConstant(Value* value); | 331 static Location RegisterOrSmiConstant(Value* value); |
| 356 static Location WritableRegisterOrSmiConstant(Value* value); | 332 static Location WritableRegisterOrSmiConstant(Value* value); |
| 357 static Location FixedRegisterOrConstant(Value* value, Register reg); | 333 static Location FixedRegisterOrConstant(Value* value, Register reg); |
| 358 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); | 334 static Location FixedRegisterOrSmiConstant(Value* value, Register reg); |
| 359 static Location AnyOrConstant(Value* value); | 335 static Location AnyOrConstant(Value* value); |
| 360 | 336 |
| 361 const char* Name() const; | 337 const char* Name() const; |
| 362 void PrintTo(BufferFormatter* f) const; | 338 void PrintTo(BufferFormatter* f) const; |
| 363 void Print() const; | 339 void Print() const; |
| 364 const char* ToCString() const; | 340 const char* ToCString() const; |
| 365 | 341 |
| 366 // Compare two locations. | 342 // Compare two locations. |
| 367 bool Equals(Location other) const { | 343 bool Equals(Location other) const { return value_ == other.value_; } |
| 368 return value_ == other.value_; | |
| 369 } | |
| 370 | 344 |
| 371 // If current location is constant might return something that | 345 // If current location is constant might return something that |
| 372 // is not equal to any Kind. | 346 // is not equal to any Kind. |
| 373 Kind kind() const { | 347 Kind kind() const { return KindField::decode(value_); } |
| 374 return KindField::decode(value_); | |
| 375 } | |
| 376 | 348 |
| 377 Location Copy() const; | 349 Location Copy() const; |
| 378 | 350 |
| 379 Location RemapForSlowPath(Definition* def, | 351 Location RemapForSlowPath(Definition* def, |
| 380 intptr_t* cpu_reg_slots, | 352 intptr_t* cpu_reg_slots, |
| 381 intptr_t* fpu_reg_slots) const; | 353 intptr_t* fpu_reg_slots) const; |
| 382 | 354 |
| 383 private: | 355 private: |
| 384 explicit Location(uword value) : value_(value) { } | 356 explicit Location(uword value) : value_(value) {} |
| 385 | 357 |
| 386 Location(Kind kind, uword payload) | 358 Location(Kind kind, uword payload) |
| 387 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 359 : value_(KindField::encode(kind) | PayloadField::encode(payload)) {} |
| 388 | 360 |
| 389 uword payload() const { | 361 uword payload() const { return PayloadField::decode(value_); } |
| 390 return PayloadField::decode(value_); | |
| 391 } | |
| 392 | 362 |
| 393 class KindField : public BitField<uword, Kind, 0, kBitsForKind> {}; | 363 class KindField : public BitField<uword, Kind, 0, kBitsForKind> {}; |
| 394 class PayloadField : | 364 class PayloadField |
| 395 public BitField<uword, uword, kBitsForKind, kBitsForPayload> {}; | 365 : public BitField<uword, uword, kBitsForKind, kBitsForPayload> {}; |
| 396 | 366 |
| 397 // Layout for kUnallocated locations payload. | 367 // Layout for kUnallocated locations payload. |
| 398 typedef BitField<uword, Policy, 0, 3> PolicyField; | 368 typedef BitField<uword, Policy, 0, 3> PolicyField; |
| 399 | 369 |
| 400 // Layout for stack slots. | 370 // Layout for stack slots. |
| 401 #if defined(ARCH_IS_64_BIT) | 371 #if defined(ARCH_IS_64_BIT) |
| 402 static const intptr_t kBitsForBaseReg = 6; | 372 static const intptr_t kBitsForBaseReg = 6; |
| 403 #else | 373 #else |
| 404 static const intptr_t kBitsForBaseReg = 5; | 374 static const intptr_t kBitsForBaseReg = 5; |
| 405 #endif | 375 #endif |
| 406 static const intptr_t kBitsForStackIndex = kBitsForPayload - kBitsForBaseReg; | 376 static const intptr_t kBitsForStackIndex = kBitsForPayload - kBitsForBaseReg; |
| 407 class StackSlotBaseField : | 377 class StackSlotBaseField |
| 408 public BitField<uword, Register, 0, kBitsForBaseReg> {}; | 378 : public BitField<uword, Register, 0, kBitsForBaseReg> {}; |
| 409 class StackIndexField : | 379 class StackIndexField |
| 410 public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> {}; | 380 : public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> { |
| 381 }; |
| 411 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters); | 382 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters); |
| 412 | 383 |
| 413 static const intptr_t kStackIndexBias = | 384 static const intptr_t kStackIndexBias = static_cast<intptr_t>(1) |
| 414 static_cast<intptr_t>(1) << (kBitsForStackIndex - 1); | 385 << (kBitsForStackIndex - 1); |
| 415 | 386 |
| 416 // Location either contains kind and payload fields or a tagged handle for | 387 // Location either contains kind and payload fields or a tagged handle for |
| 417 // a constant locations. Values of enumeration Kind are selected in such a | 388 // a constant locations. Values of enumeration Kind are selected in such a |
| 418 // way that none of them can be interpreted as a kConstant tag. | 389 // way that none of them can be interpreted as a kConstant tag. |
| 419 uword value_; | 390 uword value_; |
| 420 }; | 391 }; |
| 421 | 392 |
| 422 | 393 |
| 423 class PairLocation : public ZoneAllocated { | 394 class PairLocation : public ZoneAllocated { |
| 424 public: | 395 public: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 447 ASSERT(i < kPairLength); | 418 ASSERT(i < kPairLength); |
| 448 return &locations_[i]; | 419 return &locations_[i]; |
| 449 } | 420 } |
| 450 | 421 |
| 451 private: | 422 private: |
| 452 static const intptr_t kPairLength = 2; | 423 static const intptr_t kPairLength = 2; |
| 453 Location locations_[kPairLength]; | 424 Location locations_[kPairLength]; |
| 454 }; | 425 }; |
| 455 | 426 |
| 456 | 427 |
| 457 template<typename T> | 428 template <typename T> |
| 458 class SmallSet { | 429 class SmallSet { |
| 459 public: | 430 public: |
| 460 SmallSet() : data_(0) { } | 431 SmallSet() : data_(0) {} |
| 461 | 432 |
| 462 explicit SmallSet(intptr_t data) : data_(data) { } | 433 explicit SmallSet(intptr_t data) : data_(data) {} |
| 463 | 434 |
| 464 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } | 435 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; } |
| 465 | 436 |
| 466 void Add(T value) { data_ |= ToMask(value); } | 437 void Add(T value) { data_ |= ToMask(value); } |
| 467 | 438 |
| 468 void Remove(T value) { data_ &= ~ToMask(value); } | 439 void Remove(T value) { data_ &= ~ToMask(value); } |
| 469 | 440 |
| 470 bool IsEmpty() const { return data_ == 0; } | 441 bool IsEmpty() const { return data_ == 0; } |
| 471 | 442 |
| 472 intptr_t data() const { return data_; } | 443 intptr_t data() const { return data_; } |
| 473 | 444 |
| 474 private: | 445 private: |
| 475 static intptr_t ToMask(T value) { | 446 static intptr_t ToMask(T value) { |
| 476 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); | 447 ASSERT(static_cast<intptr_t>(value) < (kWordSize * kBitsPerByte)); |
| 477 return 1 << static_cast<intptr_t>(value); | 448 return 1 << static_cast<intptr_t>(value); |
| 478 } | 449 } |
| 479 | 450 |
| 480 intptr_t data_; | 451 intptr_t data_; |
| 481 }; | 452 }; |
| 482 | 453 |
| 483 | 454 |
| 484 class RegisterSet : public ValueObject { | 455 class RegisterSet : public ValueObject { |
| 485 public: | 456 public: |
| 486 RegisterSet() | 457 RegisterSet() |
| 487 : cpu_registers_(), | 458 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() { |
| 488 untagged_cpu_registers_(), | |
| 489 fpu_registers_() { | |
| 490 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); | 459 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte)); |
| 491 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); | 460 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte)); |
| 492 } | 461 } |
| 493 | 462 |
| 494 | 463 |
| 495 void Add(Location loc, Representation rep = kTagged) { | 464 void Add(Location loc, Representation rep = kTagged) { |
| 496 if (loc.IsRegister()) { | 465 if (loc.IsRegister()) { |
| 497 cpu_registers_.Add(loc.reg()); | 466 cpu_registers_.Add(loc.reg()); |
| 498 if (rep != kTagged) { | 467 if (rep != kTagged) { |
| 499 // CPU register contains an untagged value. | 468 // CPU register contains an untagged value. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 521 UNREACHABLE(); | 490 UNREACHABLE(); |
| 522 return false; | 491 return false; |
| 523 } | 492 } |
| 524 } | 493 } |
| 525 | 494 |
| 526 void DebugPrint() { | 495 void DebugPrint() { |
| 527 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 496 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
| 528 Register r = static_cast<Register>(i); | 497 Register r = static_cast<Register>(i); |
| 529 if (ContainsRegister(r)) { | 498 if (ContainsRegister(r)) { |
| 530 THR_Print("%s %s\n", Assembler::RegisterName(r), | 499 THR_Print("%s %s\n", Assembler::RegisterName(r), |
| 531 IsTagged(r) ? "tagged" : "untagged"); | 500 IsTagged(r) ? "tagged" : "untagged"); |
| 532 } | 501 } |
| 533 } | 502 } |
| 534 | 503 |
| 535 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { | 504 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { |
| 536 FpuRegister r = static_cast<FpuRegister>(i); | 505 FpuRegister r = static_cast<FpuRegister>(i); |
| 537 if (ContainsFpuRegister(r)) { | 506 if (ContainsFpuRegister(r)) { |
| 538 THR_Print("%s\n", Assembler::FpuRegisterName(r)); | 507 THR_Print("%s\n", Assembler::FpuRegisterName(r)); |
| 539 } | 508 } |
| 540 } | 509 } |
| 541 } | 510 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 SmallSet<Register> untagged_cpu_registers_; | 546 SmallSet<Register> untagged_cpu_registers_; |
| 578 SmallSet<FpuRegister> fpu_registers_; | 547 SmallSet<FpuRegister> fpu_registers_; |
| 579 | 548 |
| 580 DISALLOW_COPY_AND_ASSIGN(RegisterSet); | 549 DISALLOW_COPY_AND_ASSIGN(RegisterSet); |
| 581 }; | 550 }; |
| 582 | 551 |
| 583 | 552 |
| 584 // Specification of locations for inputs and output. | 553 // Specification of locations for inputs and output. |
| 585 class LocationSummary : public ZoneAllocated { | 554 class LocationSummary : public ZoneAllocated { |
| 586 public: | 555 public: |
| 587 enum ContainsCall { | 556 enum ContainsCall { kNoCall, kCall, kCallOnSlowPath }; |
| 588 kNoCall, | |
| 589 kCall, | |
| 590 kCallOnSlowPath | |
| 591 }; | |
| 592 | 557 |
| 593 LocationSummary(Zone* zone, | 558 LocationSummary(Zone* zone, |
| 594 intptr_t input_count, | 559 intptr_t input_count, |
| 595 intptr_t temp_count, | 560 intptr_t temp_count, |
| 596 LocationSummary::ContainsCall contains_call); | 561 LocationSummary::ContainsCall contains_call); |
| 597 | 562 |
| 598 intptr_t input_count() const { | 563 intptr_t input_count() const { return num_inputs_; } |
| 599 return num_inputs_; | |
| 600 } | |
| 601 | 564 |
| 602 Location in(intptr_t index) const { | 565 Location in(intptr_t index) const { |
| 603 ASSERT(index >= 0); | 566 ASSERT(index >= 0); |
| 604 ASSERT(index < num_inputs_); | 567 ASSERT(index < num_inputs_); |
| 605 return input_locations_[index]; | 568 return input_locations_[index]; |
| 606 } | 569 } |
| 607 | 570 |
| 608 Location* in_slot(intptr_t index) { | 571 Location* in_slot(intptr_t index) { |
| 609 ASSERT(index >= 0); | 572 ASSERT(index >= 0); |
| 610 ASSERT(index < num_inputs_); | 573 ASSERT(index < num_inputs_); |
| 611 return &input_locations_[index]; | 574 return &input_locations_[index]; |
| 612 } | 575 } |
| 613 | 576 |
| 614 void set_in(intptr_t index, Location loc) { | 577 void set_in(intptr_t index, Location loc) { |
| 615 ASSERT(index >= 0); | 578 ASSERT(index >= 0); |
| 616 ASSERT(index < num_inputs_); | 579 ASSERT(index < num_inputs_); |
| 617 ASSERT(!always_calls() || loc.IsMachineRegister()); | 580 ASSERT(!always_calls() || loc.IsMachineRegister()); |
| 618 input_locations_[index] = loc; | 581 input_locations_[index] = loc; |
| 619 } | 582 } |
| 620 | 583 |
| 621 intptr_t temp_count() const { | 584 intptr_t temp_count() const { return num_temps_; } |
| 622 return num_temps_; | |
| 623 } | |
| 624 | 585 |
| 625 Location temp(intptr_t index) const { | 586 Location temp(intptr_t index) const { |
| 626 ASSERT(index >= 0); | 587 ASSERT(index >= 0); |
| 627 ASSERT(index < num_temps_); | 588 ASSERT(index < num_temps_); |
| 628 return temp_locations_[index]; | 589 return temp_locations_[index]; |
| 629 } | 590 } |
| 630 | 591 |
| 631 Location* temp_slot(intptr_t index) { | 592 Location* temp_slot(intptr_t index) { |
| 632 ASSERT(index >= 0); | 593 ASSERT(index >= 0); |
| 633 ASSERT(index < num_temps_); | 594 ASSERT(index < num_temps_); |
| 634 return &temp_locations_[index]; | 595 return &temp_locations_[index]; |
| 635 } | 596 } |
| 636 | 597 |
| 637 void set_temp(intptr_t index, Location loc) { | 598 void set_temp(intptr_t index, Location loc) { |
| 638 ASSERT(index >= 0); | 599 ASSERT(index >= 0); |
| 639 ASSERT(index < num_temps_); | 600 ASSERT(index < num_temps_); |
| 640 ASSERT(!always_calls() || loc.IsMachineRegister()); | 601 ASSERT(!always_calls() || loc.IsMachineRegister()); |
| 641 temp_locations_[index] = loc; | 602 temp_locations_[index] = loc; |
| 642 } | 603 } |
| 643 | 604 |
| 644 intptr_t output_count() const { | 605 intptr_t output_count() const { return 1; } |
| 645 return 1; | |
| 646 } | |
| 647 | 606 |
| 648 Location out(intptr_t index) const { | 607 Location out(intptr_t index) const { |
| 649 ASSERT(index == 0); | 608 ASSERT(index == 0); |
| 650 return output_location_; | 609 return output_location_; |
| 651 } | 610 } |
| 652 | 611 |
| 653 Location* out_slot(intptr_t index) { | 612 Location* out_slot(intptr_t index) { |
| 654 ASSERT(index == 0); | 613 ASSERT(index == 0); |
| 655 return &output_location_; | 614 return &output_location_; |
| 656 } | 615 } |
| 657 | 616 |
| 658 void set_out(intptr_t index, Location loc) { | 617 void set_out(intptr_t index, Location loc) { |
| 659 ASSERT(index == 0); | 618 ASSERT(index == 0); |
| 660 // DBC calls are different from call on other architectures so this | 619 // DBC calls are different from call on other architectures so this |
| 661 // assert doesn't make sense. | 620 // assert doesn't make sense. |
| 662 #if !defined(TARGET_ARCH_DBC) | 621 #if !defined(TARGET_ARCH_DBC) |
| 663 ASSERT(!always_calls() || | 622 ASSERT(!always_calls() || (loc.IsMachineRegister() || loc.IsInvalid() || |
| 664 (loc.IsMachineRegister() || loc.IsInvalid() || | 623 loc.IsPairLocation())); |
| 665 loc.IsPairLocation())); | |
| 666 #endif | 624 #endif |
| 667 output_location_ = loc; | 625 output_location_ = loc; |
| 668 } | 626 } |
| 669 | 627 |
| 670 BitmapBuilder* stack_bitmap() { | 628 BitmapBuilder* stack_bitmap() { |
| 671 if (stack_bitmap_ == NULL) { | 629 if (stack_bitmap_ == NULL) { |
| 672 stack_bitmap_ = new BitmapBuilder(); | 630 stack_bitmap_ = new BitmapBuilder(); |
| 673 } | 631 } |
| 674 return stack_bitmap_; | 632 return stack_bitmap_; |
| 675 } | 633 } |
| 676 void SetStackBit(intptr_t index) { | 634 void SetStackBit(intptr_t index) { stack_bitmap()->Set(index, true); } |
| 677 stack_bitmap()->Set(index, true); | |
| 678 } | |
| 679 | 635 |
| 680 bool always_calls() const { | 636 bool always_calls() const { return contains_call_ == kCall; } |
| 681 return contains_call_ == kCall; | |
| 682 } | |
| 683 | 637 |
| 684 bool can_call() { | 638 bool can_call() { return contains_call_ != kNoCall; } |
| 685 return contains_call_ != kNoCall; | |
| 686 } | |
| 687 | 639 |
| 688 bool HasCallOnSlowPath() { | 640 bool HasCallOnSlowPath() { return can_call() && !always_calls(); } |
| 689 return can_call() && !always_calls(); | |
| 690 } | |
| 691 | 641 |
| 692 void PrintTo(BufferFormatter* f) const; | 642 void PrintTo(BufferFormatter* f) const; |
| 693 | 643 |
| 694 static LocationSummary* Make(Zone* zone, | 644 static LocationSummary* Make(Zone* zone, |
| 695 intptr_t input_count, | 645 intptr_t input_count, |
| 696 Location out, | 646 Location out, |
| 697 ContainsCall contains_call); | 647 ContainsCall contains_call); |
| 698 | 648 |
| 699 RegisterSet* live_registers() { | 649 RegisterSet* live_registers() { return &live_registers_; } |
| 700 return &live_registers_; | |
| 701 } | |
| 702 | 650 |
| 703 #if defined(DEBUG) | 651 #if defined(DEBUG) |
| 704 // Debug only verification that ensures that writable registers are correctly | 652 // Debug only verification that ensures that writable registers are correctly |
| 705 // preserved on the slow path. | 653 // preserved on the slow path. |
| 706 void DiscoverWritableInputs(); | 654 void DiscoverWritableInputs(); |
| 707 void CheckWritableInputs(); | 655 void CheckWritableInputs(); |
| 708 #endif | 656 #endif |
| 709 | 657 |
| 710 private: | 658 private: |
| 711 const intptr_t num_inputs_; | 659 const intptr_t num_inputs_; |
| 712 Location* input_locations_; | 660 Location* input_locations_; |
| 713 const intptr_t num_temps_; | 661 const intptr_t num_temps_; |
| 714 Location* temp_locations_; | 662 Location* temp_locations_; |
| 715 Location output_location_; | 663 Location output_location_; |
| 716 | 664 |
| 717 BitmapBuilder* stack_bitmap_; | 665 BitmapBuilder* stack_bitmap_; |
| 718 | 666 |
| 719 const ContainsCall contains_call_; | 667 const ContainsCall contains_call_; |
| 720 RegisterSet live_registers_; | 668 RegisterSet live_registers_; |
| 721 | 669 |
| 722 #if defined(DEBUG) | 670 #if defined(DEBUG) |
| 723 intptr_t writable_inputs_; | 671 intptr_t writable_inputs_; |
| 724 #endif | 672 #endif |
| 725 }; | 673 }; |
| 726 | 674 |
| 727 | 675 |
| 728 } // namespace dart | 676 } // namespace dart |
| 729 | 677 |
| 730 #endif // RUNTIME_VM_LOCATIONS_H_ | 678 #endif // RUNTIME_VM_LOCATIONS_H_ |
| OLD | NEW |