Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Enumerations | Functions | Variables
locations.h File Reference
#include "vm/allocation.h"
#include "vm/bitfield.h"
#include "vm/bitmap.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/constants.h"
#include "vm/cpu.h"

Go to the source code of this file.

Classes

struct  dart::RepresentationUtils
 
class  dart::Location
 
class  dart::PairLocation
 
class  dart::SmallSet< T >
 
class  dart::RegisterSet
 
class  dart::LocationSummary
 

Namespaces

namespace  dart
 

Macros

#define FOR_EACH_INTEGER_REPRESENTATION_KIND(M)
 
#define FOR_EACH_UNBOXED_REPRESENTATION_KIND(M)
 
#define FOR_EACH_SIMPLE_REPRESENTATION_KIND(M)
 
#define FOR_EACH_REPRESENTATION_KIND(M)
 
#define DECLARE_REPRESENTATION(name, __, ___, ____)   k##name,
 
#define REP_IN_SET_CLAUSE(name, __, ___, ____)
 
#define REP_SIZEOF_CLAUSE(name, __, ___, type)
 
#define REP_IS_UNSIGNED_CLAUSE(name, __, unsigned, ___)
 

Enumerations

enum  dart::Representation { dart::kNumRepresentations }
 

Functions

intptr_t dart::LocationCount (Representation rep)
 
Location dart::LocationArgumentsDescriptorLocation ()
 
Location dart::LocationExceptionLocation ()
 
Location dart::LocationStackTraceLocation ()
 
Location dart::LocationRegisterOrConstant (Value *value)
 
Location dart::LocationRegisterOrSmiConstant (Value *value, intptr_t min_value, intptr_t max_value)
 
Location dart::LocationWritableRegisterOrConstant (Value *value)
 
Location dart::LocationWritableRegisterOrSmiConstant (Value *value, intptr_t min_value, intptr_t max_value)
 
Location dart::LocationFixedRegisterOrConstant (Value *value, Register reg)
 
Location dart::LocationFixedRegisterOrSmiConstant (Value *value, Register reg)
 
Location dart::LocationAnyOrConstant (Value *value)
 
Location dart::LocationRemapForSlowPath (Location loc, Definition *def, intptr_t *cpu_reg_slots, intptr_t *fpu_reg_slots)
 
compiler::Address dart::LocationToStackSlotAddress (Location loc)
 

Variables

static constexpr intptr_t dart::kMaxLocationCount = 2
 
static constexpr Representation dart::kUnboxedWord
 
static constexpr Representation dart::kUnboxedUword
 
static constexpr Representation dart::kUnboxedIntPtr = kUnboxedWord
 
static constexpr Representation dart::kUnboxedAddress = kUnboxedUword
 

Macro Definition Documentation

◆ DECLARE_REPRESENTATION

#define DECLARE_REPRESENTATION (   name,
  __,
  ___,
  ____ 
)    k##name,

Definition at line 67 of file locations.h.

◆ FOR_EACH_INTEGER_REPRESENTATION_KIND

#define FOR_EACH_INTEGER_REPRESENTATION_KIND (   M)
Value:
M(UnboxedInt8, int8, false, int8_t) \
M(UnboxedUint8, uint8, true, uint8_t) \
M(UnboxedInt16, int16, false, int16_t) \
M(UnboxedUint16, uint16, true, uint16_t) \
M(UnboxedInt32, int32, false, int32_t) \
M(UnboxedUint32, uint32, true, uint32_t) \
M(UnboxedInt64, int64, false, int64_t)
#define M(PROC, DITHER)

Definition at line 31 of file locations.h.

65 {
66#define DECLARE_REPRESENTATION(name, __, ___, ____) k##name,
68#undef DECLARE_REPRESENTATION
70};
71
72static constexpr intptr_t kMaxLocationCount = 2;
73
74inline intptr_t LocationCount(Representation rep) {
75 switch (rep) {
76 case kPairOfTagged:
77 return 2;
78 case kUnboxedInt64:
79 return compiler::target::kWordSize == 8 ? 1 : 2;
80 default:
81 return 1;
82 }
83}
84
85struct RepresentationUtils : AllStatic {
86#define REP_IN_SET_CLAUSE(name, __, ___, ____) \
87 case k##name: \
88 return true;
89
90 // Whether the representation is for a type of unboxed integer.
91 static constexpr bool IsUnboxedInteger(Representation rep) {
92 switch (rep) {
94 default:
95 return false;
96 }
97 }
98
99 // Whether the representation is for a type of unboxed value.
100 static constexpr bool IsUnboxed(Representation rep) {
101 switch (rep) {
103 default:
104 return false;
105 }
106 }
107
108#undef REP_IN_SET_CLAUSE
109
110 // The size of values described by this representation.
111 static constexpr size_t ValueSize(Representation rep) {
112 switch (rep) {
113#define REP_SIZEOF_CLAUSE(name, __, ___, type) \
114 case k##name: \
115 return sizeof(type);
117#undef REP_SIZEOF_CLAUSE
118 default:
119 UNREACHABLE();
120 return compiler::target::kWordSize;
121 }
122 }
123
124 // Whether the values described by this representation are unsigned integers.
125 static bool IsUnsignedInteger(Representation rep) {
126 switch (rep) {
127#define REP_IS_UNSIGNED_CLAUSE(name, __, unsigned, ___) \
128 case k##name: \
129 return unsigned;
131#undef REP_IS_UNSIGNED_CLAUSE
132 default:
133 return false;
134 }
135 }
136
137 // The OperandSize that should be used in the assembler for operations on
138 // values with the given representation.
139 static compiler::OperandSize OperandSize(Representation rep);
140
141 // The minimum integral value that can be represented.
142 // Assumes that [rep] is an unboxed integer.
143 static int64_t MinValue(Representation rep);
144
145 // The maximum integral value that can be represented.
146 // Assumes that [rep] is an unboxed integer.
147 static int64_t MaxValue(Representation rep);
148
149 // Whether the given value is representable in the given representation.
150 // Assumes that [rep] is an unboxed integer.
151 static bool IsRepresentable(Representation rep, int64_t value);
152
153 // Returns the representation of the elements stored in an array with the
154 // given cid.
155 static Representation RepresentationOfArrayElement(classid_t cid);
156
157 // Returns a descriptive name as a C string for the given representation
158 // suitable for use in debugging or error information.
159 static const char* ToCString(Representation rep);
160};
161
162// The representation for word-sized unboxed fields.
163static constexpr Representation kUnboxedWord =
164 compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
165// The representation for unsigned word-sized unboxed fields.
166//
167// Note: 64-bit kUnboxedUword is identical to kUnboxedWord until range analysis
168// can handle unsigned 64-bit ranges. This means that range analysis will give
169// signed results for unboxed uword field values.
170static constexpr Representation kUnboxedUword =
171 compiler::target::kWordSize == 4 ? kUnboxedUint32 : kUnboxedInt64;
172
173// The representation which can be used for native pointers. We use signed 32/64
174// bit representation to be able to do arithmetic on pointers.
176
177// The representation used for pointers being exposed to users as Dart integers,
178// or stored in a way that could be eventually exposed to users. In particular,
179// this ensures that a 32-bit address, when extended to a 64-bit Dart integer,
180// is zero-extended, not sign extended.
182
183// Location objects are used to connect register allocator and code generator.
184// Instruction templates used by code generator have a corresponding
185// LocationSummary object which specifies expected location for every input
186// and output.
187// Each location is encoded as a single word: for non-constant locations
188// low 4 bits denote location kind, rest is kind specific location payload
189// e.g. for REGISTER kind payload is register code (value of the Register
190// enumeration), constant locations contain a tagged (low 2 bits are set to 01)
191// Object handle.
192//
193// Locations must satisfy the following invariant: if two locations' encodings
194// are bitwise unequal then these two locations are guaranteed to be disjoint.
195// Properties like representation belong to the value that is stored in
196// the location not to the location itself.
197class Location : public ValueObject {
198 private:
199 enum {
200 // Number of bits required to encode Kind value.
201 kKindBitsPos = 0,
202 kKindBitsSize = 5,
203
204 kPayloadBitsPos = kKindBitsPos + kKindBitsSize,
205 kPayloadBitsSize = kBitsPerWord - kPayloadBitsPos,
206 };
207
208 static constexpr uword kInvalidLocation = 0;
209 static constexpr uword kLocationTagMask = 0x3;
210
211 public:
212 // Constant payload can overlap with kind field so Kind values
213 // have to be chosen in a way that their last 2 bits are never
214 // the same as kConstantTag or kPairLocationTag.
215 // Note that two locations with different kinds should never point to
216 // the same place. For example kQuadStackSlot location should never intersect
217 // with kDoubleStackSlot location.
218 enum Kind : intptr_t {
219 // This location is invalid. Payload must be zero.
220 kInvalid = 0,
221
222 // Constant value. This location contains a tagged Object handle.
223 kConstantTag = 1,
224
225 // This location contains a tagged pointer to a PairLocation.
226 kPairLocationTag = 2,
227
228 // Unallocated location represents a location that is not fixed and can be
229 // allocated by a register allocator. Each unallocated location has
230 // a policy that specifies what kind of location is suitable. Payload
231 // contains register allocation policy.
232 kUnallocated = 1 << 2,
233
234 // Spill slots allocated by the register allocator. Payload contains
235 // a spill index.
236 kStackSlot = 2 << 2, // Word size slot.
237 kDoubleStackSlot = 3 << 2, // 64bit stack slot.
238 kQuadStackSlot = 4 << 2, // 128bit stack slot.
239
240 // Register location represents a fixed register. Payload contains
241 // register code.
242 kRegister = 5 << 2,
243
244 // FpuRegister location represents a fixed fpu register. Payload contains
245 // its code.
246 kFpuRegister = 6 << 2,
247 };
248
249 Location() : value_(kInvalidLocation) {
250 // Verify that non-tagged location kinds do not interfere with location tags
251 // (kConstantTag and kPairLocationTag).
252 COMPILE_ASSERT((kInvalid & kLocationTagMask) != kConstantTag);
253 COMPILE_ASSERT((kInvalid & kLocationTagMask) != kPairLocationTag);
254
255 COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kConstantTag);
256 COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kPairLocationTag);
257
258 COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kConstantTag);
259 COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kPairLocationTag);
260
261 COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kConstantTag);
262 COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kPairLocationTag);
263
264 COMPILE_ASSERT((kQuadStackSlot & kLocationTagMask) != kConstantTag);
265 COMPILE_ASSERT((kQuadStackSlot & kLocationTagMask) != kPairLocationTag);
266
267 COMPILE_ASSERT((kRegister & kLocationTagMask) != kConstantTag);
268 COMPILE_ASSERT((kRegister & kLocationTagMask) != kPairLocationTag);
269
270 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kConstantTag);
271 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag);
272
273 // Verify tags and tagmask.
274 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag);
275
276 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag);
277
278 ASSERT(IsInvalid());
279 }
280
281 Location(const Location& other) : ValueObject(), value_(other.value_) {}
282
283 Location& operator=(const Location& other) {
284 value_ = other.value_;
285 return *this;
286 }
287
288 bool IsInvalid() const { return value_ == kInvalidLocation; }
289
290 // Constants.
291 bool IsConstant() const { return (value_ & kConstantTag) == kConstantTag; }
292
293 static Location Constant(const ConstantInstr* obj, int pair_index = 0) {
294 ASSERT((pair_index == 0) || (pair_index == 1));
295 Location loc(reinterpret_cast<uword>(obj) |
296 (pair_index != 0 ? static_cast<uword>(kPairLocationTag) : 0) |
297 static_cast<uword>(kConstantTag));
298 ASSERT(obj == loc.constant_instruction());
299 ASSERT(loc.pair_index() == pair_index);
300 return loc;
301 }
302
303 intptr_t pair_index() const {
304 ASSERT(IsConstant());
305 return (value_ & kPairLocationTag) != 0 ? 1 : 0;
306 }
307
308 ConstantInstr* constant_instruction() const {
309 ASSERT(IsConstant());
310 return reinterpret_cast<ConstantInstr*>(value_ & ~kLocationTagMask);
311 }
312
313 const Object& constant() const;
314
315 bool IsPairLocation() const {
316 return (value_ & kLocationTagMask) == kPairLocationTag;
317 }
318
319 static Location Pair(Location first, Location second);
320
321 PairLocation* AsPairLocation() const;
322
323 // For pair locations, returns the ith component (for i in {0, 1}).
324 Location Component(intptr_t i) const;
325
326 // Unallocated locations.
327 enum Policy {
328 kAny,
329 kPrefersRegister,
330 kRequiresRegister,
331 kRequiresFpuRegister,
332 kWritableRegister,
333 kSameAsFirstInput,
334 // Forces the location to be spilled to the stack.
335 // Currently only used for `Handle` arguments in `FfiCall` instructions.
336 // Only available in optimized mode.
337 kRequiresStack,
338 };
339
340 bool IsUnallocated() const { return kind() == kUnallocated; }
341
342 bool IsRegisterBeneficial() {
343 return !Equals(Any()) && !Equals(RequiresStack());
344 }
345
346 static Location UnallocatedLocation(Policy policy) {
347 return Location(kUnallocated, PolicyField::encode(policy));
348 }
349
350 // Any free register is suitable to replace this unallocated location.
351 static Location Any() { return UnallocatedLocation(kAny); }
352
353 static Location RequiresStack() {
354 return UnallocatedLocation(kRequiresStack);
355 }
356
357 static Location PrefersRegister() {
358 return UnallocatedLocation(kPrefersRegister);
359 }
360
361 // Blocks a CPU register for the entirety of the IL instruction.
362 //
363 // The register value _must_ be preserved by the machine code.
364 static Location RequiresRegister() {
365 return UnallocatedLocation(kRequiresRegister);
366 }
367
368 static Location RequiresFpuRegister() {
369 return UnallocatedLocation(kRequiresFpuRegister);
370 }
371
372 // Blocks a CPU register for the entirety of the IL instruction.
373 //
374 // The register value does not have to be preserved by the machine code.
375 static Location WritableRegister() {
376 return UnallocatedLocation(kWritableRegister);
377 }
378
379 // The location of the first input to the instruction will be
380 // used to replace this unallocated location.
381 static Location SameAsFirstInput() {
382 return UnallocatedLocation(kSameAsFirstInput);
383 }
384
385 // Empty location. Used if there the location should be ignored.
386 static Location NoLocation() { return Location(); }
387
388 Policy policy() const {
389 ASSERT(IsUnallocated());
390 return PolicyField::decode(payload());
391 }
392
393 // Blocks `reg` for the entirety of the IL instruction.
394 //
395 // The register value does not have to be preserved by the machine code.
396 // TODO(https://dartbug.com/51409): Rename to WritableRegisterLocation.
397 static Location RegisterLocation(Register reg) {
398 return Location(kRegister, reg);
399 }
400
401 bool IsRegister() const { return kind() == kRegister; }
402
403 Register reg() const {
404 ASSERT(IsRegister());
405 return static_cast<Register>(payload());
406 }
407
408 // FpuRegister locations.
409 static Location FpuRegisterLocation(FpuRegister reg) {
410 return Location(kFpuRegister, reg);
411 }
412
413 bool IsFpuRegister() const { return kind() == kFpuRegister; }
414
415 FpuRegister fpu_reg() const {
416 ASSERT(IsFpuRegister());
417 return static_cast<FpuRegister>(payload());
418 }
419
420 static bool IsMachineRegisterKind(Kind kind) {
421 return (kind == kRegister) || (kind == kFpuRegister);
422 }
423
424 static Location MachineRegisterLocation(Kind kind, intptr_t reg) {
425 if (kind == kRegister) {
426 return RegisterLocation(static_cast<Register>(reg));
427 } else {
428 ASSERT(kind == kFpuRegister);
429 return FpuRegisterLocation(static_cast<FpuRegister>(reg));
430 }
431 }
432
433 bool IsMachineRegister() const { return IsMachineRegisterKind(kind()); }
434
435 intptr_t register_code() const {
436 ASSERT(IsMachineRegister());
437 return static_cast<intptr_t>(payload());
438 }
439
440 static uword EncodeStackIndex(intptr_t stack_index) {
441 ASSERT((-kStackIndexBias <= stack_index) &&
442 (stack_index < kStackIndexBias));
443 return static_cast<uword>(kStackIndexBias + stack_index);
444 }
445
446 static Location StackSlot(intptr_t stack_index, Register base) {
447 uword payload = StackSlotBaseField::encode(base) |
448 StackIndexField::encode(EncodeStackIndex(stack_index));
449 Location loc(kStackSlot, payload);
450 // Ensure that sign is preserved.
451 ASSERT(loc.stack_index() == stack_index);
452 return loc;
453 }
454
455 bool IsStackSlot() const { return kind() == kStackSlot; }
456
457 static Location DoubleStackSlot(intptr_t stack_index, Register base) {
458 uword payload = StackSlotBaseField::encode(base) |
459 StackIndexField::encode(EncodeStackIndex(stack_index));
460 Location loc(kDoubleStackSlot, payload);
461 // Ensure that sign is preserved.
462 ASSERT(loc.stack_index() == stack_index);
463 return loc;
464 }
465
466 bool IsDoubleStackSlot() const { return kind() == kDoubleStackSlot; }
467
468 static Location QuadStackSlot(intptr_t stack_index, Register base) {
469 uword payload = StackSlotBaseField::encode(base) |
470 StackIndexField::encode(EncodeStackIndex(stack_index));
471 Location loc(kQuadStackSlot, payload);
472 // Ensure that sign is preserved.
473 ASSERT(loc.stack_index() == stack_index);
474 return loc;
475 }
476
477 bool IsQuadStackSlot() const { return kind() == kQuadStackSlot; }
478
479 Register base_reg() const {
480 ASSERT(HasStackIndex());
481 return StackSlotBaseField::decode(payload());
482 }
483
484 intptr_t stack_index() const {
485 ASSERT(HasStackIndex());
486 // Decode stack index manually to preserve sign.
487 return StackIndexField::decode(payload()) - kStackIndexBias;
488 }
489
490 bool HasStackIndex() const {
491 return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot();
492 }
493
494 // Returns the offset from the frame pointer for stack slot locations.
495 intptr_t ToStackSlotOffset() const;
496
497 // If the given location is FP relative stack location this returns
498 // corresponding SP relative location assuming that FP-SP is equal to
499 // |fp_to_sp_delta|.
500 Location ToSpRelative(intptr_t fp_to_sp_delta) const;
501
502 // If the given location is FP relative stack location this returns
503 // corresponding SP relative location assuming that SP is equal to SP
504 // at the entry (i.e. no additional frame was setup on the stack).
505 Location ToEntrySpRelative() const;
506
507 // If the given location is FP relative stack location this returns
508 // corresponding SP relative location assuming that SP is equal to SP
509 // of caller before the call.
510 Location ToCallerSpRelative() const;
511
512 const char* Name() const;
513 void PrintTo(BaseTextBuffer* f) const;
514 void Print() const;
515 const char* ToCString() const;
516
517 // Compare two locations.
518 bool Equals(Location other) const { return value_ == other.value_; }
519
520 // If current location is constant might return something that
521 // is not equal to any Kind.
522 Kind kind() const { return KindField::decode(value_); }
523
524 Location Copy() const;
525
526 void Write(FlowGraphSerializer* s) const;
527 static Location Read(FlowGraphDeserializer* d);
528
529 private:
530 explicit Location(uword value) : value_(value) {}
531
532 void set_stack_index(intptr_t index) {
533 ASSERT(HasStackIndex());
534 value_ = PayloadField::update(
535 StackIndexField::update(EncodeStackIndex(index), payload()), value_);
536 }
537
538 void set_base_reg(Register reg) {
539 ASSERT(HasStackIndex());
540 value_ = PayloadField::update(StackSlotBaseField::update(reg, payload()),
541 value_);
542 }
543
544 Location(Kind kind, uword payload)
545 : value_(KindField::encode(kind) | PayloadField::encode(payload)) {}
546
547 uword payload() const { return PayloadField::decode(value_); }
548
549 class KindField : public BitField<uword, Kind, kKindBitsPos, kKindBitsSize> {
550 };
551 class PayloadField
552 : public BitField<uword, uword, kPayloadBitsPos, kPayloadBitsSize> {};
553
554 // Layout for kUnallocated locations payload.
555 typedef BitField<uword, Policy, 0, 3> PolicyField;
556
557// Layout for stack slots.
558#if defined(ARCH_IS_64_BIT)
559 static constexpr intptr_t kBitsForBaseReg = 6;
560#else
561 static constexpr intptr_t kBitsForBaseReg = 5;
562#endif
563 static constexpr intptr_t kBitsForStackIndex =
564 kPayloadBitsSize - kBitsForBaseReg;
565 class StackSlotBaseField
566 : public BitField<uword, Register, 0, kBitsForBaseReg> {};
567 class StackIndexField
568 : public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> {
569 };
570 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters);
571
572 static constexpr intptr_t kStackIndexBias = static_cast<intptr_t>(1)
573 << (kBitsForStackIndex - 1);
574
575 // Location either contains kind and payload fields or a tagged handle for
576 // a constant locations. Values of enumeration Kind are selected in such a
577 // way that none of them can be interpreted as a kConstant tag.
578 uword value_;
579};
580
584// Constants.
587 Value* value,
588 intptr_t min_value = compiler::target::kSmiMin,
589 intptr_t max_value = compiler::target::kSmiMax);
592 Value* value,
593 intptr_t min_value = compiler::target::kSmiMin,
594 intptr_t max_value = compiler::target::kSmiMax);
598
600 Definition* def,
601 intptr_t* cpu_reg_slots,
602 intptr_t* fpu_reg_slots);
603
604// Return a memory operand for stack slot locations.
605compiler::Address LocationToStackSlotAddress(Location loc);
606
607class PairLocation : public ZoneAllocated {
608 public:
609 PairLocation() {
610 for (intptr_t i = 0; i < kPairLength; i++) {
611 ASSERT(locations_[i].IsInvalid());
612 }
613 }
614
615 intptr_t length() const { return kPairLength; }
616
617 Location At(intptr_t i) const {
618 ASSERT(i >= 0);
619 ASSERT(i < kPairLength);
620 return locations_[i];
621 }
622
623 void SetAt(intptr_t i, Location loc) {
624 ASSERT(i >= 0);
625 ASSERT(i < kPairLength);
626 locations_[i] = loc;
627 }
628
629 Location* SlotAt(intptr_t i) {
630 ASSERT(i >= 0);
631 ASSERT(i < kPairLength);
632 return &locations_[i];
633 }
634
635 private:
636 static constexpr intptr_t kPairLength = 2;
637 Location locations_[kPairLength];
638};
639
640template <typename T>
641class SmallSet {
642 public:
643 SmallSet() : data_(0) {}
644
645 explicit SmallSet(uintptr_t data) : data_(data) {}
646
647 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; }
648
649 void Add(T value) { data_ |= ToMask(value); }
650
651 void Remove(T value) { data_ &= ~ToMask(value); }
652
653 bool IsEmpty() const { return data_ == 0; }
654
655 void Clear() { data_ = 0; }
656
657 uintptr_t data() const { return data_; }
658
659 private:
660 static uintptr_t ToMask(T value) {
661 ASSERT(static_cast<uintptr_t>(value) < (kWordSize * kBitsPerByte));
662 return static_cast<uintptr_t>(1) << static_cast<uintptr_t>(value);
663 }
664
665 uintptr_t data_;
666};
667
668class RegisterSet : public ValueObject {
669 public:
670 RegisterSet()
671 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() {
672 ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte));
673 ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte));
674 }
675
676 explicit RegisterSet(uintptr_t cpu_register_mask, uintptr_t fpu_register_mask)
677 : RegisterSet() {
678 AddTaggedRegisters(cpu_register_mask, fpu_register_mask);
679 }
680
681 void AddAllNonReservedRegisters(bool include_fpu_registers) {
682 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
683 if ((kReservedCpuRegisters & (1 << i)) != 0u) continue;
684 Add(Location::RegisterLocation(static_cast<Register>(i)));
685 }
686
687 if (include_fpu_registers) {
688 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
689 Add(Location::FpuRegisterLocation(static_cast<FpuRegister>(i)));
690 }
691 }
692 }
693
694 // Adds all registers which don't have a special purpose (e.g. FP, SP, PC,
695 // CSP, etc.).
696 void AddAllGeneralRegisters() {
697 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
698 Register reg = static_cast<Register>(i);
699 if (reg == FPREG || reg == SPREG) continue;
700#if defined(TARGET_ARCH_ARM)
701 if (reg == PC) continue;
702#elif defined(TARGET_ARCH_ARM64)
703 if (reg == R31) continue;
704#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
705 if (reg == ZR || reg == TP || reg == GP) continue;
706#endif
707 Add(Location::RegisterLocation(reg));
708 }
709
710 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
711 Add(Location::FpuRegisterLocation(static_cast<FpuRegister>(i)));
712 }
713 }
714
715 void AddAllArgumentRegisters() {
716 // All (native) arguments are passed on the stack in IA32.
717#if !defined(TARGET_ARCH_IA32)
718 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
719 const Register reg = static_cast<Register>(i);
720 if (IsArgumentRegister(reg)) {
721 Add(Location::RegisterLocation(reg));
722 }
723 }
724 for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) {
725 const FpuRegister reg = static_cast<FpuRegister>(i);
726 if (IsFpuArgumentRegister(reg)) {
727 Add(Location::FpuRegisterLocation(reg));
728 }
729 }
730#endif
731 }
732
733 void AddTaggedRegisters(uintptr_t cpu_register_mask,
734 uintptr_t fpu_register_mask) {
735 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
736 if (Utils::TestBit(cpu_register_mask, i)) {
737 const Register reg = static_cast<Register>(i);
738 Add(Location::RegisterLocation(reg));
739 }
740 }
741 for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) {
742 if (Utils::TestBit(fpu_register_mask, i)) {
743 const FpuRegister reg = static_cast<FpuRegister>(i);
744 Add(Location::FpuRegisterLocation(reg));
745 }
746 }
747 }
748
749 void AddRegister(Register reg, Representation rep = kTagged) {
750 Add(Location::RegisterLocation(reg), rep);
751 }
752
753 void Add(Location loc, Representation rep = kTagged) {
754 if (loc.IsRegister()) {
755 cpu_registers_.Add(loc.reg());
756 if (rep != kTagged) {
757 // CPU register contains an untagged value.
758 MarkUntagged(loc);
759 }
760 } else if (loc.IsFpuRegister()) {
761 fpu_registers_.Add(loc.fpu_reg());
762 }
763 }
764
765 void Remove(Location loc) {
766 if (loc.IsRegister()) {
767 cpu_registers_.Remove(loc.reg());
768 } else if (loc.IsFpuRegister()) {
769 fpu_registers_.Remove(loc.fpu_reg());
770 }
771 }
772
773 bool Contains(Location loc) {
774 if (loc.IsRegister()) {
775 return ContainsRegister(loc.reg());
776 } else if (loc.IsFpuRegister()) {
777 return ContainsFpuRegister(loc.fpu_reg());
778 } else {
779 UNREACHABLE();
780 return false;
781 }
782 }
783
784 void DebugPrint();
785
786 void MarkUntagged(Location loc) {
787 ASSERT(loc.IsRegister());
788 untagged_cpu_registers_.Add(loc.reg());
789 }
790
791 bool HasUntaggedValues() const {
792 return !untagged_cpu_registers_.IsEmpty() || !fpu_registers_.IsEmpty();
793 }
794
795 bool IsTagged(Register reg) const {
796 return !untagged_cpu_registers_.Contains(reg);
797 }
798
799 bool ContainsRegister(Register reg) const {
800 return cpu_registers_.Contains(reg);
801 }
802
803 bool ContainsFpuRegister(FpuRegister fpu_reg) const {
804 return fpu_registers_.Contains(fpu_reg);
805 }
806
807 intptr_t CpuRegisterCount() const { return RegisterCount(cpu_registers()); }
808 intptr_t FpuRegisterCount() const { return RegisterCount(fpu_registers()); }
809
810 bool IsEmpty() const {
811 return CpuRegisterCount() == 0 && FpuRegisterCount() == 0;
812 }
813
814 static intptr_t RegisterCount(intptr_t registers);
815 static bool Contains(uintptr_t register_set, intptr_t reg) {
816 return (register_set & (static_cast<uintptr_t>(1) << reg)) != 0;
817 }
818
819 uintptr_t cpu_registers() const { return cpu_registers_.data(); }
820 uintptr_t fpu_registers() const { return fpu_registers_.data(); }
821
822 void Clear() {
823 cpu_registers_.Clear();
824 fpu_registers_.Clear();
825 untagged_cpu_registers_.Clear();
826 }
827
828 void Write(FlowGraphSerializer* s) const;
829 explicit RegisterSet(FlowGraphDeserializer* d);
830
831 private:
832 SmallSet<Register> cpu_registers_;
833 SmallSet<Register> untagged_cpu_registers_;
834 SmallSet<FpuRegister> fpu_registers_;
835
836 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
837};
838
839// Specification of locations for inputs and output.
840class LocationSummary : public ZoneAllocated {
841 public:
842 enum ContainsCall {
843 // Used registers must be reserved as tmp.
844 kNoCall,
845 // Registers have been saved and can be used without reservation.
846 kCall,
847 // Registers will be saved by the callee.
848 kCallCalleeSafe,
849 // Used registers must be reserved as tmp.
850 kCallOnSlowPath,
851 // Registers used to invoke shared stub must be reserved as tmp.
852 kCallOnSharedSlowPath,
853 // Location is a native leaf call so any register not in the native ABI
854 // callee-save (or input/output/tmp) set might get clobbered.
855 kNativeLeafCall
856 };
857
858 LocationSummary(Zone* zone,
859 intptr_t input_count,
860 intptr_t temp_count,
861 LocationSummary::ContainsCall contains_call);
862
863 intptr_t input_count() const { return num_inputs_; }
864
865 Location in(intptr_t index) const {
866 ASSERT(index >= 0);
867 ASSERT(index < num_inputs_);
868 return input_locations_[index];
869 }
870
871 Location* in_slot(intptr_t index) {
872 ASSERT(index >= 0);
873 ASSERT(index < num_inputs_);
874 return &input_locations_[index];
875 }
876
877 void set_in(intptr_t index, Location loc);
878
879 intptr_t temp_count() const { return num_temps_; }
880
881 Location temp(intptr_t index) const {
882 ASSERT(index >= 0);
883 ASSERT(index < num_temps_);
884 return temp_locations_[index];
885 }
886
887 Location* temp_slot(intptr_t index) {
888 ASSERT(index >= 0);
889 ASSERT(index < num_temps_);
890 return &temp_locations_[index];
891 }
892
893 void set_temp(intptr_t index, Location loc) {
894 ASSERT(index >= 0);
895 ASSERT(index < num_temps_);
896 ASSERT(!always_calls() || loc.IsMachineRegister());
897 temp_locations_[index] = loc;
898 }
899
900 intptr_t output_count() const { return 1; }
901
902 Location out(intptr_t index) const {
903 ASSERT(index == 0);
904 return output_location_;
905 }
906
907 Location* out_slot(intptr_t index) {
908 ASSERT(index == 0);
909 return &output_location_;
910 }
911
912 void set_out(intptr_t index, Location loc);
913
914 const BitmapBuilder& stack_bitmap() { return EnsureStackBitmap(); }
915 void SetStackBit(intptr_t index) { EnsureStackBitmap().Set(index, true); }
916
917 bool always_calls() const {
918 return contains_call_ == kCall || contains_call_ == kCallCalleeSafe;
919 }
920
921 bool callee_safe_call() const { return contains_call_ == kCallCalleeSafe; }
922
923 bool can_call() { return contains_call_ != kNoCall; }
924
925 bool HasCallOnSlowPath() { return can_call() && !always_calls(); }
926
927 bool call_on_shared_slow_path() const {
928 return contains_call_ == kCallOnSharedSlowPath;
929 }
930
931 bool native_leaf_call() const { return contains_call_ == kNativeLeafCall; }
932
933 void PrintTo(BaseTextBuffer* f) const;
934
935 static LocationSummary* Make(Zone* zone,
936 intptr_t input_count,
937 Location out,
938 ContainsCall contains_call);
939
940 RegisterSet* live_registers() { return &live_registers_; }
941
942#if defined(DEBUG)
943 // Debug only verification that ensures that writable registers are correctly
944 // preserved on the slow path.
945 void DiscoverWritableInputs();
946 void CheckWritableInputs();
947#endif
948
949 void Write(FlowGraphSerializer* s) const;
950 explicit LocationSummary(FlowGraphDeserializer* d);
951
952 private:
953 BitmapBuilder& EnsureStackBitmap() {
954 if (stack_bitmap_ == nullptr) {
955 stack_bitmap_ = new BitmapBuilder();
956 }
957 return *stack_bitmap_;
958 }
959
960 const intptr_t num_inputs_;
961 Location* input_locations_;
962 const intptr_t num_temps_;
963 Location* temp_locations_;
964 Location output_location_;
965
966 BitmapBuilder* stack_bitmap_;
967
968 const ContainsCall contains_call_;
969 RegisterSet live_registers_;
970
971#if defined(DEBUG)
972 intptr_t writable_inputs_;
973#endif
974};
975
976} // namespace dart
977
978#endif // RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_H_
@ kInvalid
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static void encode(uint8_t output[16], const uint32_t input[4])
Definition SkMD5.cpp:240
#define UNREACHABLE()
Definition assert.h:248
#define COMPILE_ASSERT(expr)
Definition assert.h:339
bool Equals(const SkPath &a, const SkPath &b)
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
struct MyStruct s
uint8_t value
void PrintTo(FlValue *v, std::ostream *os)
Definition fl_test.cc:78
size_t length
#define REP_SIZEOF_CLAUSE(name, __, ___, type)
#define FOR_EACH_REPRESENTATION_KIND(M)
Definition locations.h:61
#define FOR_EACH_INTEGER_REPRESENTATION_KIND(M)
Definition locations.h:31
#define REP_IS_UNSIGNED_CLAUSE(name, __, unsigned, ___)
#define FOR_EACH_UNBOXED_REPRESENTATION_KIND(M)
Definition locations.h:42
#define FOR_EACH_SIMPLE_REPRESENTATION_KIND(M)
Definition locations.h:53
#define REP_IN_SET_CLAUSE(name, __, ___, ____)
Definition locations.h:87
#define DECLARE_REPRESENTATION(name, __, ___, ____)
Definition locations.h:67
ImplicitString Name
Definition DMSrcSink.h:38
SK_API bool Read(SkStreamSeekable *src, SkDocumentPage *dstArray, int dstArrayCount, const SkDeserialProcs *=nullptr)
bool Contains(const Container &container, const Value &value)
Location LocationAnyOrConstant(Value *value)
Definition locations.cc:357
Location LocationRegisterOrConstant(Value *value)
Definition locations.cc:289
constexpr intptr_t kBitsPerWord
Definition globals.h:514
static constexpr Representation kUnboxedUword
Definition locations.h:171
static constexpr intptr_t kMaxLocationCount
Definition locations.h:73
Location LocationExceptionLocation()
Definition locations.cc:484
Representation
Definition locations.h:66
@ kNumRepresentations
Definition locations.h:70
intptr_t LocationCount(Representation rep)
Definition locations.h:75
uintptr_t uword
Definition globals.h:501
@ kNumberOfCpuRegisters
Location LocationFixedRegisterOrConstant(Value *value, Register reg)
Definition locations.cc:339
const int kNumberOfFpuRegisters
Location LocationWritableRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
Definition locations.cc:322
Location LocationArgumentsDescriptorLocation()
Definition locations.cc:480
Location LocationRemapForSlowPath(Location loc, Definition *def, intptr_t *cpu_reg_slots, intptr_t *fpu_reg_slots)
Definition locations.cc:492
static constexpr Representation kUnboxedAddress
Definition locations.h:182
compiler::Address LocationToStackSlotAddress(Location loc)
Definition locations.cc:365
Location LocationStackTraceLocation()
Definition locations.cc:488
Location LocationWritableRegisterOrConstant(Value *value)
Definition locations.cc:314
static constexpr Representation kUnboxedIntPtr
Definition locations.h:176
QRegister FpuRegister
@ kAny
Definition object.h:2229
static constexpr Representation kUnboxedWord
Definition locations.h:164
Location LocationFixedRegisterOrSmiConstant(Value *value, Register reg)
Definition locations.cc:348
Location LocationRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
Definition locations.cc:297
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network policy
Definition switches.h:248
std::enable_if_t< sknonstd::is_bitmask_enum< E >::value, bool > constexpr Any(E e)
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T

◆ FOR_EACH_REPRESENTATION_KIND

#define FOR_EACH_REPRESENTATION_KIND (   M)
Value:
M(NoRepresentation, none, _, _) \
FOR_EACH_SIMPLE_REPRESENTATION_KIND(M) \
M(PairOfTagged, tagged_pair, _, _)

Definition at line 61 of file locations.h.

◆ FOR_EACH_SIMPLE_REPRESENTATION_KIND

#define FOR_EACH_SIMPLE_REPRESENTATION_KIND (   M)
Value:
M(Tagged, tagged, _, compiler::target::word) \
M(Untagged, untagged, _, compiler::target::word) \
FOR_EACH_UNBOXED_REPRESENTATION_KIND(M)

Definition at line 53 of file locations.h.

◆ FOR_EACH_UNBOXED_REPRESENTATION_KIND

#define FOR_EACH_UNBOXED_REPRESENTATION_KIND (   M)
Value:
M(UnboxedDouble, double, _, double_t) \
M(UnboxedFloat, float, _, float_t) \
FOR_EACH_INTEGER_REPRESENTATION_KIND(M) \
M(UnboxedFloat32x4, float32x4, _, simd128_value_t) \
M(UnboxedInt32x4, int32x4, _, simd128_value_t) \
M(UnboxedFloat64x2, float64x2, _, simd128_value_t)

Definition at line 42 of file locations.h.

◆ REP_IN_SET_CLAUSE

#define REP_IN_SET_CLAUSE (   name,
  __,
  ___,
  ____ 
)
Value:
case k##name: \
return true;
const char * name
Definition fuchsia.cc:50

Definition at line 87 of file locations.h.

88 : \
89 return true;

◆ REP_IS_UNSIGNED_CLAUSE

#define REP_IS_UNSIGNED_CLAUSE (   name,
  __,
  unsigned,
  ___ 
)
Value:
case k##name: \
return unsigned;

◆ REP_SIZEOF_CLAUSE

#define REP_SIZEOF_CLAUSE (   name,
  __,
  ___,
  type 
)
Value:
case k##name: \
return sizeof(type);