Revert "Add JIT"
Sorry, run-test crashes on target:
0-05 12:15:51.633 I/DEBUG (27995): Abort message: 'art/runtime/mirror/art_method.cc:349] Check failed: PcIsWithinQuickCode(reinterpret_cast<uintptr_t>(code), pc) java.lang.Throwable java.lang.Throwable.fillInStackTrace() pc=71e3366b code=0x71e3362d size=ad000000'
10-05 12:15:51.633 I/DEBUG (27995): r0 00000000 r1 0000542b r2 00000006 r3 00000000
10-05 12:15:51.633 I/DEBUG (27995): r4 00000006 r5 b6f9addc r6 00000002 r7 0000010c
10-05 12:15:51.633 I/DEBUG (27995): r8 b63fe1e8 r9 be8e1418 sl b6427400 fp b63fcce0
10-05 12:15:51.633 I/DEBUG (27995): ip 0000542b sp be8e1358 lr b6e9a27b pc b6e9c280 cpsr 40070010
10-05 12:15:51.633 I/DEBUG (27995):
Bug: 17950037
This reverts commit 2535abe7d1fcdd0e6aca782b1f1932a703ed50a4.
Change-Id: I6f88849bc6f2befed0c0aaa0b7b2a08c967a83c3
diff --git a/compiler/dex/global_value_numbering_test.cc b/compiler/dex/global_value_numbering_test.cc
index b91c3ca..54e34ea 100644
--- a/compiler/dex/global_value_numbering_test.cc
+++ b/compiler/dex/global_value_numbering_test.cc
@@ -142,7 +142,7 @@
cu_.mir_graph->ifield_lowering_infos_.reserve(count);
for (size_t i = 0u; i != count; ++i) {
const IFieldDef* def = &defs[i];
- MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
+ MirIFieldLoweringInfo field_info(def->field_idx, def->type);
if (def->declaring_dex_file != 0u) {
field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
field_info.declaring_field_idx_ = def->declaring_field_idx;
diff --git a/compiler/dex/gvn_dead_code_elimination_test.cc b/compiler/dex/gvn_dead_code_elimination_test.cc
index 4d2b8b3..954e9f1 100644
--- a/compiler/dex/gvn_dead_code_elimination_test.cc
+++ b/compiler/dex/gvn_dead_code_elimination_test.cc
@@ -143,7 +143,7 @@
cu_.mir_graph->ifield_lowering_infos_.reserve(count);
for (size_t i = 0u; i != count; ++i) {
const IFieldDef* def = &defs[i];
- MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
+ MirIFieldLoweringInfo field_info(def->field_idx, def->type);
if (def->declaring_dex_file != 0u) {
field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
field_info.declaring_field_idx_ = def->declaring_field_idx;
diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h
index 379c952..97ea05a 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -21,8 +21,8 @@
#include "base/arena_object.h"
#include "base/logging.h"
-#include "dex_instruction_utils.h"
#include "global_value_numbering.h"
+#include "utils/dex_instruction_utils.h"
namespace art {
diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc
index 566527a..d1c3a6b 100644
--- a/compiler/dex/local_value_numbering_test.cc
+++ b/compiler/dex/local_value_numbering_test.cc
@@ -96,7 +96,7 @@
cu_.mir_graph->ifield_lowering_infos_.reserve(count);
for (size_t i = 0u; i != count; ++i) {
const IFieldDef* def = &defs[i];
- MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
+ MirIFieldLoweringInfo field_info(def->field_idx, def->type);
if (def->declaring_dex_file != 0u) {
field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
field_info.declaring_field_idx_ = def->declaring_field_idx;
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index a89b250..31dbc60 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -416,8 +416,8 @@
// 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA}
kAnInvoke | kAnHeavyWeight,
- // 73 RETURN_VOID_BARRIER
- kAnBranch,
+ // 73 UNUSED_73
+ kAnNone,
// 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
kAnInvoke | kAnHeavyWeight,
@@ -752,88 +752,88 @@
// E2 USHR_INT_LIT8 vAA, vBB, #+CC
kAnMath | kAnInt,
- // E3 IGET_QUICK
+ // E3 IGET_VOLATILE
kAnNone,
- // E4 IGET_WIDE_QUICK
+ // E4 IPUT_VOLATILE
kAnNone,
- // E5 IGET_OBJECT_QUICK
+ // E5 SGET_VOLATILE
kAnNone,
- // E6 IPUT_QUICK
+ // E6 SPUT_VOLATILE
kAnNone,
- // E7 IPUT_WIDE_QUICK
+ // E7 IGET_OBJECT_VOLATILE
kAnNone,
- // E8 IPUT_OBJECT_QUICK
+ // E8 IGET_WIDE_VOLATILE
kAnNone,
- // E9 INVOKE_VIRTUAL_QUICK
+ // E9 IPUT_WIDE_VOLATILE
+ kAnNone,
+
+ // EA SGET_WIDE_VOLATILE
+ kAnNone,
+
+ // EB SPUT_WIDE_VOLATILE
+ kAnNone,
+
+ // EC BREAKPOINT
+ kAnNone,
+
+ // ED THROW_VERIFICATION_ERROR
+ kAnHeavyWeight | kAnBranch,
+
+ // EE EXECUTE_INLINE
+ kAnNone,
+
+ // EF EXECUTE_INLINE_RANGE
+ kAnNone,
+
+ // F0 INVOKE_OBJECT_INIT_RANGE
kAnInvoke | kAnHeavyWeight,
- // EA INVOKE_VIRTUAL_RANGE_QUICK
+ // F1 RETURN_VOID_BARRIER
+ kAnBranch,
+
+ // F2 IGET_QUICK
+ kAnNone,
+
+ // F3 IGET_WIDE_QUICK
+ kAnNone,
+
+ // F4 IGET_OBJECT_QUICK
+ kAnNone,
+
+ // F5 IPUT_QUICK
+ kAnNone,
+
+ // F6 IPUT_WIDE_QUICK
+ kAnNone,
+
+ // F7 IPUT_OBJECT_QUICK
+ kAnNone,
+
+ // F8 INVOKE_VIRTUAL_QUICK
kAnInvoke | kAnHeavyWeight,
- // EB IPUT_BOOLEAN_QUICK
+ // F9 INVOKE_VIRTUAL_QUICK_RANGE
+ kAnInvoke | kAnHeavyWeight,
+
+ // FA INVOKE_SUPER_QUICK
+ kAnInvoke | kAnHeavyWeight,
+
+ // FB INVOKE_SUPER_QUICK_RANGE
+ kAnInvoke | kAnHeavyWeight,
+
+ // FC IPUT_OBJECT_VOLATILE
kAnNone,
- // EC IPUT_BYTE_QUICK
+ // FD SGET_OBJECT_VOLATILE
kAnNone,
- // ED IPUT_CHAR_QUICK
- kAnNone,
-
- // EE IPUT_SHORT_QUICK
- kAnNone,
-
- // EF IGET_BOOLEAN_QUICK
- kAnNone,
-
- // F0 IGET_BYTE_QUICK
- kAnNone,
-
- // F1 IGET_CHAR_QUICK
- kAnNone,
-
- // F2 IGET_SHORT_QUICK
- kAnNone,
-
- // F3 UNUSED_F3
- kAnNone,
-
- // F4 UNUSED_F4
- kAnNone,
-
- // F5 UNUSED_F5
- kAnNone,
-
- // F6 UNUSED_F6
- kAnNone,
-
- // F7 UNUSED_F7
- kAnNone,
-
- // F8 UNUSED_F8
- kAnNone,
-
- // F9 UNUSED_F9
- kAnNone,
-
- // FA UNUSED_FA
- kAnNone,
-
- // FB UNUSED_FB
- kAnNone,
-
- // FC UNUSED_FC
- kAnNone,
-
- // FD UNUSED_FD
- kAnNone,
-
- // FE UNUSED_FE
+ // FE SPUT_OBJECT_VOLATILE
kAnNone,
// FF UNUSED_FF
@@ -1203,13 +1203,12 @@
}
void MIRGraph::DoCacheFieldLoweringInfo() {
- static constexpr uint32_t kFieldIndexFlagQuickened = 0x80000000;
// All IGET/IPUT/SGET/SPUT instructions take 2 code units and there must also be a RETURN.
const uint32_t max_refs = (GetNumDalvikInsns() - 1u) / 2u;
ScopedArenaAllocator allocator(&cu_->arena_stack);
- auto* field_idxs = allocator.AllocArray<uint32_t>(max_refs, kArenaAllocMisc);
- DexMemAccessType* field_types = allocator.AllocArray<DexMemAccessType>(
- max_refs, kArenaAllocMisc);
+ uint16_t* field_idxs = allocator.AllocArray<uint16_t>(max_refs, kArenaAllocMisc);
+ DexMemAccessType* field_types = allocator.AllocArray<DexMemAccessType>(max_refs, kArenaAllocMisc);
+
// Find IGET/IPUT/SGET/SPUT insns, store IGET/IPUT fields at the beginning, SGET/SPUT at the end.
size_t ifield_pos = 0u;
size_t sfield_pos = max_refs;
@@ -1222,36 +1221,23 @@
// Get field index and try to find it among existing indexes. If found, it's usually among
// the last few added, so we'll start the search from ifield_pos/sfield_pos. Though this
// is a linear search, it actually performs much better than map based approach.
- const bool is_iget_or_iput = IsInstructionIGetOrIPut(mir->dalvikInsn.opcode);
- const bool is_iget_or_iput_quick = IsInstructionIGetQuickOrIPutQuick(mir->dalvikInsn.opcode);
- if (is_iget_or_iput || is_iget_or_iput_quick) {
- uint32_t field_idx;
- DexMemAccessType access_type;
- if (is_iget_or_iput) {
- field_idx = mir->dalvikInsn.vC;
- access_type = IGetOrIPutMemAccessType(mir->dalvikInsn.opcode);
- } else {
- DCHECK(is_iget_or_iput_quick);
- // Set kFieldIndexFlagQuickened so that we don't deduplicate against non quickened field
- // indexes.
- field_idx = mir->offset | kFieldIndexFlagQuickened;
- access_type = IGetQuickOrIPutQuickMemAccessType(mir->dalvikInsn.opcode);
- }
+ if (IsInstructionIGetOrIPut(mir->dalvikInsn.opcode)) {
+ uint16_t field_idx = mir->dalvikInsn.vC;
size_t i = ifield_pos;
while (i != 0u && field_idxs[i - 1] != field_idx) {
--i;
}
if (i != 0u) {
mir->meta.ifield_lowering_info = i - 1;
- DCHECK_EQ(field_types[i - 1], access_type);
+ DCHECK_EQ(field_types[i - 1], IGetOrIPutMemAccessType(mir->dalvikInsn.opcode));
} else {
mir->meta.ifield_lowering_info = ifield_pos;
field_idxs[ifield_pos] = field_idx;
- field_types[ifield_pos] = access_type;
+ field_types[ifield_pos] = IGetOrIPutMemAccessType(mir->dalvikInsn.opcode);
++ifield_pos;
}
} else if (IsInstructionSGetOrSPut(mir->dalvikInsn.opcode)) {
- auto field_idx = mir->dalvikInsn.vB;
+ uint16_t field_idx = mir->dalvikInsn.vB;
size_t i = sfield_pos;
while (i != max_refs && field_idxs[i] != field_idx) {
++i;
@@ -1275,12 +1261,7 @@
DCHECK_EQ(ifield_lowering_infos_.size(), 0u);
ifield_lowering_infos_.reserve(ifield_pos);
for (size_t pos = 0u; pos != ifield_pos; ++pos) {
- const uint32_t field_idx = field_idxs[pos];
- const bool is_quickened = (field_idx & kFieldIndexFlagQuickened) != 0;
- const uint32_t masked_field_idx = field_idx & ~kFieldIndexFlagQuickened;
- CHECK_LT(masked_field_idx, 1u << 16);
- ifield_lowering_infos_.push_back(
- MirIFieldLoweringInfo(masked_field_idx, field_types[pos], is_quickened));
+ ifield_lowering_infos_.push_back(MirIFieldLoweringInfo(field_idxs[pos], field_types[pos]));
}
MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, GetCurrentDexCompilationUnit(),
ifield_lowering_infos_.data(), ifield_pos);
@@ -1301,19 +1282,18 @@
void MIRGraph::DoCacheMethodLoweringInfo() {
static constexpr uint16_t invoke_types[] = { kVirtual, kSuper, kDirect, kStatic, kInterface };
- static constexpr uint32_t kMethodIdxFlagQuickened = 0x80000000;
// Embed the map value in the entry to avoid extra padding in 64-bit builds.
struct MapEntry {
// Map key: target_method_idx, invoke_type, devirt_target. Ordered to avoid padding.
const MethodReference* devirt_target;
- uint32_t target_method_idx;
- uint32_t vtable_idx;
+ uint16_t target_method_idx;
uint16_t invoke_type;
// Map value.
uint32_t lowering_info_index;
};
+ // Sort INVOKEs by method index, then by opcode, then by devirtualization target.
struct MapEntryComparator {
bool operator()(const MapEntry& lhs, const MapEntry& rhs) const {
if (lhs.target_method_idx != rhs.target_method_idx) {
@@ -1322,9 +1302,6 @@
if (lhs.invoke_type != rhs.invoke_type) {
return lhs.invoke_type < rhs.invoke_type;
}
- if (lhs.vtable_idx != rhs.vtable_idx) {
- return lhs.vtable_idx < rhs.vtable_idx;
- }
if (lhs.devirt_target != rhs.devirt_target) {
if (lhs.devirt_target == nullptr) {
return true;
@@ -1342,7 +1319,7 @@
ScopedArenaAllocator allocator(&cu_->arena_stack);
// All INVOKE instructions take 3 code units and there must also be a RETURN.
- const uint32_t max_refs = (GetNumDalvikInsns() - 1u) / 3u;
+ uint32_t max_refs = (GetNumDalvikInsns() - 1u) / 3u;
// Map invoke key (see MapEntry) to lowering info index and vice versa.
// The invoke_map and sequential entries are essentially equivalent to Boost.MultiIndex's
@@ -1353,43 +1330,28 @@
allocator.AllocArray<const MapEntry*>(max_refs, kArenaAllocMisc);
// Find INVOKE insns and their devirtualization targets.
- const VerifiedMethod* verified_method = GetCurrentDexCompilationUnit()->GetVerifiedMethod();
AllNodesIterator iter(this);
for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
if (bb->block_type != kDalvikByteCode) {
continue;
}
for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
- const bool is_quick_invoke = IsInstructionQuickInvoke(mir->dalvikInsn.opcode);
- const bool is_invoke = IsInstructionInvoke(mir->dalvikInsn.opcode);
- if (is_quick_invoke || is_invoke) {
- uint32_t vtable_index = 0;
- uint32_t target_method_idx = 0;
- uint32_t invoke_type_idx = 0; // Default to virtual (in case of quickened).
- DCHECK_EQ(invoke_types[invoke_type_idx], kVirtual);
- if (is_quick_invoke) {
- // We need to store the vtable index since we can't necessarily recreate it at resolve
- // phase if the dequickening resolved to an interface method.
- vtable_index = mir->dalvikInsn.vB;
- // Fake up the method index by storing the mir offset so that we can read the dequicken
- // info in resolve.
- target_method_idx = mir->offset | kMethodIdxFlagQuickened;
- } else {
- DCHECK(is_invoke);
- // Decode target method index and invoke type.
- invoke_type_idx = InvokeInstructionType(mir->dalvikInsn.opcode);
- target_method_idx = mir->dalvikInsn.vB;
- }
+ if (IsInstructionInvoke(mir->dalvikInsn.opcode)) {
+ // Decode target method index and invoke type.
+ uint16_t target_method_idx = mir->dalvikInsn.vB;
+ DexInvokeType invoke_type_idx = InvokeInstructionType(mir->dalvikInsn.opcode);
+
// Find devirtualization target.
// TODO: The devirt map is ordered by the dex pc here. Is there a way to get INVOKEs
// ordered by dex pc as well? That would allow us to keep an iterator to devirt targets
// and increment it as needed instead of making O(log n) lookups.
+ const VerifiedMethod* verified_method = GetCurrentDexCompilationUnit()->GetVerifiedMethod();
const MethodReference* devirt_target = verified_method->GetDevirtTarget(mir->offset);
+
// Try to insert a new entry. If the insertion fails, we will have found an old one.
MapEntry entry = {
devirt_target,
target_method_idx,
- vtable_index,
invoke_types[invoke_type_idx],
static_cast<uint32_t>(invoke_map.size())
};
@@ -1400,24 +1362,22 @@
}
}
}
+
if (invoke_map.empty()) {
return;
}
+
// Prepare unique method infos, set method info indexes for their MIRs.
+ DCHECK_EQ(method_lowering_infos_.size(), 0u);
const size_t count = invoke_map.size();
method_lowering_infos_.reserve(count);
for (size_t pos = 0u; pos != count; ++pos) {
const MapEntry* entry = sequential_entries[pos];
- const bool is_quick = (entry->target_method_idx & kMethodIdxFlagQuickened) != 0;
- const uint32_t masked_method_idx = entry->target_method_idx & ~kMethodIdxFlagQuickened;
- MirMethodLoweringInfo method_info(masked_method_idx,
- static_cast<InvokeType>(entry->invoke_type), is_quick);
+ MirMethodLoweringInfo method_info(entry->target_method_idx,
+ static_cast<InvokeType>(entry->invoke_type));
if (entry->devirt_target != nullptr) {
method_info.SetDevirtualizationTarget(*entry->devirt_target);
}
- if (is_quick) {
- method_info.SetVTableIndex(entry->vtable_idx);
- }
method_lowering_infos_.push_back(method_info);
}
MirMethodLoweringInfo::Resolve(cu_->compiler_driver, GetCurrentDexCompilationUnit(),
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index dfaff6c..f9f7e22 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -374,7 +374,7 @@
// 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA}
DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
- // 73 RETURN_VOID_BARRIER
+ // 73 UNUSED_73
DF_NOP,
// 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
@@ -710,89 +710,89 @@
// E2 USHR_INT_LIT8 vAA, vBB, #+CC
DF_DA | DF_UB | DF_CORE_A | DF_CORE_B,
- // E3 IGET_QUICK
+ // E3 IGET_VOLATILE
DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
- // E4 IGET_WIDE_QUICK
- DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // E4 IPUT_VOLATILE
+ DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
- // E5 IGET_OBJECT_QUICK
+ // E5 SGET_VOLATILE
+ DF_DA | DF_SFIELD | DF_CLINIT | DF_UMS,
+
+ // E6 SPUT_VOLATILE
+ DF_UA | DF_SFIELD | DF_CLINIT | DF_UMS,
+
+ // E7 IGET_OBJECT_VOLATILE
DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
- // E6 IPUT_QUICK
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // E8 IGET_WIDE_VOLATILE
+ DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
- // E7 IPUT_WIDE_QUICK
+ // E9 IPUT_WIDE_VOLATILE
DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
- // E8 IPUT_OBJECT_QUICK
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
+ // EA SGET_WIDE_VOLATILE
+ DF_DA | DF_A_WIDE | DF_SFIELD | DF_CLINIT | DF_UMS,
- // E9 INVOKE_VIRTUAL_QUICK
+ // EB SPUT_WIDE_VOLATILE
+ DF_UA | DF_A_WIDE | DF_SFIELD | DF_CLINIT | DF_UMS,
+
+ // EC BREAKPOINT
+ DF_NOP,
+
+ // ED THROW_VERIFICATION_ERROR
+ DF_NOP | DF_UMS,
+
+ // EE EXECUTE_INLINE
+ DF_FORMAT_35C,
+
+ // EF EXECUTE_INLINE_RANGE
+ DF_FORMAT_3RC,
+
+ // F0 INVOKE_OBJECT_INIT_RANGE
+ DF_NOP,
+
+ // F1 RETURN_VOID_BARRIER
+ DF_NOP,
+
+ // F2 IGET_QUICK
+ DF_DA | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F3 IGET_WIDE_QUICK
+ DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F4 IGET_OBJECT_QUICK
+ DF_DA | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F5 IPUT_QUICK
+ DF_UA | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F6 IPUT_WIDE_QUICK
+ DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F7 IPUT_OBJECT_QUICK
+ DF_UA | DF_UB | DF_NULL_CHK_B | DF_IFIELD | DF_LVN,
+
+ // F8 INVOKE_VIRTUAL_QUICK
DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
- // EA INVOKE_VIRTUAL_RANGE_QUICK
+ // F9 INVOKE_VIRTUAL_QUICK_RANGE
DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
- // EB IPUT_BOOLEAN_QUICK vA, vB, index
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // FA INVOKE_SUPER_QUICK
+ DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
- // EC IPUT_BYTE_QUICK vA, vB, index
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // FB INVOKE_SUPER_QUICK_RANGE
+ DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
- // ED IPUT_CHAR_QUICK vA, vB, index
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // FC IPUT_OBJECT_VOLATILE
+ DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_A | DF_REF_B | DF_IFIELD | DF_LVN,
- // EE IPUT_SHORT_QUICK vA, vB, index
- DF_UA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
+ // FD SGET_OBJECT_VOLATILE
+ DF_DA | DF_REF_A | DF_SFIELD | DF_CLINIT | DF_UMS,
- // EF IGET_BOOLEAN_QUICK vA, vB, index
- DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
-
- // F0 IGET_BYTE_QUICK vA, vB, index
- DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
-
- // F1 IGET_CHAR_QUICK vA, vB, index
- DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
-
- // F2 IGET_SHORT_QUICK vA, vB, index
- DF_DA | DF_UB | DF_NULL_CHK_B | DF_REF_B | DF_IFIELD | DF_LVN,
-
- // F3 UNUSED_F3
- DF_NOP,
-
- // F4 UNUSED_F4
- DF_NOP,
-
- // F5 UNUSED_F5
- DF_NOP,
-
- // F6 UNUSED_F6
- DF_NOP,
-
- // F7 UNUSED_F7
- DF_NOP,
-
- // F8 UNUSED_F8
- DF_NOP,
-
- // F9 UNUSED_F9
- DF_NOP,
-
- // FA UNUSED_FA
- DF_NOP,
-
- // FB UNUSED_FB
- DF_NOP,
-
- // FC UNUSED_FC
- DF_NOP,
-
- // FD UNUSED_FD
- DF_NOP,
-
- // FE UNUSED_FE
- DF_NOP,
+ // FE SPUT_OBJECT_VOLATILE
+ DF_UA | DF_REF_A | DF_SFIELD | DF_CLINIT | DF_UMS,
// FF UNUSED_FF
DF_NOP,
diff --git a/compiler/dex/mir_field_info.cc b/compiler/dex/mir_field_info.cc
index d2079a2..53afcad 100644
--- a/compiler/dex/mir_field_info.cc
+++ b/compiler/dex/mir_field_info.cc
@@ -35,9 +35,8 @@
DCHECK(field_infos != nullptr);
DCHECK_NE(count, 0u);
for (auto it = field_infos, end = field_infos + count; it != end; ++it) {
- MirIFieldLoweringInfo unresolved(it->field_idx_, it->MemAccessType(), it->IsQuickened());
- unresolved.field_offset_ = it->field_offset_;
- unresolved.CheckEquals(*it);
+ MirIFieldLoweringInfo unresolved(it->field_idx_, it->MemAccessType());
+ DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0);
}
}
@@ -50,30 +49,13 @@
hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit)));
Handle<mirror::Class> referrer_class(hs.NewHandle(
compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit)));
- const VerifiedMethod* const verified_method = mUnit->GetVerifiedMethod();
// Even if the referrer class is unresolved (i.e. we're compiling a method without class
// definition) we still want to resolve fields and record all available info.
+
for (auto it = field_infos, end = field_infos + count; it != end; ++it) {
- uint32_t field_idx;
- mirror::ArtField* resolved_field;
- if (!it->IsQuickened()) {
- field_idx = it->field_idx_;
- resolved_field = compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit,
- field_idx, false);
- } else {
- const auto mir_offset = it->field_idx_;
- // For quickened instructions, it->field_offset_ actually contains the mir offset.
- // We need to use the de-quickening info to get dex file / field idx
- auto* field_idx_ptr = verified_method->GetDequickenIndex(mir_offset);
- CHECK(field_idx_ptr != nullptr);
- field_idx = field_idx_ptr->index;
- StackHandleScope<1> hs2(soa.Self());
- auto h_dex_cache = hs2.NewHandle(compiler_driver->FindDexCache(field_idx_ptr->dex_file));
- resolved_field = compiler_driver->ResolveFieldWithDexFile(
- soa, h_dex_cache, class_loader, field_idx_ptr->dex_file, field_idx, false);
- // Since we don't have a valid field index we can't go slow path later.
- CHECK(resolved_field != nullptr);
- }
+ uint32_t field_idx = it->field_idx_;
+ mirror::ArtField* resolved_field =
+ compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, field_idx, false);
if (UNLIKELY(resolved_field == nullptr)) {
continue;
}
diff --git a/compiler/dex/mir_field_info.h b/compiler/dex/mir_field_info.h
index ca56958..98b2da8 100644
--- a/compiler/dex/mir_field_info.h
+++ b/compiler/dex/mir_field_info.h
@@ -19,8 +19,8 @@
#include "base/macros.h"
#include "dex_file.h"
-#include "dex_instruction_utils.h"
#include "offsets.h"
+#include "utils/dex_instruction_utils.h"
namespace art {
@@ -39,9 +39,6 @@
uint16_t FieldIndex() const {
return field_idx_;
}
- void SetFieldIndex(uint16_t field_idx) {
- field_idx_ = field_idx;
- }
bool IsStatic() const {
return (flags_ & kFlagIsStatic) != 0u;
@@ -54,9 +51,6 @@
const DexFile* DeclaringDexFile() const {
return declaring_dex_file_;
}
- void SetDeclaringDexFile(const DexFile* dex_file) {
- declaring_dex_file_ = dex_file;
- }
uint16_t DeclaringClassIndex() const {
return declaring_class_idx_;
@@ -70,35 +64,20 @@
return (flags_ & kFlagIsVolatile) != 0u;
}
- // IGET_QUICK, IGET_BYTE_QUICK, ...
- bool IsQuickened() const {
- return (flags_ & kFlagIsQuickened) != 0u;
- }
-
DexMemAccessType MemAccessType() const {
return static_cast<DexMemAccessType>((flags_ >> kBitMemAccessTypeBegin) & kMemAccessTypeMask);
}
- void CheckEquals(const MirFieldInfo& other) const {
- CHECK_EQ(field_idx_, other.field_idx_);
- CHECK_EQ(flags_, other.flags_);
- CHECK_EQ(declaring_field_idx_, other.declaring_field_idx_);
- CHECK_EQ(declaring_class_idx_, other.declaring_class_idx_);
- CHECK_EQ(declaring_dex_file_, other.declaring_dex_file_);
- }
-
protected:
enum {
kBitIsStatic = 0,
kBitIsVolatile,
- kBitIsQuickened,
kBitMemAccessTypeBegin,
kBitMemAccessTypeEnd = kBitMemAccessTypeBegin + 3, // 3 bits for raw type.
kFieldInfoBitEnd = kBitMemAccessTypeEnd
};
static constexpr uint16_t kFlagIsVolatile = 1u << kBitIsVolatile;
static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
- static constexpr uint16_t kFlagIsQuickened = 1u << kBitIsQuickened;
static constexpr uint16_t kMemAccessTypeMask = 7u;
static_assert((1u << (kBitMemAccessTypeEnd - kBitMemAccessTypeBegin)) - 1u == kMemAccessTypeMask,
"Invalid raw type mask");
@@ -138,10 +117,8 @@
LOCKS_EXCLUDED(Locks::mutator_lock_);
// Construct an unresolved instance field lowering info.
- explicit MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type, bool is_quickened)
- : MirFieldInfo(field_idx,
- kFlagIsVolatile | (is_quickened ? kFlagIsQuickened : 0u),
- type), // Without kFlagIsStatic.
+ explicit MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type)
+ : MirFieldInfo(field_idx, kFlagIsVolatile, type), // Without kFlagIsStatic.
field_offset_(0u) {
}
@@ -157,11 +134,6 @@
return field_offset_;
}
- void CheckEquals(const MirIFieldLoweringInfo& other) const {
- MirFieldInfo::CheckEquals(other);
- CHECK_EQ(field_offset_.Uint32Value(), other.field_offset_.Uint32Value());
- }
-
private:
enum {
kBitFastGet = kFieldInfoBitEnd,
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index f354a49..76b5e44 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -1673,6 +1673,12 @@
}
}
+const char* MIRGraph::GetShortyFromTargetIdx(int target_idx) {
+ // TODO: for inlining support, use current code unit.
+ const DexFile::MethodId& method_id = cu_->dex_file->GetMethodId(target_idx);
+ return cu_->dex_file->GetShorty(method_id.proto_idx_);
+}
+
const char* MIRGraph::GetShortyFromMethodReference(const MethodReference& target_method) {
const DexFile::MethodId& method_id =
target_method.dex_file->GetMethodId(target_method.dex_method_index);
@@ -1718,7 +1724,8 @@
* high-word loc for wide arguments. Also pull up any following
* MOVE_RESULT and incorporate it into the invoke.
*/
-CallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range) {
+CallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type,
+ bool is_range) {
CallInfo* info = static_cast<CallInfo*>(arena_->Alloc(sizeof(CallInfo),
kArenaAllocMisc));
MIR* move_result_mir = FindMoveResult(bb, mir);
@@ -1737,13 +1744,6 @@
info->opt_flags = mir->optimization_flags;
info->type = type;
info->is_range = is_range;
- if (IsInstructionQuickInvoke(mir->dalvikInsn.opcode)) {
- const auto& method_info = GetMethodLoweringInfo(mir);
- info->method_ref = method_info.GetTargetMethod();
- } else {
- info->method_ref = MethodReference(GetCurrentDexCompilationUnit()->GetDexFile(),
- mir->dalvikInsn.vB);
- }
info->index = mir->dalvikInsn.vB;
info->offset = mir->offset;
info->mir = mir;
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 3dae5b4..e5abd3b 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -504,7 +504,6 @@
int opt_flags;
InvokeType type;
uint32_t dex_idx;
- MethodReference method_ref;
uint32_t index; // Method idx for invokes, type idx for FilledNewArray.
uintptr_t direct_code;
uintptr_t direct_method;
@@ -688,7 +687,7 @@
void DoCacheMethodLoweringInfo();
- const MirMethodLoweringInfo& GetMethodLoweringInfo(MIR* mir) const {
+ const MirMethodLoweringInfo& GetMethodLoweringInfo(MIR* mir) {
DCHECK_LT(mir->meta.method_lowering_info, method_lowering_infos_.size());
return method_lowering_infos_[mir->meta.method_lowering_info];
}
@@ -1133,6 +1132,7 @@
std::string GetSSAName(int ssa_reg);
std::string GetSSANameWithConst(int ssa_reg, bool singles_only);
void GetBlockName(BasicBlock* bb, char* name);
+ const char* GetShortyFromTargetIdx(int);
const char* GetShortyFromMethodReference(const MethodReference& target_method);
void DumpMIRGraph();
CallInfo* NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range);
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
index 3d3d979..b234950 100644
--- a/compiler/dex/mir_method_info.cc
+++ b/compiler/dex/mir_method_info.cc
@@ -33,103 +33,51 @@
DCHECK(method_infos != nullptr);
DCHECK_NE(count, 0u);
for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
- MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType(), it->IsQuickened());
- unresolved.declaring_dex_file_ = it->declaring_dex_file_;
- unresolved.vtable_idx_ = it->vtable_idx_;
+ MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType());
if (it->target_dex_file_ != nullptr) {
unresolved.target_dex_file_ = it->target_dex_file_;
unresolved.target_method_idx_ = it->target_method_idx_;
}
- if (kIsDebugBuild) {
- unresolved.CheckEquals(*it);
- }
+ DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0);
}
}
// We're going to resolve methods and check access in a tight loop. It's better to hold
// the lock and needed references once than re-acquiring them again and again.
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<4> hs(soa.Self());
+ StackHandleScope<3> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit)));
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit)));
Handle<mirror::Class> referrer_class(hs.NewHandle(
compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit)));
- auto current_dex_cache(hs.NewHandle<mirror::DexCache>(nullptr));
// Even if the referrer class is unresolved (i.e. we're compiling a method without class
// definition) we still want to resolve methods and record all available info.
- const DexFile* const dex_file = mUnit->GetDexFile();
- const bool use_jit = Runtime::Current()->UseJit();
- const VerifiedMethod* const verified_method = mUnit->GetVerifiedMethod();
for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
- // For quickened invokes, the dex method idx is actually the mir offset.
- if (it->IsQuickened()) {
- const auto* dequicken_ref = verified_method->GetDequickenIndex(it->method_idx_);
- CHECK(dequicken_ref != nullptr);
- it->target_dex_file_ = dequicken_ref->dex_file;
- it->target_method_idx_ = dequicken_ref->index;
- }
// Remember devirtualized invoke target and set the called method to the default.
MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
+ it->target_dex_file_ = mUnit->GetDexFile();
+ it->target_method_idx_ = it->MethodIndex();
+
InvokeType invoke_type = it->GetInvokeType();
- mirror::ArtMethod* resolved_method = nullptr;
- if (!it->IsQuickened()) {
- it->target_dex_file_ = dex_file;
- it->target_method_idx_ = it->MethodIndex();
- current_dex_cache.Assign(dex_cache.Get());
- resolved_method = compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit,
- it->MethodIndex(), invoke_type);
- } else {
- // The method index is actually the dex PC in this case.
- // Calculate the proper dex file and target method idx.
- CHECK(use_jit);
- CHECK_EQ(invoke_type, kVirtual);
- // Don't devirt if we are in a different dex file since we can't have direct invokes in
- // another dex file unless we always put a direct / patch pointer.
- devirt_target = nullptr;
- current_dex_cache.Assign(
- Runtime::Current()->GetClassLinker()->FindDexCache(*it->target_dex_file_));
- CHECK(current_dex_cache.Get() != nullptr);
- DexCompilationUnit cu(
- mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(),
- *it->target_dex_file_, nullptr /* code_item not used */, 0u /* class_def_idx not used */,
- it->target_method_idx_, 0u /* access_flags not used */,
- nullptr /* verified_method not used */);
- resolved_method = compiler_driver->ResolveMethod(soa, current_dex_cache, class_loader, &cu,
- it->target_method_idx_, invoke_type, false);
- if (resolved_method != nullptr) {
- // Since this was a dequickened virtual, it is guaranteed to be resolved. However, it may be
- // resolved to an interface method. If this is the case then change the invoke type to
- // interface with the assumption that sharp_type will be kVirtual.
- if (resolved_method->GetInvokeType() == kInterface) {
- it->flags_ = (it->flags_ & ~(kInvokeTypeMask << kBitInvokeTypeBegin)) |
- (static_cast<uint16_t>(kInterface) << kBitInvokeTypeBegin);
- }
- }
- }
+ mirror::ArtMethod* resolved_method =
+ compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(),
+ invoke_type);
if (UNLIKELY(resolved_method == nullptr)) {
continue;
}
compiler_driver->GetResolvedMethodDexFileLocation(resolved_method,
&it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_);
- if (!it->IsQuickened()) {
- // For quickened invoke virtuals we may have desharpened to an interface method which
- // wont give us the right method index, in this case blindly dispatch or else we can't
- // compile the method. Converting the invoke to interface dispatch doesn't work since we
- // have no way to get the dex method index for quickened invoke virtuals in the interface
- // trampolines.
- it->vtable_idx_ =
- compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
- }
+ it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
- MethodReference target_method(it->target_dex_file_, it->target_method_idx_);
+ MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex());
int fast_path_flags = compiler_driver->IsFastInvoke(
- soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method,
- &invoke_type, &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
- const bool is_referrers_class = referrer_class.Get() == resolved_method->GetDeclaringClass();
- const bool is_class_initialized =
+ soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type,
+ &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
+ bool is_referrers_class = (referrer_class.Get() == resolved_method->GetDeclaringClass());
+ bool is_class_initialized =
compiler_driver->IsMethodsClassInitialized(referrer_class.Get(), resolved_method);
uint16_t other_flags = it->flags_ &
~(kFlagFastPath | kFlagClassIsInitialized | (kInvokeTypeMask << kBitSharpTypeBegin));
diff --git a/compiler/dex/mir_method_info.h b/compiler/dex/mir_method_info.h
index e131c96..08fb103 100644
--- a/compiler/dex/mir_method_info.h
+++ b/compiler/dex/mir_method_info.h
@@ -46,9 +46,6 @@
const DexFile* DeclaringDexFile() const {
return declaring_dex_file_;
}
- void SetDeclaringDexFile(const DexFile* dex_file) {
- declaring_dex_file_ = dex_file;
- }
uint16_t DeclaringClassIndex() const {
return declaring_class_idx_;
@@ -101,12 +98,11 @@
MirMethodLoweringInfo* method_infos, size_t count)
LOCKS_EXCLUDED(Locks::mutator_lock_);
- MirMethodLoweringInfo(uint16_t method_idx, InvokeType type, bool is_quickened)
+ MirMethodLoweringInfo(uint16_t method_idx, InvokeType type)
: MirMethodInfo(method_idx,
((type == kStatic) ? kFlagIsStatic : 0u) |
(static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
- (static_cast<uint16_t>(type) << kBitSharpTypeBegin) |
- (is_quickened ? kFlagQuickened : 0u)),
+ (static_cast<uint16_t>(type) << kBitSharpTypeBegin)),
direct_code_(0u),
direct_method_(0u),
target_dex_file_(nullptr),
@@ -135,11 +131,6 @@
return (flags_ & kFlagClassIsInitialized) != 0u;
}
- // Returns true iff the method invoke is INVOKE_VIRTUAL_QUICK or INVOKE_VIRTUAL_RANGE_QUICK.
- bool IsQuickened() const {
- return (flags_ & kFlagQuickened) != 0u;
- }
-
InvokeType GetInvokeType() const {
return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
}
@@ -155,9 +146,6 @@
uint16_t VTableIndex() const {
return vtable_idx_;
}
- void SetVTableIndex(uint16_t index) {
- vtable_idx_ = index;
- }
uintptr_t DirectCode() const {
return direct_code_;
@@ -171,20 +159,6 @@
return stats_flags_;
}
- void CheckEquals(const MirMethodLoweringInfo& info) const {
- CHECK_EQ(method_idx_, info.method_idx_);
- CHECK_EQ(flags_, info.flags_);
- CHECK_EQ(declaring_method_idx_, info.declaring_method_idx_);
- CHECK_EQ(declaring_class_idx_, info.declaring_class_idx_);
- CHECK_EQ(declaring_dex_file_, info.declaring_dex_file_);
- CHECK_EQ(direct_code_, info.direct_code_);
- CHECK_EQ(direct_method_, info.direct_method_);
- CHECK_EQ(target_dex_file_, info.target_dex_file_);
- CHECK_EQ(target_method_idx_, info.target_method_idx_);
- CHECK_EQ(vtable_idx_, info.vtable_idx_);
- CHECK_EQ(stats_flags_, info.stats_flags_);
- }
-
private:
enum {
kBitFastPath = kMethodInfoBitEnd,
@@ -194,14 +168,12 @@
kBitSharpTypeEnd = kBitSharpTypeBegin + 3, // 3 bits for sharp type.
kBitIsReferrersClass = kBitSharpTypeEnd,
kBitClassIsInitialized,
- kBitQuickened,
kMethodLoweringInfoBitEnd
};
static_assert(kMethodLoweringInfoBitEnd <= 16, "Too many flags");
static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
- static constexpr uint16_t kFlagQuickened = 1u << kBitQuickened;
static constexpr uint16_t kInvokeTypeMask = 7u;
static_assert((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
"assert invoke type bits failed");
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 93749e4..fd67d4e 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -1437,7 +1437,7 @@
nullptr /* code_item not used */, 0u /* class_def_idx not used */, target.dex_method_index,
0u /* access_flags not used */, nullptr /* verified_method not used */);
DexMemAccessType type = IGetOrIPutMemAccessType(iget_or_iput->dalvikInsn.opcode);
- MirIFieldLoweringInfo inlined_field_info(field_idx, type, false);
+ MirIFieldLoweringInfo inlined_field_info(field_idx, type);
MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, &inlined_unit, &inlined_field_info, 1u);
DCHECK(inlined_field_info.IsResolved());
diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc
index 9ce5ebb..be05b80 100644
--- a/compiler/dex/mir_optimization_test.cc
+++ b/compiler/dex/mir_optimization_test.cc
@@ -254,7 +254,7 @@
cu_.mir_graph->method_lowering_infos_.reserve(count);
for (size_t i = 0u; i != count; ++i) {
const MethodDef* def = &defs[i];
- MirMethodLoweringInfo method_info(def->method_idx, def->invoke_type, false);
+ MirMethodLoweringInfo method_info(def->method_idx, def->invoke_type);
if (def->declaring_dex_file != 0u) {
method_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
method_info.declaring_class_idx_ = def->declaring_class_idx;
@@ -407,7 +407,7 @@
cu_.mir_graph->ifield_lowering_infos_.reserve(count);
for (size_t i = 0u; i != count; ++i) {
const IFieldDef* def = &defs[i];
- MirIFieldLoweringInfo field_info(def->field_idx, def->type, false);
+ MirIFieldLoweringInfo field_info(def->field_idx, def->type);
if (def->declaring_dex_file != 0u) {
field_info.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file);
field_info.declaring_class_idx_ = def->declaring_class_idx;
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index f636e3b..7245853 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -427,7 +427,7 @@
InlineMethod intrinsic;
{
ReaderMutexLock mu(Thread::Current(), lock_);
- auto it = inline_methods_.find(info->method_ref.dex_method_index);
+ auto it = inline_methods_.find(info->index);
if (it == inline_methods_.end() || (it->second.flags & kInlineIntrinsic) == 0) {
return false;
}
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 6f68d1a..3c9b7a3 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -865,12 +865,7 @@
void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, Primitive::Type type,
RegLocation rl_dest, RegLocation rl_obj) {
const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
- if (kIsDebugBuild) {
- auto mem_access_type = IsInstructionIGetQuickOrIPutQuick(mir->dalvikInsn.opcode) ?
- IGetQuickOrIPutQuickMemAccessType(mir->dalvikInsn.opcode) :
- IGetMemAccessType(mir->dalvikInsn.opcode);
- DCHECK_EQ(mem_access_type, field_info.MemAccessType()) << mir->dalvikInsn.opcode;
- }
+ DCHECK_EQ(IGetMemAccessType(mir->dalvikInsn.opcode), field_info.MemAccessType());
cu_->compiler_driver->ProcessedInstanceField(field_info.FastGet());
if (!ForceSlowFieldPath(cu_) && field_info.FastGet()) {
RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
@@ -895,9 +890,6 @@
StoreValue(rl_dest, rl_result);
}
} else {
- if (field_info.DeclaringDexFile() != nullptr) {
- DCHECK_EQ(field_info.DeclaringDexFile(), cu_->dex_file);
- }
DCHECK(SizeMatchesTypeForEntrypoint(size, type));
QuickEntrypointEnum target;
switch (type) {
@@ -947,12 +939,7 @@
void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size,
RegLocation rl_src, RegLocation rl_obj) {
const MirIFieldLoweringInfo& field_info = mir_graph_->GetIFieldLoweringInfo(mir);
- if (kIsDebugBuild) {
- auto mem_access_type = IsInstructionIGetQuickOrIPutQuick(mir->dalvikInsn.opcode) ?
- IGetQuickOrIPutQuickMemAccessType(mir->dalvikInsn.opcode) :
- IPutMemAccessType(mir->dalvikInsn.opcode);
- DCHECK_EQ(mem_access_type, field_info.MemAccessType());
- }
+ DCHECK_EQ(IPutMemAccessType(mir->dalvikInsn.opcode), field_info.MemAccessType());
cu_->compiler_driver->ProcessedInstanceField(field_info.FastPut());
if (!ForceSlowFieldPath(cu_) && field_info.FastPut()) {
RegisterClass reg_class = RegClassForFieldLoadStore(size, field_info.IsVolatile());
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 040b07c..8e3df7c 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -863,12 +863,11 @@
RegLocation res;
if (info->result.location == kLocInvalid) {
// If result is unused, return a sink target based on type of invoke target.
- res = GetReturn(
- ShortyToRegClass(mir_graph_->GetShortyFromMethodReference(info->method_ref)[0]));
+ res = GetReturn(ShortyToRegClass(mir_graph_->GetShortyFromTargetIdx(info->index)[0]));
} else {
res = info->result;
DCHECK_EQ(LocToRegClass(res),
- ShortyToRegClass(mir_graph_->GetShortyFromMethodReference(info->method_ref)[0]));
+ ShortyToRegClass(mir_graph_->GetShortyFromTargetIdx(info->index)[0]));
}
return res;
}
@@ -877,12 +876,11 @@
RegLocation res;
if (info->result.location == kLocInvalid) {
// If result is unused, return a sink target based on type of invoke target.
- res = GetReturnWide(ShortyToRegClass(
- mir_graph_->GetShortyFromMethodReference(info->method_ref)[0]));
+ res = GetReturnWide(ShortyToRegClass(mir_graph_->GetShortyFromTargetIdx(info->index)[0]));
} else {
res = info->result;
DCHECK_EQ(LocToRegClass(res),
- ShortyToRegClass(mir_graph_->GetShortyFromMethodReference(info->method_ref)[0]));
+ ShortyToRegClass(mir_graph_->GetShortyFromTargetIdx(info->index)[0]));
}
return res;
}
@@ -1420,8 +1418,7 @@
void Mir2Lir::GenInvoke(CallInfo* info) {
DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
- const DexFile* dex_file = info->method_ref.dex_file;
- if (cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(dex_file)
+ if (cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file)
->GenIntrinsic(this, info)) {
return;
}
@@ -1431,7 +1428,7 @@
void Mir2Lir::GenInvokeNoInline(CallInfo* info) {
int call_state = 0;
LIR* null_ck;
- LIR** p_null_ck = nullptr;
+ LIR** p_null_ck = NULL;
NextCallInsn next_call_insn;
FlushAllRegs(); /* Everything to home location */
// Explicit register usage
@@ -1443,7 +1440,6 @@
info->type = method_info.GetSharpType();
bool fast_path = method_info.FastPath();
bool skip_this;
-
if (info->type == kInterface) {
next_call_insn = fast_path ? NextInterfaceCallInsn : NextInterfaceCallInsnWithAccessCheck;
skip_this = fast_path;
@@ -1473,8 +1469,7 @@
// Finish up any of the call sequence not interleaved in arg loading
while (call_state >= 0) {
call_state = next_call_insn(cu_, info, call_state, target_method, method_info.VTableIndex(),
- method_info.DirectCode(), method_info.DirectMethod(),
- original_type);
+ method_info.DirectCode(), method_info.DirectMethod(), original_type);
}
LIR* call_insn = GenCallInsn(method_info);
MarkSafepointPC(call_insn);
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 966a92d..34e5e25 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -540,7 +540,6 @@
GenMoveException(rl_dest);
break;
- case Instruction::RETURN_VOID_BARRIER:
case Instruction::RETURN_VOID:
if (((cu_->access_flags & kAccConstructor) != 0) &&
cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
@@ -791,12 +790,10 @@
GenArrayPut(opt_flags, kUnsignedByte, rl_src[1], rl_src[2], rl_src[0], 0, false);
break;
- case Instruction::IGET_OBJECT_QUICK:
case Instruction::IGET_OBJECT:
GenIGet(mir, opt_flags, kReference, Primitive::kPrimNot, rl_dest, rl_src[0]);
break;
- case Instruction::IGET_WIDE_QUICK:
case Instruction::IGET_WIDE:
// kPrimLong and kPrimDouble share the same entrypoints.
if (rl_dest.fp) {
@@ -806,7 +803,6 @@
}
break;
- case Instruction::IGET_QUICK:
case Instruction::IGET:
if (rl_dest.fp) {
GenIGet(mir, opt_flags, kSingle, Primitive::kPrimFloat, rl_dest, rl_src[0]);
@@ -815,54 +811,43 @@
}
break;
- case Instruction::IGET_CHAR_QUICK:
case Instruction::IGET_CHAR:
GenIGet(mir, opt_flags, kUnsignedHalf, Primitive::kPrimChar, rl_dest, rl_src[0]);
break;
- case Instruction::IGET_SHORT_QUICK:
case Instruction::IGET_SHORT:
GenIGet(mir, opt_flags, kSignedHalf, Primitive::kPrimShort, rl_dest, rl_src[0]);
break;
- case Instruction::IGET_BOOLEAN_QUICK:
case Instruction::IGET_BOOLEAN:
GenIGet(mir, opt_flags, kUnsignedByte, Primitive::kPrimBoolean, rl_dest, rl_src[0]);
break;
- case Instruction::IGET_BYTE_QUICK:
case Instruction::IGET_BYTE:
GenIGet(mir, opt_flags, kSignedByte, Primitive::kPrimByte, rl_dest, rl_src[0]);
break;
- case Instruction::IPUT_WIDE_QUICK:
case Instruction::IPUT_WIDE:
GenIPut(mir, opt_flags, rl_src[0].fp ? kDouble : k64, rl_src[0], rl_src[1]);
break;
- case Instruction::IPUT_OBJECT_QUICK:
case Instruction::IPUT_OBJECT:
GenIPut(mir, opt_flags, kReference, rl_src[0], rl_src[1]);
break;
- case Instruction::IPUT_QUICK:
case Instruction::IPUT:
GenIPut(mir, opt_flags, rl_src[0].fp ? kSingle : k32, rl_src[0], rl_src[1]);
break;
- case Instruction::IPUT_BYTE_QUICK:
- case Instruction::IPUT_BOOLEAN_QUICK:
case Instruction::IPUT_BYTE:
case Instruction::IPUT_BOOLEAN:
GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1]);
break;
- case Instruction::IPUT_CHAR_QUICK:
case Instruction::IPUT_CHAR:
GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1]);
break;
- case Instruction::IPUT_SHORT_QUICK:
case Instruction::IPUT_SHORT:
GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1]);
break;
@@ -936,12 +921,9 @@
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kDirect, true));
break;
- case Instruction::INVOKE_VIRTUAL_QUICK:
case Instruction::INVOKE_VIRTUAL:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, false));
break;
-
- case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
case Instruction::INVOKE_VIRTUAL_RANGE:
GenInvoke(mir_graph_->NewMemCallInfo(bb, mir, kVirtual, true));
break;
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index fcf4716..19c2a5a 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -542,11 +542,6 @@
void QuickCompiler::InitCompilationUnit(CompilationUnit& cu) const {
// Disable optimizations according to instruction set.
cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
- if (Runtime::Current()->UseJit()) {
- // Disable these optimizations for JIT until quickened byte codes are done being implemented.
- // TODO: Find a cleaner way to do this.
- cu.disable_opt |= 1u << kLocalValueNumbering;
- }
}
void QuickCompiler::Init() {
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index 51a3d84..4ff173d 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -66,10 +66,8 @@
// TODO: Investigate why are we doing the work again for this method and try to avoid it.
LOG(WARNING) << "Method processed more than once: "
<< PrettyMethod(ref.dex_method_index, *ref.dex_file);
- if (!Runtime::Current()->UseJit()) {
- DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size());
- DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size());
- }
+ DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size());
+ DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size());
DCHECK_EQ(it->second->GetDexGcMap().size(), verified_method->GetDexGcMap().size());
delete it->second;
verified_methods_.erase(it);
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 42d66be..21e965d 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -24,7 +24,6 @@
#include "base/stl_util.h"
#include "dex_file.h"
#include "dex_instruction-inl.h"
-#include "dex_instruction_utils.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
@@ -53,11 +52,6 @@
if (method_verifier->HasVirtualOrInterfaceInvokes()) {
verified_method->GenerateDevirtMap(method_verifier);
}
-
- // Only need dequicken info for JIT so far.
- if (Runtime::Current()->UseJit()) {
- verified_method->GenerateDequickenMap(method_verifier);
- }
}
if (method_verifier->HasCheckCasts()) {
@@ -71,12 +65,6 @@
return (it != devirt_map_.end()) ? &it->second : nullptr;
}
-const DexFileReference* VerifiedMethod::GetDequickenIndex(uint32_t dex_pc) const {
- DCHECK(Runtime::Current()->UseJit());
- auto it = dequicken_map_.find(dex_pc);
- return (it != dequicken_map_.end()) ? &it->second : nullptr;
-}
-
bool VerifiedMethod::IsSafeCast(uint32_t pc) const {
return std::binary_search(safe_cast_set_.begin(), safe_cast_set_.end(), pc);
}
@@ -194,7 +182,7 @@
*log2_max_gc_pc = i;
}
-void VerifiedMethod::GenerateDequickenMap(verifier::MethodVerifier* method_verifier) {
+void VerifiedMethod::GenerateDeQuickenMap(verifier::MethodVerifier* method_verifier) {
if (method_verifier->HasFailures()) {
return;
}
@@ -208,24 +196,13 @@
if (is_virtual_quick || is_range_quick) {
uint32_t dex_pc = inst->GetDexPc(insns);
verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
- mirror::ArtMethod* method =
- method_verifier->GetQuickInvokedMethod(inst, line, is_range_quick);
+ mirror::ArtMethod* method = method_verifier->GetQuickInvokedMethod(inst, line,
+ is_range_quick);
CHECK(method != nullptr);
// The verifier must know what the type of the object was or else we would have gotten a
// failure. Put the dex method index in the dequicken map since we need this to get number of
// arguments in the compiler.
- dequicken_map_.Put(dex_pc, DexFileReference(method->GetDexFile(),
- method->GetDexMethodIndex()));
- } else if (IsInstructionIGetQuickOrIPutQuick(inst->Opcode())) {
- uint32_t dex_pc = inst->GetDexPc(insns);
- verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
- mirror::ArtField* field = method_verifier->GetQuickFieldAccess(inst, line);
- CHECK(field != nullptr);
- // The verifier must know what the type of the field was or else we would have gotten a
- // failure. Put the dex field index in the dequicken map since we need this for lowering
- // in the compiler.
- // TODO: Putting a field index in a method reference is gross.
- dequicken_map_.Put(dex_pc, DexFileReference(field->GetDexFile(), field->GetDexFieldIndex()));
+ dequicken_map_.Put(dex_pc, method->ToMethodReference());
}
}
}
diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h
index 748bdcb..fe9dfd1 100644
--- a/compiler/dex/verified_method.h
+++ b/compiler/dex/verified_method.h
@@ -20,7 +20,6 @@
#include <vector>
#include "base/mutex.h"
-#include "dex_file.h"
#include "method_reference.h"
#include "safe_map.h"
@@ -40,9 +39,6 @@
// Devirtualization map type maps dex offset to concrete method reference.
typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;
- // Devirtualization map type maps dex offset to field / method idx.
- typedef SafeMap<uint32_t, DexFileReference> DequickenMap;
-
static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
~VerifiedMethod() = default;
@@ -62,10 +58,6 @@
// Returns the devirtualization target method, or nullptr if none.
const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;
- // Returns the dequicken field / method for a quick invoke / field get. Returns null if there is
- // no entry for that dex pc.
- const DexFileReference* GetDequickenIndex(uint32_t dex_pc) const;
-
// Returns true if the cast can statically be verified to be redundant
// by using the check-cast elision peephole optimization in the verifier.
bool IsSafeCast(uint32_t pc) const;
@@ -94,7 +86,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Generate dequickening map into dequicken_map_.
- void GenerateDequickenMap(verifier::MethodVerifier* method_verifier)
+ void GenerateDeQuickenMap(verifier::MethodVerifier* method_verifier)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Generate safe case set into safe_cast_set_.
@@ -103,9 +95,9 @@
std::vector<uint8_t> dex_gc_map_;
DevirtualizationMap devirt_map_;
- // Dequicken map is required for compiling quickened byte codes. The quicken maps from
- // dex PC to dex method index or dex field index based on the instruction.
- DequickenMap dequicken_map_;
+ // Dequicken map is required for having the compiler compiled quickened invokes. The quicken map
+ // enables us to get the dex method index so that we can get the required argument count.
+ DevirtualizationMap dequicken_map_;
SafeCastSet safe_cast_set_;
};
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index 2b78e38..b620969 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -19,7 +19,6 @@
#include "compiler_ir.h"
#include "dex/dataflow_iterator-inl.h"
#include "dex_flags.h"
-#include "driver/dex_compilation_unit.h"
namespace art {
@@ -260,8 +259,8 @@
if ((flags & Instruction::kInvoke) &&
(attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
DCHECK_EQ(next, 0);
- const auto& lowering_info = GetMethodLoweringInfo(mir);
- const char* shorty = GetShortyFromMethodReference(lowering_info.GetTargetMethod());
+ int target_idx = mir->dalvikInsn.vB;
+ const char* shorty = GetShortyFromTargetIdx(target_idx);
// Handle result type if floating point
if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
MIR* move_result_mir = FindMoveResult(bb, mir);