Minor nterp improvements.
Do not resolve primitive field types for iput*, sput*
before updating the interpreter cache.
Introduce and use `ArtMethod::IsStringConstructor(),
a convenience helper function where we avoid a read
barrier for checking if the declaring class is the
`String` class.
Change one `CHECK_LE()` to `DCHECK_LE()`.
Test: testrunner.py --host --interpreter
Change-Id: I17b0409cee5321e0ca389f053da1f767d2913d08
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index 2498319..a652d62 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -293,7 +293,7 @@
Instruction::Code opcode = inst->Opcode();
DCHECK(IsUint<8>(static_cast<std::underlying_type_t<Instruction::Code>>(opcode)));
uint8_t raw_invoke_type = kOpcodeInvokeTypes[opcode];
- CHECK_LE(raw_invoke_type, kMaxInvokeType);
+ DCHECK_LE(raw_invoke_type, kMaxInvokeType);
InvokeType invoke_type = static_cast<InvokeType>(raw_invoke_type);
// In release mode, this is just a simple load.
@@ -341,9 +341,7 @@
}
UpdateCache(self, dex_pc_ptr, result);
return result;
- } else if (resolved_method->GetDeclaringClass()->IsStringClass()
- && !resolved_method->IsStatic()
- && resolved_method->IsConstructor()) {
+ } else if (resolved_method->IsStringConstructor()) {
CHECK_NE(invoke_type, kSuper);
resolved_method = WellKnownClasses::StringInitToStringFactory(resolved_method);
// Or the result with 1 to notify to nterp this is a string init method. We
@@ -369,14 +367,14 @@
const Instruction* inst = Instruction::At(dex_pc_ptr);
uint16_t field_index = inst->VRegB_21c();
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
- bool is_put = IsInstructionSPut(inst->Opcode());
+ Instruction::Code opcode = inst->Opcode();
ArtField* resolved_field = ResolveFieldWithAccessChecks(
self,
class_linker,
field_index,
caller,
- /* is_static */ true,
- is_put,
+ /*is_static=*/ true,
+ /*is_put=*/ IsInstructionSPut(opcode),
resolve_field_type);
if (resolved_field == nullptr) {
@@ -399,11 +397,13 @@
// check for it.
return reinterpret_cast<size_t>(resolved_field) | 1;
} else {
- // Try to resolve the field type even if we were not requested to. Only if
- // the field type is successfully resolved can we update the cache. If we
+ // For sput-object, try to resolve the field type even if we were not requested to.
+ // Only if the field type is successfully resolved can we update the cache. If we
// fail to resolve the type, we clear the exception to keep interpreter
// semantics of not throwing when null is stored.
- if (is_put && resolve_field_type == 0 && resolved_field->ResolveType() == nullptr) {
+ if (opcode == Instruction::SPUT_OBJECT &&
+ resolve_field_type == 0 &&
+ resolved_field->ResolveType() == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
} else {
@@ -422,14 +422,14 @@
const Instruction* inst = Instruction::At(dex_pc_ptr);
uint16_t field_index = inst->VRegC_22c();
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
- bool is_put = IsInstructionIPut(inst->Opcode());
+ Instruction::Code opcode = inst->Opcode();
ArtField* resolved_field = ResolveFieldWithAccessChecks(
self,
class_linker,
field_index,
caller,
- /* is_static */ false,
- is_put,
+ /*is_static=*/ false,
+ /*is_put=*/ IsInstructionIPut(opcode),
resolve_field_type);
if (resolved_field == nullptr) {
DCHECK(self->IsExceptionPending());
@@ -440,11 +440,13 @@
// of volatile.
return -resolved_field->GetOffset().Uint32Value();
}
- // Try to resolve the field type even if we were not requested to. Only if
- // the field type is successfully resolved can we update the cache. If we
+ // For iput-object, try to resolve the field type even if we were not requested to.
+ // Only if the field type is successfully resolved can we update the cache. If we
// fail to resolve the type, we clear the exception to keep interpreter
// semantics of not throwing when null is stored.
- if (is_put && resolve_field_type == 0 && resolved_field->ResolveType() == nullptr) {
+ if (opcode == Instruction::IPUT_OBJECT &&
+ resolve_field_type == 0 &&
+ resolved_field->ResolveType() == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
} else {