Revert "Check FastInstance() early for special getters and setters."
This reverts commit 5dc5727261e87ba8a418e2d0e970c75f67e4ab79.
Change-Id: I3299c8ca5c3ce3f2de994bab61ea16a734f1de33
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 22466f0..661050f 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -127,19 +127,15 @@
}
}
-MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (!data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
+MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir,
+ OpSize size, bool long_or_double, bool is_object) {
+ int32_t field_offset;
+ bool is_volatile;
+ uint32_t field_idx = mir->dalvikInsn.vC;
+ bool fast_path = FastInstance(field_idx, false, &field_offset, &is_volatile);
+ if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) {
+ return NULL;
}
-
- OpSize size = static_cast<OpSize>(data.op_size);
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool long_or_double = (data.op_size == kLong);
- bool is_object = data.is_object;
-
- // TODO: Generate the method using only the data in special.
RegLocation rl_obj = mir_graph_->GetSrc(mir, 0);
LockLiveArgs(mir);
rl_obj = ArmMir2Lir::ArgLoc(rl_obj);
@@ -152,24 +148,19 @@
// Point of no return - no aborts after this
ArmMir2Lir::GenPrintLabel(mir);
rl_obj = LoadArg(rl_obj);
- uint32_t field_idx = mir->dalvikInsn.vC;
GenIGet(field_idx, mir->optimization_flags, size, rl_dest, rl_obj, long_or_double, is_object);
return GetNextMir(bb, mir);
}
-MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special) {
- // FastInstance() already checked by DexFileMethodInliner.
- const InlineIGetIPutData& data = special.d.ifield_data;
- if (!data.method_is_static || data.object_arg != 0) {
- return NULL; // The object is not "this" and has to be null-checked.
+MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir,
+ OpSize size, bool long_or_double, bool is_object) {
+ int32_t field_offset;
+ bool is_volatile;
+ uint32_t field_idx = mir->dalvikInsn.vC;
+ bool fast_path = FastInstance(field_idx, false, &field_offset, &is_volatile);
+ if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) {
+ return NULL;
}
-
- OpSize size = static_cast<OpSize>(data.op_size);
- DCHECK_NE(data.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
- bool long_or_double = (data.op_size == kLong);
- bool is_object = data.is_object;
-
- // TODO: Generate the method using only the data in special.
RegLocation rl_src;
RegLocation rl_obj;
LockLiveArgs(mir);
@@ -183,7 +174,7 @@
rl_src = ArmMir2Lir::ArgLoc(rl_src);
rl_obj = ArmMir2Lir::ArgLoc(rl_obj);
// Reject if source is split across registers & frame
- if (rl_src.location == kLocInvalid) {
+ if (rl_obj.location == kLocInvalid) {
ResetRegPool();
return NULL;
}
@@ -191,7 +182,6 @@
ArmMir2Lir::GenPrintLabel(mir);
rl_obj = LoadArg(rl_obj);
rl_src = LoadArg(rl_src);
- uint32_t field_idx = mir->dalvikInsn.vC;
GenIPut(field_idx, mir->optimization_flags, size, rl_src, rl_obj, long_or_double, is_object);
return GetNextMir(bb, mir);
}
@@ -229,6 +219,8 @@
*/
void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir,
const InlineMethod& special) {
+ // TODO: Generate the method using only the data in special. (Requires FastInstance() field
+ // validation in DexFileMethodInliner::AnalyseIGetMethod()/AnalyseIPutMethod().)
DCHECK(special.flags & kInlineSpecial);
current_dalvik_offset_ = mir->offset;
MIR* next_mir = NULL;
@@ -239,17 +231,30 @@
break;
case kInlineOpConst:
ArmMir2Lir::GenPrintLabel(mir);
- LoadConstant(rARM_RET0, static_cast<int>(special.d.data));
+ LoadConstant(rARM_RET0, special.data);
next_mir = GetNextMir(&bb, mir);
break;
- case kInlineOpIGet:
- next_mir = SpecialIGet(&bb, mir, special);
+ case kInlineOpIGet: {
+ InlineIGetIPutData data;
+ data.data = special.data;
+ OpSize op_size = static_cast<OpSize>(data.d.op_size);
+ DCHECK_NE(data.d.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
+ bool long_or_double = (data.d.op_size == kLong);
+ bool is_object = data.d.is_object;
+ next_mir = SpecialIGet(&bb, mir, op_size, long_or_double, is_object);
break;
- case kInlineOpIPut:
- next_mir = SpecialIPut(&bb, mir, special);
+ }
+ case kInlineOpIPut: {
+ InlineIGetIPutData data;
+ data.data = special.data;
+ OpSize op_size = static_cast<OpSize>(data.d.op_size);
+ DCHECK_NE(data.d.op_size, kDouble); // The inliner doesn't distinguish kDouble, uses kLong.
+ bool long_or_double = (data.d.op_size == kLong);
+ bool is_object = data.d.is_object;
+ next_mir = SpecialIPut(&bb, mir, op_size, long_or_double, is_object);
break;
+ }
case kInlineOpReturnArg:
- // TODO: Generate the method using only the data in special.
next_mir = SpecialIdentity(mir);
break;
default:
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 598da89..0ed4576 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -190,8 +190,8 @@
RegLocation LoadArg(RegLocation loc);
void LockLiveArgs(MIR* mir);
MIR* GetNextMir(BasicBlock** p_bb, MIR* mir);
- MIR* SpecialIGet(BasicBlock** bb, MIR* mir, const InlineMethod& special);
- MIR* SpecialIPut(BasicBlock** bb, MIR* mir, const InlineMethod& special);
+ MIR* SpecialIGet(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object);
+ MIR* SpecialIPut(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object);
MIR* SpecialIdentity(MIR* mir);
LIR* LoadFPConstantValue(int r_dest, int value);
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 0ad8abf..0937be3 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -24,27 +24,11 @@
#include "dex/mir_graph.h"
#include "dex_instruction.h"
#include "dex_instruction-inl.h"
-#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
#include "dex_file_method_inliner.h"
namespace art {
-namespace { // anonymous namespace
-
-constexpr uint8_t kIGetIPutOpSizes[] = {
- kWord, // IGET, IPUT
- kLong, // IGET_WIDE, IPUT_WIDE
- kWord, // IGET_OBJECT, IPUT_OBJECT
- kSignedByte, // IGET_BOOLEAN, IPUT_BOOLEAN
- kSignedByte, // IGET_BYTE, IPUT_BYTE
- kUnsignedHalf, // IGET_CHAR, IPUT_CHAR
- kSignedHalf, // IGET_SHORT, IPUT_SHORT
-};
-
-} // anonymous namespace
-
const uint32_t DexFileMethodInliner::kIndexUnresolved;
const char* const DexFileMethodInliner::kClassCacheNames[] = {
"Z", // kClassCacheBoolean
@@ -183,7 +167,7 @@
const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods[] = {
#define INTRINSIC(c, n, p, o, d) \
- { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineIntrinsic, { d } } }
+ { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineIntrinsic, d } }
INTRINSIC(JavaLangDouble, DoubleToRawLongBits, D_J, kIntrinsicDoubleCvt, 0),
INTRINSIC(JavaLangDouble, LongBitsToDouble, J_D, kIntrinsicDoubleCvt, 0),
@@ -264,58 +248,57 @@
DexFileMethodInliner::~DexFileMethodInliner() {
}
-bool DexFileMethodInliner::AnalyseMethodCode(verifier::MethodVerifier* verifier) {
+bool DexFileMethodInliner::AnalyseMethodCode(uint32_t method_idx,
+ const DexFile::CodeItem* code_item) {
// We currently support only plain return or 2-instruction methods.
- const DexFile::CodeItem* code_item = verifier->CodeItem();
DCHECK_NE(code_item->insns_size_in_code_units_, 0u);
const Instruction* instruction = Instruction::At(code_item->insns_);
Instruction::Code opcode = instruction->Opcode();
- InlineMethod method;
- bool success;
switch (opcode) {
case Instruction::RETURN_VOID:
- method.opcode = kInlineOpNop;
- method.flags = kInlineSpecial;
- method.d.data = 0u;
- success = true;
- break;
+ return AddInlineMethod(method_idx, kInlineOpNop, kInlineSpecial, 0);
case Instruction::RETURN:
case Instruction::RETURN_OBJECT:
+ return AnalyseReturnMethod(method_idx, code_item, kWord);
case Instruction::RETURN_WIDE:
- success = AnalyseReturnMethod(code_item, &method);
- break;
+ return AnalyseReturnMethod(method_idx, code_item, kLong);
case Instruction::CONST:
case Instruction::CONST_4:
case Instruction::CONST_16:
case Instruction::CONST_HIGH16:
// TODO: Support wide constants (RETURN_WIDE).
- success = AnalyseConstMethod(code_item, &method);
- break;
+ return AnalyseConstMethod(method_idx, code_item);
case Instruction::IGET:
+ return AnalyseIGetMethod(method_idx, code_item, kWord, false);
case Instruction::IGET_OBJECT:
+ return AnalyseIGetMethod(method_idx, code_item, kWord, true);
case Instruction::IGET_BOOLEAN:
case Instruction::IGET_BYTE:
+ return AnalyseIGetMethod(method_idx, code_item, kSignedByte, false);
case Instruction::IGET_CHAR:
+ return AnalyseIGetMethod(method_idx, code_item, kUnsignedHalf, false);
case Instruction::IGET_SHORT:
+ return AnalyseIGetMethod(method_idx, code_item, kSignedHalf, false);
case Instruction::IGET_WIDE:
- success = AnalyseIGetMethod(verifier, &method);
- break;
+ return AnalyseIGetMethod(method_idx, code_item, kLong, false);
case Instruction::IPUT:
+ return AnalyseIPutMethod(method_idx, code_item, kWord, false);
case Instruction::IPUT_OBJECT:
+ return AnalyseIPutMethod(method_idx, code_item, kWord, true);
case Instruction::IPUT_BOOLEAN:
case Instruction::IPUT_BYTE:
+ return AnalyseIPutMethod(method_idx, code_item, kSignedByte, false);
case Instruction::IPUT_CHAR:
+ return AnalyseIPutMethod(method_idx, code_item, kUnsignedHalf, false);
case Instruction::IPUT_SHORT:
+ return AnalyseIPutMethod(method_idx, code_item, kSignedHalf, false);
case Instruction::IPUT_WIDE:
- success = AnalyseIPutMethod(verifier, &method);
- break;
+ return AnalyseIPutMethod(method_idx, code_item, kLong, false);
default:
- success = false;
- break;
- }
- return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method);
+ return false;
+ }
}
bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) {
@@ -340,13 +323,13 @@
case kIntrinsicFloatCvt:
return backend->GenInlinedFloatCvt(info);
case kIntrinsicReverseBytes:
- return backend->GenInlinedReverseBytes(info, static_cast<OpSize>(intrinsic.d.data));
+ return backend->GenInlinedReverseBytes(info, static_cast<OpSize>(intrinsic.data));
case kIntrinsicAbsInt:
return backend->GenInlinedAbsInt(info);
case kIntrinsicAbsLong:
return backend->GenInlinedAbsLong(info);
case kIntrinsicMinMaxInt:
- return backend->GenInlinedMinMaxInt(info, intrinsic.d.data & kIntrinsicFlagMin);
+ return backend->GenInlinedMinMaxInt(info, intrinsic.data & kIntrinsicFlagMin);
case kIntrinsicSqrt:
return backend->GenInlinedSqrt(info);
case kIntrinsicCharAt:
@@ -354,27 +337,26 @@
case kIntrinsicCompareTo:
return backend->GenInlinedStringCompareTo(info);
case kIntrinsicIsEmptyOrLength:
- return backend->GenInlinedStringIsEmptyOrLength(
- info, intrinsic.d.data & kIntrinsicFlagIsEmpty);
+ return backend->GenInlinedStringIsEmptyOrLength(info, intrinsic.data & kIntrinsicFlagIsEmpty);
case kIntrinsicIndexOf:
- return backend->GenInlinedIndexOf(info, intrinsic.d.data & kIntrinsicFlagBase0);
+ return backend->GenInlinedIndexOf(info, intrinsic.data & kIntrinsicFlagBase0);
case kIntrinsicCurrentThread:
return backend->GenInlinedCurrentThread(info);
case kIntrinsicPeek:
- return backend->GenInlinedPeek(info, static_cast<OpSize>(intrinsic.d.data));
+ return backend->GenInlinedPeek(info, static_cast<OpSize>(intrinsic.data));
case kIntrinsicPoke:
- return backend->GenInlinedPoke(info, static_cast<OpSize>(intrinsic.d.data));
+ return backend->GenInlinedPoke(info, static_cast<OpSize>(intrinsic.data));
case kIntrinsicCas:
- return backend->GenInlinedCas(info, intrinsic.d.data & kIntrinsicFlagIsLong,
- intrinsic.d.data & kIntrinsicFlagIsObject);
+ return backend->GenInlinedCas(info, intrinsic.data & kIntrinsicFlagIsLong,
+ intrinsic.data & kIntrinsicFlagIsObject);
case kIntrinsicUnsafeGet:
- return backend->GenInlinedUnsafeGet(info, intrinsic.d.data & kIntrinsicFlagIsLong,
- intrinsic.d.data & kIntrinsicFlagIsVolatile);
+ return backend->GenInlinedUnsafeGet(info, intrinsic.data & kIntrinsicFlagIsLong,
+ intrinsic.data & kIntrinsicFlagIsVolatile);
case kIntrinsicUnsafePut:
- return backend->GenInlinedUnsafePut(info, intrinsic.d.data & kIntrinsicFlagIsLong,
- intrinsic.d.data & kIntrinsicFlagIsObject,
- intrinsic.d.data & kIntrinsicFlagIsVolatile,
- intrinsic.d.data & kIntrinsicFlagIsOrdered);
+ return backend->GenInlinedUnsafePut(info, intrinsic.data & kIntrinsicFlagIsLong,
+ intrinsic.data & kIntrinsicFlagIsObject,
+ intrinsic.data & kIntrinsicFlagIsVolatile,
+ intrinsic.data & kIntrinsicFlagIsOrdered);
default:
LOG(FATAL) << "Unexpected intrinsic opcode: " << intrinsic.opcode;
return false; // avoid warning "control reaches end of non-void function"
@@ -523,10 +505,12 @@
dex_file_ = dex_file;
}
-bool DexFileMethodInliner::AddInlineMethod(int32_t method_idx, const InlineMethod& method) {
+bool DexFileMethodInliner::AddInlineMethod(int32_t method_idx, InlineMethodOpcode opcode,
+ InlineMethodFlags flags, uint32_t data) {
WriterMutexLock mu(Thread::Current(), lock_);
if (LIKELY(inline_methods_.find(method_idx) == inline_methods_.end())) {
- inline_methods_.Put(method_idx, method);
+ InlineMethod im = {opcode, flags, data};
+ inline_methods_.Put(method_idx, im);
return true;
} else {
if (PrettyMethod(method_idx, *dex_file_) == "int java.lang.String.length()") {
@@ -538,30 +522,26 @@
}
}
-bool DexFileMethodInliner::AnalyseReturnMethod(const DexFile::CodeItem* code_item,
- InlineMethod* result) {
+bool DexFileMethodInliner::AnalyseReturnMethod(int32_t method_idx,
+ const DexFile::CodeItem* code_item, OpSize size) {
const Instruction* return_instruction = Instruction::At(code_item->insns_);
- Instruction::Code return_opcode = return_instruction->Opcode();
- uint16_t size = (return_opcode == Instruction::RETURN_WIDE) ? kLong : kWord;
- uint16_t is_object = (return_opcode == Instruction::RETURN_OBJECT) ? 1u : 0u;
+ if (return_instruction->Opcode() == Instruction::RETURN_VOID) {
+ return AddInlineMethod(method_idx, kInlineOpNop, kInlineSpecial, 0);
+ }
uint32_t reg = return_instruction->VRegA_11x();
uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
DCHECK_GE(reg, arg_start);
DCHECK_LT(size == kLong ? reg + 1 : reg, code_item->registers_size_);
- result->opcode = kInlineOpReturnArg;
- result->flags = kInlineSpecial;
- InlineReturnArgData* data = &result->d.return_data;
- data->arg = reg - arg_start;
- data->op_size = size;
- data->is_object = is_object;
- data->reserved = 0u;
- data->reserved2 = 0u;
- return true;
+ InlineReturnArgData data;
+ data.d.arg = reg - arg_start;
+ data.d.op_size = size;
+ data.d.reserved = 0;
+ return AddInlineMethod(method_idx, kInlineOpReturnArg, kInlineSpecial, data.data);
}
-bool DexFileMethodInliner::AnalyseConstMethod(const DexFile::CodeItem* code_item,
- InlineMethod* result) {
+bool DexFileMethodInliner::AnalyseConstMethod(int32_t method_idx,
+ const DexFile::CodeItem* code_item) {
const Instruction* instruction = Instruction::At(code_item->insns_);
const Instruction* return_instruction = instruction->Next();
Instruction::Code return_opcode = return_instruction->Opcode();
@@ -586,20 +566,13 @@
if (return_opcode == Instruction::RETURN_OBJECT && vB != 0) {
return false; // Returning non-null reference constant?
}
- result->opcode = kInlineOpConst;
- result->flags = kInlineSpecial;
- result->d.data = static_cast<uint64_t>(vB);
- return true;
+ return AddInlineMethod(method_idx, kInlineOpConst, kInlineSpecial, vB);
}
-bool DexFileMethodInliner::AnalyseIGetMethod(verifier::MethodVerifier* verifier,
- InlineMethod* result) {
- const DexFile::CodeItem* code_item = verifier->CodeItem();
+bool DexFileMethodInliner::AnalyseIGetMethod(int32_t method_idx, const DexFile::CodeItem* code_item,
+ OpSize size, bool is_object) {
const Instruction* instruction = Instruction::At(code_item->insns_);
Instruction::Code opcode = instruction->Opcode();
- DCHECK_LT(static_cast<size_t>(opcode - Instruction::IGET), arraysize(kIGetIPutOpSizes));
- uint16_t size = kIGetIPutOpSizes[opcode - Instruction::IGET];
-
const Instruction* return_instruction = instruction->Next();
Instruction::Code return_opcode = return_instruction->Opcode();
if (!(return_opcode == Instruction::RETURN && size != kLong) &&
@@ -612,74 +585,61 @@
DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1 : return_reg,
code_item->registers_size_);
- uint32_t dst_reg = instruction->VRegA_22c();
- uint32_t object_reg = instruction->VRegB_22c();
- uint32_t field_idx = instruction->VRegC_22c();
+ uint32_t vA, vB, vC;
+ uint64_t dummy_wide;
+ instruction->Decode(vA, vB, dummy_wide, vC, nullptr);
uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
- DCHECK_GE(object_reg, arg_start);
- DCHECK_LT(object_reg, code_item->registers_size_);
- DCHECK_LT(size == kLong ? dst_reg + 1 : dst_reg, code_item->registers_size_);
- if (dst_reg != return_reg) {
- return false; // Not returning the value retrieved by IGET?
+ DCHECK_GE(vB, arg_start);
+ DCHECK_LT(vB, code_item->registers_size_);
+ DCHECK_LT(size == kLong ? vA + 1 : vA, code_item->registers_size_);
+ if (vA != return_reg) {
+ return false; // Not returning the value retrieved by iget?
}
- if (!CompilerDriver::ComputeSpecialAccessorInfo(field_idx, false, verifier,
- &result->d.ifield_data)) {
- return false;
- }
+ // TODO: Check that the field is FastInstance().
- result->opcode = kInlineOpIGet;
- result->flags = kInlineSpecial;
- InlineIGetIPutData* data = &result->d.ifield_data;
- data->op_size = size;
- data->is_object = (opcode == Instruction::IGET_OBJECT) ? 1u : 0u;
- data->object_arg = object_reg - arg_start; // Allow IGET on any register, not just "this".
- data->src_arg = 0;
- data->reserved = 0;
- return true;
+ InlineIGetIPutData data;
+ data.d.field = vC;
+ data.d.op_size = size;
+ data.d.is_object = is_object;
+ data.d.object_arg = vB - arg_start; // Allow iget on any register, not just "this"
+ data.d.src_arg = 0;
+ data.d.reserved = 0;
+ return AddInlineMethod(method_idx, kInlineOpIGet, kInlineSpecial, data.data);
}
-bool DexFileMethodInliner::AnalyseIPutMethod(verifier::MethodVerifier* verifier,
- InlineMethod* result) {
- const DexFile::CodeItem* code_item = verifier->CodeItem();
+bool DexFileMethodInliner::AnalyseIPutMethod(int32_t method_idx, const DexFile::CodeItem* code_item,
+ OpSize size, bool is_object) {
const Instruction* instruction = Instruction::At(code_item->insns_);
- Instruction::Code opcode = instruction->Opcode();
- DCHECK_LT(static_cast<size_t>(opcode - Instruction::IPUT), arraysize(kIGetIPutOpSizes));
- uint16_t size = kIGetIPutOpSizes[opcode - Instruction::IPUT];
-
const Instruction* return_instruction = instruction->Next();
if (return_instruction->Opcode() != Instruction::RETURN_VOID) {
// TODO: Support returning an argument.
// This is needed by builder classes and generated accessor setters.
// builder.setX(value): iput value, this, fieldX; return-object this;
// object.access$nnn(value): iput value, this, fieldX; return value;
- // Use InlineIGetIPutData::reserved to hold the information.
+ // Use InlineIGetIPutData::d::reserved to hold the information.
return false;
}
- uint32_t src_reg = instruction->VRegA_22c();
- uint32_t object_reg = instruction->VRegB_22c();
- uint32_t field_idx = instruction->VRegC_22c();
+ uint32_t vA, vB, vC;
+ uint64_t dummy_wide;
+ instruction->Decode(vA, vB, dummy_wide, vC, nullptr);
uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
- DCHECK_GE(object_reg, arg_start);
- DCHECK_LT(object_reg, code_item->registers_size_);
- DCHECK_GE(src_reg, arg_start);
- DCHECK_LT(size == kLong ? src_reg + 1 : src_reg, code_item->registers_size_);
+ DCHECK_GE(vB, arg_start);
+ DCHECK_GE(vA, arg_start);
+ DCHECK_LT(vB, code_item->registers_size_);
+ DCHECK_LT(size == kLong ? vA + 1 : vA, code_item->registers_size_);
- if (!CompilerDriver::ComputeSpecialAccessorInfo(field_idx, true, verifier,
- &result->d.ifield_data)) {
- return false;
- }
+ // TODO: Check that the field (vC) is FastInstance().
- result->opcode = kInlineOpIPut;
- result->flags = kInlineSpecial;
- InlineIGetIPutData* data = &result->d.ifield_data;
- data->op_size = size;
- data->is_object = (opcode == Instruction::IPUT_OBJECT) ? 1u : 0u;
- data->object_arg = object_reg - arg_start; // Allow IPUT on any register, not just "this".
- data->src_arg = src_reg - arg_start;
- data->reserved = 0;
- return true;
+ InlineIGetIPutData data;
+ data.d.field = vC;
+ data.d.op_size = size;
+ data.d.is_object = is_object;
+ data.d.object_arg = vB - arg_start; // Allow iput on any register, not just "this"
+ data.d.src_arg = vA - arg_start;
+ data.d.reserved = 0;
+ return AddInlineMethod(method_idx, kInlineOpIPut, kInlineSpecial, data.data);
}
} // namespace art
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index fe0824c..6e81303 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -27,10 +27,6 @@
namespace art {
-namespace verifier {
-class MethodVerifier;
-} // namespace verifier
-
class CallInfo;
class Mir2Lir;
@@ -66,7 +62,13 @@
kInlineSpecial = 0x0002,
};
-// IntrinsicFlags are stored in InlineMethod::d::raw_data
+struct InlineMethod {
+ InlineMethodOpcode opcode;
+ InlineMethodFlags flags;
+ uint32_t data;
+};
+
+// IntrinsicFlags are stored in InlineMethod::data
enum IntrinsicFlags {
kIntrinsicFlagNone = 0,
@@ -95,37 +97,28 @@
COMPILE_ASSERT(kWord < 8 && kLong < 8 && kSingle < 8 && kDouble < 8 && kUnsignedHalf < 8 &&
kSignedHalf < 8 && kUnsignedByte < 8 && kSignedByte < 8, op_size_field_too_narrow);
-struct InlineIGetIPutData {
- uint16_t op_size : 3; // OpSize
- uint16_t is_object : 1;
- uint16_t object_arg : 4;
- uint16_t src_arg : 4; // iput only
- uint16_t method_is_static : 1;
- uint16_t reserved : 3;
- uint16_t field_idx;
- uint32_t is_volatile : 1;
- uint32_t field_offset : 31;
-};
-COMPILE_ASSERT(sizeof(InlineIGetIPutData) == sizeof(uint64_t), InvalidSizeOfInlineIGetIPutData);
-
-struct InlineReturnArgData {
- uint16_t arg;
- uint16_t op_size : 3; // OpSize
- uint16_t is_object : 1;
- uint16_t reserved : 12;
- uint32_t reserved2;
-};
-COMPILE_ASSERT(sizeof(InlineReturnArgData) == sizeof(uint64_t), InvalidSizeOfInlineReturnArgData);
-
-struct InlineMethod {
- InlineMethodOpcode opcode;
- InlineMethodFlags flags;
- union {
- uint64_t data;
- InlineIGetIPutData ifield_data;
- InlineReturnArgData return_data;
+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.
@@ -151,8 +144,8 @@
* @param method_idx the index of the inlining candidate.
* @param code_item a previously verified code item of the method.
*/
- bool AnalyseMethodCode(verifier::MethodVerifier* verifier)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_);
+ 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.
@@ -376,14 +369,17 @@
friend class DexFileToMethodInlinerMap;
- bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_);
+ bool AddInlineMethod(int32_t method_idx, InlineMethodOpcode opcode,
+ InlineMethodFlags flags, uint32_t data) LOCKS_EXCLUDED(lock_);
- static bool AnalyseReturnMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
- static bool AnalyseConstMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
- static bool AnalyseIGetMethod(verifier::MethodVerifier* verifier, InlineMethod* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static bool AnalyseIPutMethod(verifier::MethodVerifier* verifier, InlineMethod* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_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_;
/*
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5b9d66c..9f48351 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -29,7 +29,6 @@
#include "dex_file-inl.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
-#include "dex/quick/dex_file_method_inliner.h"
#include "jni_internal.h"
#include "object_utils.h"
#include "runtime.h"
@@ -50,7 +49,6 @@
#include "thread_pool.h"
#include "trampolines/trampoline_compiler.h"
#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
#if defined(ART_USE_PORTABLE_COMPILER)
#include "elf_writer_mclinker.h"
@@ -997,30 +995,6 @@
class_loader, NULL, type);
}
-bool CompilerDriver::ComputeSpecialAccessorInfo(uint32_t field_idx, bool is_put,
- verifier::MethodVerifier* verifier,
- InlineIGetIPutData* result) {
- mirror::DexCache* dex_cache = verifier->GetDexCache();
- uint32_t method_idx = verifier->GetMethodReference().dex_method_index;
- mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
- mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
- if (method == nullptr || field == nullptr) {
- return false;
- }
- mirror::Class* method_class = method->GetDeclaringClass();
- mirror::Class* field_class = field->GetDeclaringClass();
- if (!method_class->CanAccessResolvedField(field_class, field, dex_cache, field_idx) ||
- (is_put && field->IsFinal() && method_class != field_class)) {
- return false;
- }
- DCHECK_GE(field->GetOffset().Int32Value(), 0);
- result->method_is_static = method->IsStatic();
- result->field_idx = field_idx;
- result->field_offset = field->GetOffset().Int32Value();
- result->is_volatile = field->IsVolatile();
- return true;
-}
-
bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit,
bool is_put, int* field_offset, bool* is_volatile) {
ScopedObjectAccess soa(Thread::Current());
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index ea43e4f..4307212 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -38,15 +38,10 @@
namespace art {
-namespace verifier {
-class MethodVerifier;
-} // namespace verifier
-
class AOTCompilationStats;
class ParallelCompilationManager;
class DexCompilationUnit;
class DexFileToMethodInlinerMap;
-class InlineIGetIPutData;
class OatWriter;
class TimingLogger;
class VerificationResults;
@@ -199,13 +194,6 @@
bool* is_type_initialized, bool* use_direct_type_ptr,
uintptr_t* direct_type_ptr);
- // Can we fast path instance field access in a verified accessor?
- // If yes, computes field's offset and volatility and whether the method is static or not.
- static bool ComputeSpecialAccessorInfo(uint32_t field_idx, bool is_put,
- verifier::MethodVerifier* verifier,
- InlineIGetIPutData* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
// Can we fast path instance field access? Computes field's offset and volatility.
bool ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put,
int* field_offset, bool* is_volatile)
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 90eea5e..5ac01f2 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -364,7 +364,7 @@
if (result && method_inliner_map_ != nullptr) {
MethodReference ref = verifier->GetMethodReference();
method_inliner_map_->GetMethodInliner(ref.dex_file)
- ->AnalyseMethodCode(verifier);
+ ->AnalyseMethodCode(ref.dex_method_index, verifier->CodeItem());
}
return result;
}
diff --git a/runtime/common_test.h b/runtime/common_test.h
index daa2ff1..ddaf52a 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -677,7 +677,7 @@
if (result && method_inliner_map_ != nullptr) {
MethodReference ref = verifier->GetMethodReference();
method_inliner_map_->GetMethodInliner(ref.dex_file)
- ->AnalyseMethodCode(verifier);
+ ->AnalyseMethodCode(ref.dex_method_index, verifier->CodeItem());
}
return result;
}