Runtime support for the new stack maps for the opt compiler.
Now most of the methods supported by the compiler can be optimized,
instead of using the baseline.
Change-Id: I80ab36a34913fa4e7dd576c7bf55af63594dc1fa
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 83035b5..33b1f1f 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -47,7 +47,7 @@
};
/**
- * A live range contains the start and end of a range where an instruction
+ * A live range contains the start and end of a range where an instruction or a temporary
* is live.
*/
class LiveRange : public ArenaObject {
@@ -76,7 +76,7 @@
private:
size_t start_;
- size_t end_;
+ const size_t end_;
LiveRange* next_;
friend class LiveInterval;
@@ -133,7 +133,12 @@
*/
class LiveInterval : public ArenaObject {
public:
- LiveInterval(ArenaAllocator* allocator, Primitive::Type type, HInstruction* defined_by = nullptr)
+ LiveInterval(ArenaAllocator* allocator,
+ Primitive::Type type,
+ HInstruction* defined_by = nullptr,
+ bool is_fixed = false,
+ int reg = kNoRegister,
+ bool is_temp = false)
: allocator_(allocator),
first_range_(nullptr),
last_range_(nullptr),
@@ -141,16 +146,20 @@
type_(type),
next_sibling_(nullptr),
parent_(this),
- register_(kNoRegister),
+ register_(reg),
spill_slot_(kNoSpillSlot),
- is_fixed_(false),
+ is_fixed_(is_fixed),
+ is_temp_(is_temp),
defined_by_(defined_by) {}
static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, Primitive::Type type) {
- LiveInterval* interval = new (allocator) LiveInterval(allocator, type);
- interval->SetRegister(reg);
- interval->is_fixed_ = true;
- return interval;
+ return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false);
+ }
+
+ static LiveInterval* MakeTempInterval(ArenaAllocator* allocator,
+ HInstruction* defined_by,
+ Primitive::Type type) {
+ return new (allocator) LiveInterval(allocator, type, defined_by, false, kNoRegister, true);
}
bool IsFixed() const { return is_fixed_; }
@@ -192,8 +201,10 @@
} else if (first_range_->GetStart() == end) {
// There is a use in the following block.
first_range_->start_ = start;
+ } else if (first_range_->GetStart() == start && first_range_->GetEnd() == end) {
+ DCHECK(is_fixed_);
} else {
- DCHECK(first_range_->GetStart() > end);
+ DCHECK_GT(first_range_->GetStart(), end);
// There is a hole in the interval. Create a new range.
first_range_ = new (allocator_) LiveRange(start, end, first_range_);
}
@@ -215,7 +226,11 @@
}
bool HasSpillSlot() const { return spill_slot_ != kNoSpillSlot; }
- void SetSpillSlot(int slot) { spill_slot_ = slot; }
+ void SetSpillSlot(int slot) {
+ DCHECK(!is_fixed_);
+ DCHECK(!is_temp_);
+ spill_slot_ = slot;
+ }
int GetSpillSlot() const { return spill_slot_; }
void SetFrom(size_t from) {
@@ -243,6 +258,9 @@
}
bool Covers(size_t position) const {
+ if (IsDeadAt(position)) {
+ return false;
+ }
LiveRange* current = first_range_;
while (current != nullptr) {
if (position >= current->GetStart() && position < current->GetEnd()) {
@@ -288,6 +306,9 @@
}
size_t FirstRegisterUseAfter(size_t position) const {
+ if (is_temp_) {
+ return position == GetStart() ? position : kNoLifetime;
+ }
if (position == GetStart() && defined_by_ != nullptr) {
LocationSummary* locations = defined_by_->GetLocations();
Location location = locations->Out();
@@ -342,6 +363,7 @@
* [position ... end)
*/
LiveInterval* SplitAt(size_t position) {
+ DCHECK(!is_temp_);
DCHECK(!is_fixed_);
DCHECK_GT(position, GetStart());
@@ -453,7 +475,10 @@
int spill_slot_;
// Whether the interval is for a fixed register.
- bool is_fixed_;
+ const bool is_fixed_;
+
+ // Whether the interval is for a temporary.
+ const bool is_temp_;
// The instruction represented by this interval.
HInstruction* const defined_by_;