Add a HCurrentMethod node.
This enables register allocation for the current method, so
that users of it don't always load it from the stack.
Currently only used by HLoadClass. Will make follow-up
CLs for the other users.
Change-Id: If73324d85643102faba47fabbbd2755eb258c59c
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 01870c3..d542e59 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -35,6 +35,7 @@
class GraphChecker;
class HBasicBlock;
+class HCurrentMethod;
class HDoubleConstant;
class HEnvironment;
class HFloatConstant;
@@ -147,7 +148,8 @@
cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
- cached_double_constants_(std::less<int64_t>(), arena->Adapter()) {}
+ cached_double_constants_(std::less<int64_t>(), arena->Adapter()),
+ cached_current_method_(nullptr) {}
ArenaAllocator* GetArena() const { return arena_; }
const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
@@ -278,6 +280,8 @@
return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
}
+ HCurrentMethod* GetCurrentMethod();
+
HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
const DexFile& GetDexFile() const {
@@ -386,6 +390,8 @@
ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
+ HCurrentMethod* cached_current_method_;
+
friend class SsaBuilder; // For caching constants.
friend class SsaLivenessAnalysis; // For the linear order.
ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
@@ -811,6 +817,7 @@
M(ClinitCheck, Instruction) \
M(Compare, BinaryOperation) \
M(Condition, BinaryOperation) \
+ M(CurrentMethod, Instruction) \
M(Deoptimize, Instruction) \
M(Div, BinaryOperation) \
M(DivZeroCheck, Instruction) \
@@ -1824,6 +1831,19 @@
DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
};
+// Represents the ArtMethod that was passed as a first argument to
+// the method. It is used by instructions that depend on it, like
+// instructions that work with the dex cache.
+class HCurrentMethod : public HExpression<0> {
+ public:
+ HCurrentMethod() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
+
+ DECLARE_INSTRUCTION(CurrentMethod);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
+};
+
class HUnaryOperation : public HExpression<1> {
public:
HUnaryOperation(Primitive::Type result_type, HInstruction* input)
@@ -3433,9 +3453,10 @@
/**
* Instruction to load a Class object.
*/
-class HLoadClass : public HExpression<0> {
+class HLoadClass : public HExpression<1> {
public:
- HLoadClass(uint16_t type_index,
+ HLoadClass(HCurrentMethod* current_method,
+ uint16_t type_index,
const DexFile& dex_file,
bool is_referrers_class,
uint32_t dex_pc)
@@ -3445,7 +3466,9 @@
is_referrers_class_(is_referrers_class),
dex_pc_(dex_pc),
generate_clinit_check_(false),
- loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
+ loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
+ SetRawInputAt(0, current_method);
+ }
bool CanBeMoved() const OVERRIDE { return true; }