Detect special methods at the end of verification.
This moves special method handling to method inliner
and prepares for eventual inlining of these methods.
Change-Id: I51c51b940fb7bc714e33135cd61be69467861352
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 9198f2a..06de4fe 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -21,15 +21,16 @@
#include <map>
#include "base/mutex.h"
#include "base/macros.h"
+#include "dex/compiler_enums.h"
+#include "dex_file.h"
#include "locks.h"
namespace art {
class CallInfo;
-class DexFile;
class Mir2Lir;
-enum IntrinsicOpcode {
+enum InlineMethodOpcode : uint16_t {
kIntrinsicDoubleCvt,
kIntrinsicFloatCvt,
kIntrinsicReverseBytes,
@@ -47,8 +48,26 @@
kIntrinsicCas,
kIntrinsicUnsafeGet,
kIntrinsicUnsafePut,
+
+ kInlineOpNop,
+ kInlineOpReturnArg,
+ kInlineOpConst,
+ kInlineOpIGet,
+ kInlineOpIPut,
};
+enum InlineMethodFlags {
+ kInlineIntrinsic = 0x0001,
+ kInlineSpecial = 0x0002,
+};
+
+struct InlineMethod {
+ uint16_t opcode;
+ uint16_t flags;
+ uint32_t data;
+};
+
+// IntrinsicFlags are stored in InlineMethod::data
enum IntrinsicFlags {
kIntrinsicFlagNone = 0,
@@ -73,10 +92,32 @@
kIntrinsicFlagIsOrdered = 8,
};
-struct Intrinsic {
- IntrinsicOpcode opcode;
+// Check that OpSize fits into 3 bits (at least the values the inliner uses).
+COMPILE_ASSERT(kWord < 8 && kLong < 8 && kSingle < 8 && kDouble < 8 && kUnsignedHalf < 8 &&
+ kSignedHalf < 8 && kUnsignedByte < 8 && kSignedByte < 8, op_size_field_too_narrow);
+
+union InlineIGetIPutData {
uint32_t data;
+ struct {
+ uint16_t field;
+ uint32_t op_size : 3; // OpSize
+ uint32_t is_object : 1;
+ uint32_t object_arg : 4;
+ uint32_t src_arg : 4; // iput only
+ uint32_t reserved : 4;
+ } d;
};
+COMPILE_ASSERT(sizeof(InlineIGetIPutData) == sizeof(uint32_t), InvalidSizeOfInlineIGetIPutData);
+
+union InlineReturnArgData {
+ uint32_t data;
+ struct {
+ uint16_t arg;
+ uint32_t op_size : 3; // OpSize
+ uint32_t reserved : 13;
+ } d;
+};
+COMPILE_ASSERT(sizeof(InlineReturnArgData) == sizeof(uint32_t), InvalidSizeOfInlineReturnArgData);
/**
* Handles inlining of methods from a particular DexFile.
@@ -96,6 +137,16 @@
~DexFileMethodInliner();
/**
+ * Analyse method code to determine if the method is a candidate for inlining.
+ * If it is, record its data for later.
+ *
+ * @param method_idx the index of the inlining candidate.
+ * @param code_item a previously verified code item of the method.
+ */
+ bool AnalyseMethodCode(uint32_t method_idx,
+ const DexFile::CodeItem* code_item) LOCKS_EXCLUDED(lock_);
+
+ /**
* Check whether a particular method index corresponds to an intrinsic function.
*/
bool IsIntrinsic(uint32_t method_index) LOCKS_EXCLUDED(lock_);
@@ -105,6 +156,16 @@
*/
bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_);
+ /**
+ * Check whether a particular method index corresponds to a special function.
+ */
+ bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_);
+
+ /**
+ * Generate code for a special function.
+ */
+ bool GenSpecial(Mir2Lir* backend, uint32_t method_idx);
+
private:
/**
* To avoid multiple lookups of a class by its descriptor, we cache its
@@ -261,7 +322,7 @@
*/
struct IntrinsicDef {
MethodDef method_def;
- Intrinsic intrinsic;
+ InlineMethod intrinsic;
};
/**
@@ -281,8 +342,8 @@
uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst];
};
- static const char* kClassCacheNames[];
- static const char* kNameCacheNames[];
+ static const char* const kClassCacheNames[];
+ static const char* const kNameCacheNames[];
static const ProtoDef kProtoCacheDefs[];
static const IntrinsicDef kIntrinsicMethods[];
@@ -307,11 +368,23 @@
friend class DexFileToMethodInlinerMap;
+ bool AddInlineMethod(int32_t method_idx, InlineMethodOpcode opcode,
+ uint16_t flags, uint32_t data) LOCKS_EXCLUDED(lock_);
+
+ bool AnalyseReturnMethod(int32_t method_idx, const DexFile::CodeItem* code_item,
+ OpSize size) LOCKS_EXCLUDED(lock_);
+ bool AnalyseConstMethod(int32_t method_idx, const DexFile::CodeItem* code_item
+ ) LOCKS_EXCLUDED(lock_);
+ bool AnalyseIGetMethod(int32_t method_idx, const DexFile::CodeItem* code_item,
+ OpSize size, bool is_object) LOCKS_EXCLUDED(lock_);
+ bool AnalyseIPutMethod(int32_t method_idx, const DexFile::CodeItem* code_item,
+ OpSize size, bool is_object) LOCKS_EXCLUDED(lock_);
+
ReaderWriterMutex lock_;
/*
* Maps method indexes (for the particular DexFile) to Intrinsic defintions.
*/
- std::map<uint32_t, Intrinsic> intrinsics_ GUARDED_BY(lock_);
+ std::map<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_);
const DexFile* dex_file_;
DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);