ART: Move exception clearing into own instruction
Runtime delivers exceptions only to catch blocks which begin with a
MOVE_EXCEPTION instruction (in DEX). In that case, the catch block is
expected to clear the thread-local exception storage after having
read the exception reference.
This patch changes Optimizing to represent MOVE_EXCEPTION with two
instructions - HLoadException and HClearException - instead of one.
If the exception reference is not used, HLoadException can be safely
removed, saving a memory load without breaking the runtime behaviour.
Change-Id: Idad8a714467bf9d9d5fccefbc43c0bd8ae13ddba
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 75b8f06..b0a4ce2 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4290,6 +4290,10 @@
__ Bind(slow_path->GetExitLabel());
}
+static int32_t GetExceptionTlsOffset() {
+ return Thread::ExceptionOffset<kArmWordSize>().Int32Value();
+}
+
void LocationsBuilderARM::VisitLoadException(HLoadException* load) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kNoCall);
@@ -4298,10 +4302,16 @@
void InstructionCodeGeneratorARM::VisitLoadException(HLoadException* load) {
Register out = load->GetLocations()->Out().AsRegister<Register>();
- int32_t offset = Thread::ExceptionOffset<kArmWordSize>().Int32Value();
- __ LoadFromOffset(kLoadWord, out, TR, offset);
+ __ LoadFromOffset(kLoadWord, out, TR, GetExceptionTlsOffset());
+}
+
+void LocationsBuilderARM::VisitClearException(HClearException* clear) {
+ new (GetGraph()->GetArena()) LocationSummary(clear, LocationSummary::kNoCall);
+}
+
+void InstructionCodeGeneratorARM::VisitClearException(HClearException* clear ATTRIBUTE_UNUSED) {
__ LoadImmediate(IP, 0);
- __ StoreToOffset(kStoreWord, IP, TR, offset);
+ __ StoreToOffset(kStoreWord, IP, TR, GetExceptionTlsOffset());
}
void LocationsBuilderARM::VisitThrow(HThrow* instruction) {