Index: runtime/vm/locations.h |
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h |
index 43182cd159ca42603bd9731fdc4eba70a61823cc..503633b04573edef96def586a841deda5732438c 100644 |
--- a/runtime/vm/locations.h |
+++ b/runtime/vm/locations.h |
@@ -13,6 +13,7 @@ namespace dart { |
class BufferFormatter; |
class Value; |
+class PairLocation; |
enum Representation { |
@@ -24,6 +25,8 @@ enum Representation { |
kUnboxedFloat32x4, |
kUnboxedInt32x4, |
kUnboxedFloat64x2, |
+ kPairOfTagged, |
+ kPairOfUnboxedDouble, |
kNumRepresentations |
}; |
@@ -33,7 +36,7 @@ enum Representation { |
// LocationSummary object which specifies expected location for every input |
// and output. |
// Each location is encoded as a single word: for non-constant locations |
-// low 3 bits denote location kind, rest is kind specific location payload |
+// low 4 bits denote location kind, rest is kind specific location payload |
// e.g. for REGISTER kind payload is register code (value of the Register |
// enumeration), constant locations contain a tagged (low 2 bits are set to 01) |
// Object handle. |
@@ -51,15 +54,12 @@ class Location : public ValueObject { |
}; |
static const uword kInvalidLocation = 0; |
- static const uword kConstantMask = 0x3; |
- |
- static const intptr_t kMachineRegisterMask = 0x6; |
- static const intptr_t kMachineRegister = 0x6; |
+ static const uword kLocationTagMask = 0x3; |
public: |
// Constant payload can overlap with kind field so Kind values |
// have to be chosen in a way that their last 2 bits are never |
- // the same as kConstant. |
+ // the same as kConstantTag or kPairLocationTag. |
// Note that two locations with different kinds should never point to |
// the same place. For example kQuadStackSlot location should never intersect |
// with kDoubleStackSlot location. |
@@ -68,30 +68,77 @@ class Location : public ValueObject { |
kInvalid = 0, |
// Constant value. This location contains a tagged Object handle. |
- kConstant = 1, |
+ kConstantTag = 1, |
+ |
+ // This location contains a tagged pointer to a PairLocation. |
+ kPairLocationTag = 2, |
// Unallocated location represents a location that is not fixed and can be |
// allocated by a register allocator. Each unallocated location has |
// a policy that specifies what kind of location is suitable. Payload |
// contains register allocation policy. |
- kUnallocated = 2, |
+ kUnallocated = 3, |
// Spill slots allocated by the register allocator. Payload contains |
// a spill index. |
- kStackSlot = 3, // Word size slot. |
- kDoubleStackSlot = 4, // 64bit stack slot. |
- kQuadStackSlot = 8, // 128bit stack slot. |
+ kStackSlot = 4, // Word size slot. |
+ kDoubleStackSlot = 7, // 64bit stack slot. |
+ kQuadStackSlot = 11, // 128bit stack slot. |
// Register location represents a fixed register. Payload contains |
// register code. |
- kRegister = 6, |
+ kRegister = 8, |
// FpuRegister location represents a fixed fpu register. Payload contains |
// its code. |
- kFpuRegister = 7, |
+ kFpuRegister = 12, |
}; |
Location() : value_(kInvalidLocation) { |
+ // Verify that non-tagged location kinds do not interfere with location tags |
+ // (kConstantTag and kPairLocationTag). |
+ COMPILE_ASSERT(((kInvalid & kLocationTagMask) != kConstantTag), |
+ invalid_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kInvalid & kLocationTagMask) != kPairLocationTag), |
+ invalid_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kUnallocated & kLocationTagMask) != kConstantTag), |
+ unallocated_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kUnallocated & kLocationTagMask) != kPairLocationTag), |
+ unallocated_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kStackSlot & kLocationTagMask) != kConstantTag), |
+ stackslot_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kStackSlot & kLocationTagMask) != kPairLocationTag), |
+ stackslot_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kDoubleStackSlot & kLocationTagMask) != kConstantTag), |
+ doublestackslot_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kDoubleStackSlot & kLocationTagMask) != kPairLocationTag), |
+ doublestackslot_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kQuadStackSlot & kLocationTagMask) != kConstantTag), |
+ quadstackslot_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kQuadStackSlot & kLocationTagMask) != kPairLocationTag), |
+ quadstackslot_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kRegister & kLocationTagMask) != kConstantTag), |
+ register_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kRegister & kLocationTagMask) != kPairLocationTag), |
+ register_conflicts_with_pair_tag); |
+ |
+ COMPILE_ASSERT(((kFpuRegister & kLocationTagMask) != kConstantTag), |
+ fpuregister_conflicts_with_constant_tag); |
+ COMPILE_ASSERT(((kFpuRegister & kLocationTagMask) != kPairLocationTag), |
+ fpuregister_conflicts_with_pair_tag); |
+ |
+ // Verify tags and tagmask. |
+ COMPILE_ASSERT(((kConstantTag & kLocationTagMask) == kConstantTag), |
+ bad_constant_tag); |
+ |
+ COMPILE_ASSERT(((kPairLocationTag & kLocationTagMask) == kPairLocationTag), |
+ bad_pair_tag); |
+ |
ASSERT(IsInvalid()); |
} |
@@ -108,21 +155,28 @@ class Location : public ValueObject { |
// Constants. |
bool IsConstant() const { |
- ASSERT((kConstant & kConstantMask) == kConstant); |
- return (value_ & kConstantMask) == kConstant; |
+ return (value_ & kLocationTagMask) == kConstantTag; |
} |
static Location Constant(const Object& obj) { |
- Location loc(reinterpret_cast<uword>(&obj) | kConstant); |
+ Location loc(reinterpret_cast<uword>(&obj) | kConstantTag); |
ASSERT(&obj == &loc.constant()); |
return loc; |
} |
const Object& constant() const { |
ASSERT(IsConstant()); |
- return *reinterpret_cast<const Object*>(value_ & ~kConstantMask); |
+ return *reinterpret_cast<const Object*>(value_ & ~kLocationTagMask); |
} |
+ bool IsPairLocation() const { |
+ return (value_ & kLocationTagMask) == kPairLocationTag; |
+ } |
+ |
+ static Location Pair(Location first, Location second); |
+ |
+ PairLocation* AsPairLocation() const; |
+ |
// Unallocated locations. |
enum Policy { |
kAny, |
@@ -211,7 +265,7 @@ class Location : public ValueObject { |
} |
static bool IsMachineRegisterKind(Kind kind) { |
- return (kind & kMachineRegisterMask) == kMachineRegister; |
+ return (kind == kRegister) || (kind == kFpuRegister); |
} |
static Location MachineRegisterLocation(Kind kind, |
@@ -337,6 +391,40 @@ class Location : public ValueObject { |
}; |
+class PairLocation : public ZoneAllocated { |
+ public: |
+ PairLocation() { |
+ for (intptr_t i = 0; i < kPairLength; i++) { |
+ ASSERT(locations_[i].IsInvalid()); |
+ } |
+ } |
+ |
+ intptr_t length() const { return kPairLength; } |
+ |
+ Location At(intptr_t i) const { |
+ ASSERT(i >= 0); |
+ ASSERT(i < kPairLength); |
+ return locations_[i]; |
+ } |
+ |
+ void SetAt(intptr_t i, Location loc) { |
+ ASSERT(i >= 0); |
+ ASSERT(i < kPairLength); |
+ locations_[i] = loc; |
+ } |
+ |
+ Location* SlotAt(intptr_t i) { |
+ ASSERT(i >= 0); |
+ ASSERT(i < kPairLength); |
+ return &locations_[i]; |
+ } |
+ |
+ private: |
+ static const intptr_t kPairLength = 2; |
+ Location locations_[kPairLength]; |
+}; |
+ |
+ |
class RegisterSet : public ValueObject { |
public: |
RegisterSet() : cpu_registers_(0), fpu_registers_(0) { |
@@ -456,7 +544,9 @@ class LocationSummary : public ZoneAllocated { |
} |
void set_out(intptr_t index, Location loc) { |
- ASSERT(!always_calls() || (loc.IsMachineRegister() || loc.IsInvalid())); |
+ ASSERT(!always_calls() || |
+ (loc.IsMachineRegister() || loc.IsInvalid() || |
+ loc.IsPairLocation())); |
output_locations_[index] = loc; |
} |