ARM/MIPS: Avoid dead dex cache arrays base for intrinsics.
Test: Run ART test suite on host and Nexus 6.
Change-Id: Ie2ad70f1e3f125eae5dad53a6384d405e0311505
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index ba2df07..4ea17a9 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1857,9 +1857,7 @@
// art::PrepareForRegisterAllocation.
DCHECK(!invoke->IsStaticWithExplicitClinitCheck());
- IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
- codegen_->GetAssembler(),
- codegen_->GetInstructionSetFeatures());
+ IntrinsicLocationsBuilderARM intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
if (invoke->GetLocations()->CanCall() && invoke->HasPcRelativeDexCache()) {
invoke->GetLocations()->SetInAt(invoke->GetSpecialInputIndex(), Location::Any());
@@ -1905,9 +1903,7 @@
}
void LocationsBuilderARM::VisitInvokeVirtual(HInvokeVirtual* invoke) {
- IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
- codegen_->GetAssembler(),
- codegen_->GetInstructionSetFeatures());
+ IntrinsicLocationsBuilderARM intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
return;
}
diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.cc b/compiler/optimizing/dex_cache_array_fixups_arm.cc
index 14c318e..6ad9b07 100644
--- a/compiler/optimizing/dex_cache_array_fixups_arm.cc
+++ b/compiler/optimizing/dex_cache_array_fixups_arm.cc
@@ -17,6 +17,8 @@
#include "dex_cache_array_fixups_arm.h"
#include "base/arena_containers.h"
+#include "code_generator_arm.h"
+#include "intrinsics_arm.h"
#include "utils/dex_cache_arrays_layout-inl.h"
namespace art {
@@ -27,8 +29,9 @@
*/
class DexCacheArrayFixupsVisitor : public HGraphVisitor {
public:
- explicit DexCacheArrayFixupsVisitor(HGraph* graph)
+ DexCacheArrayFixupsVisitor(HGraph* graph, CodeGenerator* codegen)
: HGraphVisitor(graph),
+ codegen_(down_cast<CodeGeneratorARM*>(codegen)),
dex_cache_array_bases_(std::less<const DexFile*>(),
// Attribute memory use to code generator.
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) {}
@@ -77,7 +80,8 @@
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
// If this is an invoke with PC-relative access to the dex cache methods array,
// we need to add the dex cache arrays base as the special input.
- if (invoke->HasPcRelativeDexCache()) {
+ if (invoke->HasPcRelativeDexCache() &&
+ !IsCallFreeIntrinsic<IntrinsicLocationsBuilderARM>(invoke, codegen_)) {
// Initialize base for target method dex file if needed.
MethodReference target_method = invoke->GetTargetMethod();
HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(*target_method.dex_file);
@@ -107,6 +111,8 @@
return base;
}
+ CodeGeneratorARM* codegen_;
+
using DexCacheArraysBaseMap =
ArenaSafeMap<const DexFile*, HArmDexCacheArraysBase*, std::less<const DexFile*>>;
DexCacheArraysBaseMap dex_cache_array_bases_;
@@ -118,7 +124,7 @@
// that can be live-in at the irreducible loop header.
return;
}
- DexCacheArrayFixupsVisitor visitor(graph_);
+ DexCacheArrayFixupsVisitor visitor(graph_, codegen_);
visitor.VisitInsertionOrder();
visitor.MoveBasesIfNeeded();
}
diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.h b/compiler/optimizing/dex_cache_array_fixups_arm.h
index 9142e29..9d67a31 100644
--- a/compiler/optimizing/dex_cache_array_fixups_arm.h
+++ b/compiler/optimizing/dex_cache_array_fixups_arm.h
@@ -21,16 +21,23 @@
#include "optimization.h"
namespace art {
+
+class CodeGenerator;
+
namespace arm {
class DexCacheArrayFixups : public HOptimization {
public:
- DexCacheArrayFixups(HGraph* graph, OptimizingCompilerStats* stats)
- : HOptimization(graph, kDexCacheArrayFixupsArmPassName, stats) {}
+ DexCacheArrayFixups(HGraph* graph, CodeGenerator* codegen, OptimizingCompilerStats* stats)
+ : HOptimization(graph, kDexCacheArrayFixupsArmPassName, stats),
+ codegen_(codegen) {}
static constexpr const char* kDexCacheArrayFixupsArmPassName = "dex_cache_array_fixups_arm";
void Run() OVERRIDE;
+
+ private:
+ CodeGenerator* codegen_;
};
} // namespace arm
diff --git a/compiler/optimizing/dex_cache_array_fixups_mips.cc b/compiler/optimizing/dex_cache_array_fixups_mips.cc
index 19bab08..300284d 100644
--- a/compiler/optimizing/dex_cache_array_fixups_mips.cc
+++ b/compiler/optimizing/dex_cache_array_fixups_mips.cc
@@ -18,6 +18,7 @@
#include "dex_cache_array_fixups_mips.h"
#include "base/arena_containers.h"
+#include "intrinsics_mips.h"
#include "utils/dex_cache_arrays_layout-inl.h"
namespace art {
@@ -85,7 +86,8 @@
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
// If this is an invoke with PC-relative access to the dex cache methods array,
// we need to add the dex cache arrays base as the special input.
- if (invoke->HasPcRelativeDexCache()) {
+ if (invoke->HasPcRelativeDexCache() &&
+ !IsCallFreeIntrinsic<IntrinsicLocationsBuilderMIPS>(invoke, codegen_)) {
// Initialize base for target method dex file if needed.
MethodReference target_method = invoke->GetTargetMethod();
HMipsDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(*target_method.dex_file);
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index 1a8eb58..62f731d 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -243,6 +243,24 @@
UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \
UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence)
+template <typename IntrinsicLocationsBuilder, typename Codegenerator>
+bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) {
+ if (invoke->GetIntrinsic() != Intrinsics::kNone) {
+ // This invoke may have intrinsic code generation defined. However, we must
+ // now also determine if this code generation is truly there and call-free
+ // (not unimplemented, no bail on instruction features, or call on slow path).
+ // This is done by actually calling the locations builder on the instruction
+ // and clearing out the locations once result is known. We assume this
+ // call only has creating locations as side effects!
+ // TODO: Avoid wasting Arena memory.
+ IntrinsicLocationsBuilder builder(codegen);
+ bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall();
+ invoke->SetLocations(nullptr);
+ return success;
+ }
+ return false;
+}
+
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index e1a6454..df7cb85 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -127,6 +127,11 @@
#undef __
+IntrinsicLocationsBuilderARM::IntrinsicLocationsBuilderARM(CodeGeneratorARM* codegen)
+ : arena_(codegen->GetGraph()->GetArena()),
+ assembler_(codegen->GetAssembler()),
+ features_(codegen->GetInstructionSetFeatures()) {}
+
bool IntrinsicLocationsBuilderARM::TryDispatch(HInvoke* invoke) {
Dispatch(invoke);
LocationSummary* res = invoke->GetLocations();
diff --git a/compiler/optimizing/intrinsics_arm.h b/compiler/optimizing/intrinsics_arm.h
index e01b6ff..c671700 100644
--- a/compiler/optimizing/intrinsics_arm.h
+++ b/compiler/optimizing/intrinsics_arm.h
@@ -33,10 +33,7 @@
class IntrinsicLocationsBuilderARM FINAL : public IntrinsicVisitor {
public:
- IntrinsicLocationsBuilderARM(ArenaAllocator* arena,
- ArmAssembler* assembler,
- const ArmInstructionSetFeatures& features)
- : arena_(arena), assembler_(assembler), features_(features) {}
+ explicit IntrinsicLocationsBuilderARM(CodeGeneratorARM* codegen);
// Define visitor methods.
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index f7c325e..6e98b4d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -490,7 +490,7 @@
return new (arena) SideEffectsAnalysis(graph);
#ifdef ART_ENABLE_CODEGEN_arm
} else if (opt_name == arm::DexCacheArrayFixups::kDexCacheArrayFixupsArmPassName) {
- return new (arena) arm::DexCacheArrayFixups(graph, stats);
+ return new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
} else if (opt_name == arm::InstructionSimplifierArm::kInstructionSimplifierArmPassName) {
return new (arena) arm::InstructionSimplifierArm(graph, stats);
#endif
@@ -604,7 +604,8 @@
#ifdef ART_ENABLE_CODEGEN_arm
case kThumb2:
case kArm: {
- arm::DexCacheArrayFixups* fixups = new (arena) arm::DexCacheArrayFixups(graph, stats);
+ arm::DexCacheArrayFixups* fixups =
+ new (arena) arm::DexCacheArrayFixups(graph, codegen, stats);
arm::InstructionSimplifierArm* simplifier =
new (arena) arm::InstructionSimplifierArm(graph, stats);
SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph);
diff --git a/compiler/optimizing/pc_relative_fixups_mips.cc b/compiler/optimizing/pc_relative_fixups_mips.cc
index c6acc45..c6d297d 100644
--- a/compiler/optimizing/pc_relative_fixups_mips.cc
+++ b/compiler/optimizing/pc_relative_fixups_mips.cc
@@ -115,7 +115,8 @@
return;
}
- if (has_extra_input && !WillHaveCallFreeIntrinsicsCodeGen(invoke)) {
+ if (has_extra_input &&
+ !IsCallFreeIntrinsic<IntrinsicLocationsBuilderMIPS>(invoke, codegen_)) {
InitializePCRelativeBasePointer();
// Add the extra parameter base_.
invoke_static_or_direct->AddSpecialInput(base_);
@@ -123,22 +124,6 @@
}
}
- bool WillHaveCallFreeIntrinsicsCodeGen(HInvoke* invoke) {
- if (invoke->GetIntrinsic() != Intrinsics::kNone) {
- // This invoke may have intrinsic code generation defined. However, we must
- // now also determine if this code generation is truly there and call-free
- // (not unimplemented, no bail on instruction features, or call on slow path).
- // This is done by actually calling the locations builder on the instruction
- // and clearing out the locations once result is known. We assume this
- // call only has creating locations as side effects!
- IntrinsicLocationsBuilderMIPS builder(codegen_);
- bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall();
- invoke->SetLocations(nullptr);
- return success;
- }
- return false;
- }
-
CodeGeneratorMIPS* codegen_;
// The generated HMipsComputeBaseMethodAddress in the entry block needed as an
diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc
index ad0921d..75587af 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -203,7 +203,7 @@
bool base_added = false;
if (invoke_static_or_direct != nullptr &&
invoke_static_or_direct->HasPcRelativeDexCache() &&
- !WillHaveCallFreeIntrinsicsCodeGen(invoke)) {
+ !IsCallFreeIntrinsic<IntrinsicLocationsBuilderX86>(invoke, codegen_)) {
InitializePCRelativeBasePointer();
// Add the extra parameter base_.
invoke_static_or_direct->AddSpecialInput(base_);
@@ -240,22 +240,6 @@
}
}
- bool WillHaveCallFreeIntrinsicsCodeGen(HInvoke* invoke) {
- if (invoke->GetIntrinsic() != Intrinsics::kNone) {
- // This invoke may have intrinsic code generation defined. However, we must
- // now also determine if this code generation is truly there and call-free
- // (not unimplemented, no bail on instruction features, or call on slow path).
- // This is done by actually calling the locations builder on the instruction
- // and clearing out the locations once result is known. We assume this
- // call only has creating locations as side effects!
- IntrinsicLocationsBuilderX86 builder(codegen_);
- bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall();
- invoke->SetLocations(nullptr);
- return success;
- }
- return false;
- }
-
CodeGeneratorX86* codegen_;
// The generated HX86ComputeBaseMethodAddress in the entry block needed as an