Extend the InvokeRuntime() changes to mips.
Also fix the side effects for <Static/Instance>Field<Get/Set>.
Test: test-art-target
Change-Id: Ia4284ccd9d0c88210eaa4458f74728c805e2e076
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index e0de03b..cec3ca1 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -170,14 +170,10 @@
locations->InAt(1),
Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
Primitive::kPrimInt);
- uint32_t entry_point_offset = instruction_->AsBoundsCheck()->IsStringCharAt()
- ? QUICK_ENTRY_POINT(pThrowStringBounds)
- : QUICK_ENTRY_POINT(pThrowArrayBounds);
- mips_codegen->InvokeRuntime(entry_point_offset,
- instruction_,
- instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickThrowArrayBounds));
+ QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt()
+ ? kQuickThrowStringBounds
+ : kQuickThrowArrayBounds;
+ mips_codegen->InvokeRuntime(entrypoint, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowStringBounds, void, int32_t, int32_t>();
CheckEntrypointTypes<kQuickThrowArrayBounds, void, int32_t, int32_t>();
}
@@ -201,11 +197,7 @@
// Live registers will be restored in the catch block if caught.
SaveLiveRegisters(codegen, instruction_->GetLocations());
}
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowDivZero),
- instruction_,
- instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickThrowDivZero));
+ mips_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -237,12 +229,9 @@
InvokeRuntimeCallingConvention calling_convention;
__ LoadConst32(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
- int32_t entry_point_offset = do_clinit_ ? QUICK_ENTRY_POINT(pInitializeStaticStorage)
- : QUICK_ENTRY_POINT(pInitializeType);
- bool direct = do_clinit_ ? IsDirectEntrypoint(kQuickInitializeStaticStorage)
- : IsDirectEntrypoint(kQuickInitializeType);
-
- mips_codegen->InvokeRuntime(entry_point_offset, at_, dex_pc_, this, direct);
+ QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
+ : kQuickInitializeType;
+ mips_codegen->InvokeRuntime(entrypoint, at_, dex_pc_, this);
if (do_clinit_) {
CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, uint32_t>();
} else {
@@ -295,11 +284,7 @@
InvokeRuntimeCallingConvention calling_convention;
const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
__ LoadConst32(calling_convention.GetRegisterAt(0), string_index);
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pResolveString),
- instruction_,
- instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickResolveString));
+ mips_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
Primitive::Type type = instruction_->GetType();
mips_codegen->MoveLocation(locations->Out(),
@@ -327,11 +312,10 @@
// Live registers will be restored in the catch block if caught.
SaveLiveRegisters(codegen, instruction_->GetLocations());
}
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowNullPointer),
+ mips_codegen->InvokeRuntime(kQuickThrowNullPointer,
instruction_,
instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickThrowNullPointer));
+ this);
CheckEntrypointTypes<kQuickThrowNullPointer, void, void>();
}
@@ -351,11 +335,7 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen);
__ Bind(GetEntryLabel());
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pTestSuspend),
- instruction_,
- instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickTestSuspend));
+ mips_codegen->InvokeRuntime(kQuickTestSuspend, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickTestSuspend, void, void>();
if (successor_ == nullptr) {
__ B(GetReturnLabel());
@@ -407,11 +387,7 @@
Primitive::kPrimNot);
if (instruction_->IsInstanceOf()) {
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pInstanceofNonTrivial),
- instruction_,
- dex_pc,
- this,
- IsDirectEntrypoint(kQuickInstanceofNonTrivial));
+ mips_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this);
CheckEntrypointTypes<
kQuickInstanceofNonTrivial, size_t, const mirror::Class*, const mirror::Class*>();
Primitive::Type ret_type = instruction_->GetType();
@@ -419,11 +395,7 @@
mips_codegen->MoveLocation(locations->Out(), ret_loc, ret_type);
} else {
DCHECK(instruction_->IsCheckCast());
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pCheckCast),
- instruction_,
- dex_pc,
- this,
- IsDirectEntrypoint(kQuickCheckCast));
+ mips_codegen->InvokeRuntime(kQuickCheckCast, instruction_, dex_pc, this);
CheckEntrypointTypes<kQuickCheckCast, void, const mirror::Class*, const mirror::Class*>();
}
@@ -446,11 +418,7 @@
CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen);
__ Bind(GetEntryLabel());
SaveLiveRegisters(codegen, instruction_->GetLocations());
- mips_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pDeoptimize),
- instruction_,
- instruction_->GetDexPc(),
- this,
- IsDirectEntrypoint(kQuickDeoptimize));
+ mips_codegen->InvokeRuntime(kQuickDeoptimize, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickDeoptimize, void, void>();
}
@@ -1245,28 +1213,17 @@
stream << FRegister(reg);
}
+constexpr size_t kMipsDirectEntrypointRuntimeOffset = 16;
+
void CodeGeneratorMIPS::InvokeRuntime(QuickEntrypointEnum entrypoint,
HInstruction* instruction,
uint32_t dex_pc,
SlowPathCode* slow_path) {
- InvokeRuntime(GetThreadOffset<kMipsPointerSize>(entrypoint).Int32Value(),
- instruction,
- dex_pc,
- slow_path,
- IsDirectEntrypoint(entrypoint));
-}
-
-constexpr size_t kMipsDirectEntrypointRuntimeOffset = 16;
-
-void CodeGeneratorMIPS::InvokeRuntime(int32_t entry_point_offset,
- HInstruction* instruction,
- uint32_t dex_pc,
- SlowPathCode* slow_path,
- bool is_direct_entrypoint) {
+ ValidateInvokeRuntime(instruction, slow_path);
bool reordering = __ SetReorder(false);
- __ LoadFromOffset(kLoadWord, T9, TR, entry_point_offset);
+ __ LoadFromOffset(kLoadWord, T9, TR, GetThreadOffset<kMipsPointerSize>(entrypoint).Int32Value());
__ Jalr(T9);
- if (is_direct_entrypoint) {
+ if (IsDirectEntrypoint(entrypoint)) {
// Reserve argument space on stack (for $a0-$a3) for
// entrypoints that directly reference native implementations.
// Called function may use this space to store $a0-$a3 regs.
@@ -1276,7 +1233,9 @@
__ Nop(); // In delay slot.
}
__ SetReorder(reordering);
- RecordPcInfo(instruction, dex_pc, slow_path);
+ if (EntrypointRequiresStackMap(entrypoint)) {
+ RecordPcInfo(instruction, dex_pc, slow_path);
+ }
}
void InstructionCodeGeneratorMIPS::GenerateClassInitializationCheck(SlowPathCodeMIPS* slow_path,
@@ -2080,11 +2039,7 @@
}
} else {
DCHECK_EQ(value_type, Primitive::kPrimNot);
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickAputObject));
+ codegen_->InvokeRuntime(kQuickAputObject, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickAputObject, void, mirror::Array*, int32_t, mirror::Object*>();
}
break;
@@ -2650,11 +2605,7 @@
GenerateDivRemIntegral(instruction);
break;
case Primitive::kPrimLong: {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLdiv),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickLdiv));
+ codegen_->InvokeRuntime(kQuickLdiv, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickLdiv, int64_t, int64_t, int64_t>();
break;
}
@@ -3640,11 +3591,7 @@
// Do implicit Null check
__ Lw(ZERO, locations->GetTemp(0).AsRegister<Register>(), 0);
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pA64Load),
- instruction,
- dex_pc,
- nullptr,
- IsDirectEntrypoint(kQuickA64Load));
+ codegen_->InvokeRuntime(kQuickA64Load, instruction, dex_pc);
CheckEntrypointTypes<kQuickA64Load, int64_t, volatile const int64_t*>();
if (type == Primitive::kPrimDouble) {
// FP results are returned in core registers. Need to move them.
@@ -3792,11 +3739,7 @@
value);
}
}
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pA64Store),
- instruction,
- dex_pc,
- nullptr,
- IsDirectEntrypoint(kQuickA64Store));
+ codegen_->InvokeRuntime(kQuickA64Store, instruction, dex_pc);
CheckEntrypointTypes<kQuickA64Store, void, volatile int64_t *, int64_t>();
} else {
if (!Primitive::IsFloatingPointType(type)) {
@@ -4380,11 +4323,7 @@
LocationSummary* locations = cls->GetLocations();
if (cls->NeedsAccessCheck()) {
codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pInitializeTypeAndVerifyAccess),
- cls,
- cls->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickInitializeTypeAndVerifyAccess));
+ codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
return;
}
@@ -4652,18 +4591,10 @@
void InstructionCodeGeneratorMIPS::VisitMonitorOperation(HMonitorOperation* instruction) {
if (instruction->IsEnter()) {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLockObject),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickLockObject));
+ codegen_->InvokeRuntime(kQuickLockObject, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickLockObject, void, mirror::Object*>();
} else {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pUnlockObject),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickUnlockObject));
+ codegen_->InvokeRuntime(kQuickUnlockObject, instruction, instruction->GetDexPc());
}
CheckEntrypointTypes<kQuickUnlockObject, void, mirror::Object*>();
}
@@ -4838,12 +4769,7 @@
__ Lw(current_method_register, SP, kCurrentMethodStackOffset);
// Move an uint16_t value to a register.
__ LoadConst32(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
- codegen_->InvokeRuntime(
- GetThreadOffset<kMipsPointerSize>(instruction->GetEntrypoint()).Int32Value(),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickAllocArrayWithAccessCheck));
+ codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck,
void*, uint32_t, int32_t, ArtMethod*>();
}
@@ -4872,12 +4798,7 @@
__ NopIfNoReordering();
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
} else {
- codegen_->InvokeRuntime(
- GetThreadOffset<kMipsPointerSize>(instruction->GetEntrypoint()).Int32Value(),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickAllocObjectWithAccessCheck));
+ codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, ArtMethod*>();
}
}
@@ -5062,27 +4983,17 @@
GenerateDivRemIntegral(instruction);
break;
case Primitive::kPrimLong: {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLmod),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickLmod));
+ codegen_->InvokeRuntime(kQuickLmod, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickLmod, int64_t, int64_t, int64_t>();
break;
}
case Primitive::kPrimFloat: {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmodf),
- instruction, instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickFmodf));
+ codegen_->InvokeRuntime(kQuickFmodf, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickFmodf, float, float, float>();
break;
}
case Primitive::kPrimDouble: {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmod),
- instruction, instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickFmod));
+ codegen_->InvokeRuntime(kQuickFmod, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickFmod, double, double, double>();
break;
}
@@ -5263,11 +5174,7 @@
}
void InstructionCodeGeneratorMIPS::VisitThrow(HThrow* instruction) {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pDeliverException),
- instruction,
- instruction->GetDexPc(),
- nullptr,
- IsDirectEntrypoint(kQuickDeliverException));
+ codegen_->InvokeRuntime(kQuickDeliverException, instruction, instruction->GetDexPc());
CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
}
@@ -5388,15 +5295,9 @@
__ Cvtdl(dst, FTMP);
}
} else {
- int32_t entry_offset = (result_type == Primitive::kPrimFloat) ? QUICK_ENTRY_POINT(pL2f)
- : QUICK_ENTRY_POINT(pL2d);
- bool direct = (result_type == Primitive::kPrimFloat) ? IsDirectEntrypoint(kQuickL2f)
- : IsDirectEntrypoint(kQuickL2d);
- codegen_->InvokeRuntime(entry_offset,
- conversion,
- conversion->GetDexPc(),
- nullptr,
- direct);
+ QuickEntrypointEnum entrypoint = (result_type == Primitive::kPrimFloat) ? kQuickL2f
+ : kQuickL2d;
+ codegen_->InvokeRuntime(entrypoint, conversion, conversion->GetDexPc());
if (result_type == Primitive::kPrimFloat) {
CheckEntrypointTypes<kQuickL2f, float, int64_t>();
} else {
@@ -5489,11 +5390,9 @@
__ Bind(&done);
} else {
- int32_t entry_offset = (input_type == Primitive::kPrimFloat) ? QUICK_ENTRY_POINT(pF2l)
- : QUICK_ENTRY_POINT(pD2l);
- bool direct = (result_type == Primitive::kPrimFloat) ? IsDirectEntrypoint(kQuickF2l)
- : IsDirectEntrypoint(kQuickD2l);
- codegen_->InvokeRuntime(entry_offset, conversion, conversion->GetDexPc(), nullptr, direct);
+ QuickEntrypointEnum entrypoint = (input_type == Primitive::kPrimFloat) ? kQuickF2l
+ : kQuickD2l;
+ codegen_->InvokeRuntime(entrypoint, conversion, conversion->GetDexPc());
if (input_type == Primitive::kPrimFloat) {
CheckEntrypointTypes<kQuickF2l, int64_t, float>();
} else {
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 46810d6..4ce54b6 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -347,13 +347,7 @@
void InvokeRuntime(QuickEntrypointEnum entrypoint,
HInstruction* instruction,
uint32_t dex_pc,
- SlowPathCode* slow_path) OVERRIDE;
-
- void InvokeRuntime(int32_t offset,
- HInstruction* instruction,
- uint32_t dex_pc,
- SlowPathCode* slow_path,
- bool is_direct_entrypoint);
+ SlowPathCode* slow_path = nullptr) OVERRIDE;
ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; }
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index 862a93f..99ad898 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -1875,7 +1875,7 @@
// int java.lang.String.compareTo(String anotherString)
void IntrinsicLocationsBuilderMIPS::VisitStringCompareTo(HInvoke* invoke) {
LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kCallOnMainOnly,
+ LocationSummary::kCallOnMainAndSlowPath,
kIntrinsified);
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
@@ -1895,13 +1895,7 @@
SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke);
codegen_->AddSlowPath(slow_path);
__ Beqz(argument, slow_path->GetEntryLabel());
-
- __ LoadFromOffset(kLoadWord,
- T9,
- TR,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pStringCompareTo).Int32Value());
- __ Jalr(T9);
- __ NopIfNoReordering();
+ codegen_->InvokeRuntime(kQuickStringCompareTo, invoke, invoke->GetDexPc(), slow_path);
__ Bind(slow_path->GetExitLabel());
}
@@ -2055,13 +2049,7 @@
__ Clear(tmp_reg);
}
- __ LoadFromOffset(kLoadWord,
- T9,
- TR,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pIndexOf).Int32Value());
- __ Jalr(T9);
- __ NopIfNoReordering();
-
+ codegen->InvokeRuntime(kQuickIndexOf, invoke, invoke->GetDexPc(), slow_path);
if (slow_path != nullptr) {
__ Bind(slow_path->GetExitLabel());
}
@@ -2140,14 +2128,7 @@
SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke);
codegen_->AddSlowPath(slow_path);
__ Beqz(byte_array, slow_path->GetEntryLabel());
-
- __ LoadFromOffset(kLoadWord,
- T9,
- TR,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pAllocStringFromBytes).Int32Value());
- __ Jalr(T9);
- __ NopIfNoReordering();
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
+ codegen_->InvokeRuntime(kQuickAllocStringFromBytes, invoke, invoke->GetDexPc(), slow_path);
__ Bind(slow_path->GetExitLabel());
}
@@ -2165,22 +2146,13 @@
}
void IntrinsicCodeGeneratorMIPS::VisitStringNewStringFromChars(HInvoke* invoke) {
- MipsAssembler* assembler = GetAssembler();
-
// No need to emit code checking whether `locations->InAt(2)` is a null
// pointer, as callers of the native method
//
// java.lang.StringFactory.newStringFromChars(int offset, int charCount, char[] data)
//
// all include a null check on `data` before calling that method.
-
- __ LoadFromOffset(kLoadWord,
- T9,
- TR,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pAllocStringFromChars).Int32Value());
- __ Jalr(T9);
- __ NopIfNoReordering();
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
+ codegen_->InvokeRuntime(kQuickAllocStringFromChars, invoke, invoke->GetDexPc());
}
// java.lang.StringFactory.newStringFromString(String toCopy)
@@ -2202,14 +2174,7 @@
SlowPathCodeMIPS* slow_path = new (GetAllocator()) IntrinsicSlowPathMIPS(invoke);
codegen_->AddSlowPath(slow_path);
__ Beqz(string_to_copy, slow_path->GetEntryLabel());
-
- __ LoadFromOffset(kLoadWord,
- T9,
- TR,
- QUICK_ENTRYPOINT_OFFSET(kMipsPointerSize, pAllocStringFromString).Int32Value());
- __ Jalr(T9);
- __ NopIfNoReordering();
- codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
+ codegen_->InvokeRuntime(kQuickAllocStringFromString, invoke, invoke->GetDexPc());
__ Bind(slow_path->GetExitLabel());
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index dfa8276..94913fc 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -5021,7 +5021,7 @@
Handle<mirror::DexCache> dex_cache,
uint32_t dex_pc)
: HExpression(field_type,
- SideEffects::FieldReadOfType(field_type, is_volatile),
+ SideEffectsForArchRuntimeCalls(field_type, is_volatile),
dex_pc),
field_info_(field_offset,
field_type,
@@ -5053,6 +5053,16 @@
Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
bool IsVolatile() const { return field_info_.IsVolatile(); }
+ static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) {
+ SideEffects side_effects = SideEffects::FieldReadOfType(field_type, is_volatile);
+
+ // MIPS delegates volatile kPrimLong and kPrimDouble loads to a runtime helper.
+ if (Primitive::Is64BitType(field_type)) {
+ side_effects.Add(SideEffects::CanTriggerGC());
+ }
+ return side_effects;
+ }
+
DECLARE_INSTRUCTION(InstanceFieldGet);
private:
@@ -5073,7 +5083,7 @@
const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile),
+ : HTemplateInstruction(SideEffectsForArchRuntimeCalls(field_type, is_volatile),
dex_pc),
field_info_(field_offset,
field_type,
@@ -5099,6 +5109,16 @@
bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
+ static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) {
+ SideEffects side_effects = SideEffects::FieldWriteOfType(field_type, is_volatile);
+
+ // MIPS delegates volatile kPrimLong and kPrimDouble stores to a runtime helper.
+ if (Primitive::Is64BitType(field_type)) {
+ side_effects.Add(SideEffects::CanTriggerGC());
+ }
+ return side_effects;
+ }
+
DECLARE_INSTRUCTION(InstanceFieldSet);
private:
@@ -5896,7 +5916,7 @@
Handle<mirror::DexCache> dex_cache,
uint32_t dex_pc)
: HExpression(field_type,
- SideEffects::FieldReadOfType(field_type, is_volatile),
+ SideEffectsForArchRuntimeCalls(field_type, is_volatile),
dex_pc),
field_info_(field_offset,
field_type,
@@ -5925,6 +5945,16 @@
Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
bool IsVolatile() const { return field_info_.IsVolatile(); }
+ static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) {
+ SideEffects side_effects = SideEffects::FieldReadOfType(field_type, is_volatile);
+
+ // MIPS delegates volatile kPrimLong and kPrimDouble loads to a runtime helper.
+ if (Primitive::Is64BitType(field_type)) {
+ side_effects.Add(SideEffects::CanTriggerGC());
+ }
+ return side_effects;
+ }
+
DECLARE_INSTRUCTION(StaticFieldGet);
private:
@@ -5945,7 +5975,7 @@
const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile),
+ : HTemplateInstruction(SideEffectsForArchRuntimeCalls(field_type, is_volatile),
dex_pc),
field_info_(field_offset,
field_type,
@@ -5968,6 +5998,16 @@
bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
+ static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type field_type, bool is_volatile) {
+ SideEffects side_effects = SideEffects::FieldWriteOfType(field_type, is_volatile);
+
+ // MIPS delegates volatile kPrimLong and kPrimDouble stores to a runtime helper.
+ if (Primitive::Is64BitType(field_type)) {
+ side_effects.Add(SideEffects::CanTriggerGC());
+ }
+ return side_effects;
+ }
+
DECLARE_INSTRUCTION(StaticFieldSet);
private:
diff --git a/runtime/entrypoints/quick/quick_entrypoints_enum.cc b/runtime/entrypoints/quick/quick_entrypoints_enum.cc
index 5153f0f..7b80af6 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_enum.cc
+++ b/runtime/entrypoints/quick/quick_entrypoints_enum.cc
@@ -61,6 +61,11 @@
case kQuickUshrLong:
return false;
+ /* Used by mips for 64bit volatile load/stores. */
+ case kQuickA64Load:
+ case kQuickA64Store:
+ return false;
+
default:
return true;
}