summaryrefslogtreecommitdiff
path: root/runtime/common_throws.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/common_throws.cc')
-rw-r--r--runtime/common_throws.cc40
1 files changed, 28 insertions, 12 deletions
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 99732c64ab..e1da23c208 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -402,6 +402,16 @@ void ThrowNullPointerExceptionForMethodAccess(ArtMethod* method,
dex_file, type);
}
+static bool IsValidReadBarrierImplicitCheck(uintptr_t addr) {
+ DCHECK(kEmitCompilerReadBarrier);
+ uint32_t monitor_offset = mirror::Object::MonitorOffset().Uint32Value();
+ if (kUseBakerReadBarrier && (kRuntimeISA == kX86 || kRuntimeISA == kX86_64)) {
+ constexpr uint32_t gray_byte_position = LockWord::kReadBarrierStateShift / kBitsPerByte;
+ monitor_offset += gray_byte_position;
+ }
+ return addr == monitor_offset;
+}
+
static bool IsValidImplicitCheck(uintptr_t addr, ArtMethod* method, const Instruction& instr)
SHARED_REQUIRES(Locks::mutator_lock_) {
if (!CanDoImplicitNullCheckOn(addr)) {
@@ -424,9 +434,13 @@ static bool IsValidImplicitCheck(uintptr_t addr, ArtMethod* method, const Instru
return true;
}
+ case Instruction::IGET_OBJECT:
+ if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) {
+ return true;
+ }
+ FALLTHROUGH_INTENDED;
case Instruction::IGET:
case Instruction::IGET_WIDE:
- case Instruction::IGET_OBJECT:
case Instruction::IGET_BOOLEAN:
case Instruction::IGET_BYTE:
case Instruction::IGET_CHAR:
@@ -440,18 +454,20 @@ static bool IsValidImplicitCheck(uintptr_t addr, ArtMethod* method, const Instru
case Instruction::IPUT_SHORT: {
ArtField* field =
Runtime::Current()->GetClassLinker()->ResolveField(instr.VRegC_22c(), method, false);
- return (addr == 0) ||
- (addr == field->GetOffset().Uint32Value()) ||
- (kEmitCompilerReadBarrier && (addr == mirror::Object::MonitorOffset().Uint32Value()));
+ return (addr == 0) || (addr == field->GetOffset().Uint32Value());
}
+ case Instruction::IGET_OBJECT_QUICK:
+ if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) {
+ return true;
+ }
+ FALLTHROUGH_INTENDED;
case Instruction::IGET_QUICK:
case Instruction::IGET_BOOLEAN_QUICK:
case Instruction::IGET_BYTE_QUICK:
case Instruction::IGET_CHAR_QUICK:
case Instruction::IGET_SHORT_QUICK:
case Instruction::IGET_WIDE_QUICK:
- case Instruction::IGET_OBJECT_QUICK:
case Instruction::IPUT_QUICK:
case Instruction::IPUT_BOOLEAN_QUICK:
case Instruction::IPUT_BYTE_QUICK:
@@ -459,14 +475,16 @@ static bool IsValidImplicitCheck(uintptr_t addr, ArtMethod* method, const Instru
case Instruction::IPUT_SHORT_QUICK:
case Instruction::IPUT_WIDE_QUICK:
case Instruction::IPUT_OBJECT_QUICK: {
- return (addr == 0u) ||
- (addr == instr.VRegC_22c()) ||
- (kEmitCompilerReadBarrier && (addr == mirror::Object::MonitorOffset().Uint32Value()));
+ return (addr == 0u) || (addr == instr.VRegC_22c());
}
+ case Instruction::AGET_OBJECT:
+ if (kEmitCompilerReadBarrier && IsValidReadBarrierImplicitCheck(addr)) {
+ return true;
+ }
+ FALLTHROUGH_INTENDED;
case Instruction::AGET:
case Instruction::AGET_WIDE:
- case Instruction::AGET_OBJECT:
case Instruction::AGET_BOOLEAN:
case Instruction::AGET_BYTE:
case Instruction::AGET_CHAR:
@@ -482,9 +500,7 @@ static bool IsValidImplicitCheck(uintptr_t addr, ArtMethod* method, const Instru
case Instruction::ARRAY_LENGTH: {
// The length access should crash. We currently do not do implicit checks on
// the array access itself.
- return (addr == 0u) ||
- (addr == mirror::Array::LengthOffset().Uint32Value()) ||
- (kEmitCompilerReadBarrier && (addr == mirror::Object::MonitorOffset().Uint32Value()));
+ return (addr == 0u) || (addr == mirror::Array::LengthOffset().Uint32Value());
}
default: {