Support for inlining methods that call/throw.
Mostly fixes here and there to make it working.
Change-Id: I1b535e895105d78b65634636d675b818551f783e
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 3144c5c..005d50e 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -143,6 +143,7 @@
dex_file_(dex_file),
method_idx_(method_idx),
invoke_type_(invoke_type),
+ in_ssa_form_(false),
should_generate_constructor_barrier_(should_generate_constructor_barrier),
cached_null_constant_(nullptr),
cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
@@ -174,6 +175,7 @@
// users remaining when being visited.
if (!AnalyzeNaturalLoops()) return false;
TransformToSsa();
+ in_ssa_form_ = true;
return true;
}
@@ -216,11 +218,16 @@
maximum_number_of_out_vregs_ = new_value;
}
+ void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
+ maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
+ }
+
void UpdateTemporariesVRegSlots(size_t slots) {
temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
}
size_t GetTemporariesVRegSlots() const {
+ DCHECK(!in_ssa_form_);
return temporaries_vreg_slots_;
}
@@ -229,6 +236,7 @@
}
uint16_t GetNumberOfVRegs() const {
+ DCHECK(!in_ssa_form_);
return number_of_vregs_;
}
@@ -237,6 +245,7 @@
}
uint16_t GetNumberOfLocalVRegs() const {
+ DCHECK(!in_ssa_form_);
return number_of_vregs_ - number_of_in_vregs_;
}
@@ -381,6 +390,11 @@
// If inlined, this encodes how the callee is being invoked.
const InvokeType invoke_type_;
+ // Whether the graph has been transformed to SSA form. Only used
+ // in debug mode to ensure we are not using properties only valid
+ // for non-SSA form (like the number of temporaries).
+ bool in_ssa_form_;
+
const bool should_generate_constructor_barrier_;
// Cached constants.
@@ -1121,14 +1135,16 @@
const DexFile& dex_file,
uint32_t method_idx,
uint32_t dex_pc,
- InvokeType invoke_type)
+ InvokeType invoke_type,
+ HInstruction* holder)
: vregs_(arena, number_of_vregs),
locations_(arena, number_of_vregs),
parent_(nullptr),
dex_file_(dex_file),
method_idx_(method_idx),
dex_pc_(dex_pc),
- invoke_type_(invoke_type) {
+ invoke_type_(invoke_type),
+ holder_(holder) {
vregs_.SetSize(number_of_vregs);
for (size_t i = 0; i < number_of_vregs; i++) {
vregs_.Put(i, HUserRecord<HEnvironment*>());
@@ -1140,19 +1156,24 @@
}
}
- HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy)
+ HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
: HEnvironment(arena,
to_copy.Size(),
to_copy.GetDexFile(),
to_copy.GetMethodIdx(),
to_copy.GetDexPc(),
- to_copy.GetInvokeType()) {}
+ to_copy.GetInvokeType(),
+ holder) {}
void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
- parent_ = new (allocator) HEnvironment(allocator, *parent);
- parent_->CopyFrom(parent);
- if (parent->GetParent() != nullptr) {
- parent_->SetAndCopyParentChain(allocator, parent->GetParent());
+ if (parent_ != nullptr) {
+ parent_->SetAndCopyParentChain(allocator, parent);
+ } else {
+ parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
+ parent_->CopyFrom(parent);
+ if (parent->GetParent() != nullptr) {
+ parent_->SetAndCopyParentChain(allocator, parent->GetParent());
+ }
}
}
@@ -1202,6 +1223,10 @@
return dex_file_;
}
+ HInstruction* GetHolder() const {
+ return holder_;
+ }
+
private:
// Record instructions' use entries of this environment for constant-time removal.
// It should only be called by HInstruction when a new environment use is added.
@@ -1219,6 +1244,10 @@
const uint32_t dex_pc_;
const InvokeType invoke_type_;
+ // The instruction that holds this environment. Only used in debug mode
+ // to ensure the graph is consistent.
+ HInstruction* const holder_;
+
friend class HInstruction;
DISALLOW_COPY_AND_ASSIGN(HEnvironment);
@@ -1425,13 +1454,18 @@
HEnvironment* GetEnvironment() const { return environment_; }
// Set the `environment_` field. Raw because this method does not
// update the uses lists.
- void SetRawEnvironment(HEnvironment* environment) { environment_ = environment; }
+ void SetRawEnvironment(HEnvironment* environment) {
+ DCHECK(environment_ == nullptr);
+ DCHECK_EQ(environment->GetHolder(), this);
+ environment_ = environment;
+ }
// Set the environment of this instruction, copying it from `environment`. While
// copying, the uses lists are being updated.
void CopyEnvironmentFrom(HEnvironment* environment) {
+ DCHECK(environment_ == nullptr);
ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
- environment_ = new (allocator) HEnvironment(allocator, *environment);
+ environment_ = new (allocator) HEnvironment(allocator, *environment, this);
environment_->CopyFrom(environment);
if (environment->GetParent() != nullptr) {
environment_->SetAndCopyParentChain(allocator, environment->GetParent());
@@ -1440,8 +1474,9 @@
void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
HBasicBlock* block) {
+ DCHECK(environment_ == nullptr);
ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
- environment_ = new (allocator) HEnvironment(allocator, *environment);
+ environment_ = new (allocator) HEnvironment(allocator, *environment, this);
environment_->CopyFromWithLoopPhiAdjustment(environment, block);
if (environment->GetParent() != nullptr) {
environment_->SetAndCopyParentChain(allocator, environment->GetParent());
@@ -2420,6 +2455,12 @@
intrinsic_ = intrinsic;
}
+ bool IsInlined() const {
+ return GetEnvironment()->GetParent() != nullptr;
+ }
+
+ bool CanThrow() const OVERRIDE { return true; }
+
DECLARE_INSTRUCTION(Invoke);
protected: