diff options
author | 2015-06-09 14:12:28 +0100 | |
---|---|---|
committer | 2015-06-09 15:03:47 +0100 | |
commit | ae71a0539451a8350bdd9d46c76ddab7b763f209 (patch) | |
tree | a7f7040991d89bc787ed38864ab09f0bcbf84576 | |
parent | 7c5e26b3ea5262c0aea3374148750e81340a4bf9 (diff) |
Fix a crash in optimizing compiler with the current method.
Crash was due to overwriting the location of the current method
in the slow path of an intrinsic.
Change-Id: I6ca58ef5b3cea19925e60b9500aef543bc5f71ef
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 18 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 19 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 21 | ||||
-rw-r--r-- | test/491-current-method/expected.txt | 0 | ||||
-rw-r--r-- | test/491-current-method/info.txt | 2 | ||||
-rw-r--r-- | test/491-current-method/src/Main.java | 70 |
7 files changed, 108 insertions, 28 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index f4544ea70d..6168c2046f 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1254,10 +1254,6 @@ void LocationsBuilderARM::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invok IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(), codegen_->GetInstructionSetFeatures()); if (intrinsic.TryDispatch(invoke)) { - LocationSummary* locations = invoke->GetLocations(); - if (locations->CanCall()) { - locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister()); - } return; } @@ -4227,12 +4223,20 @@ void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, } else if (invoke->IsRecursive()) { __ bl(GetFrameEntryLabel()); } else { - Register current_method = - invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<Register>(); + Location current_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()); + Register method_reg; Register reg = temp.AsRegister<Register>(); + if (current_method.IsRegister()) { + method_reg = current_method.AsRegister<Register>(); + } else { + DCHECK(invoke->GetLocations()->Intrinsified()); + DCHECK(!current_method.IsValid()); + method_reg = reg; + __ LoadFromOffset(kLoadWord, reg, SP, kCurrentMethodStackOffset); + } // reg = current_method->dex_cache_resolved_methods_; __ LoadFromOffset( - kLoadWord, reg, current_method, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()); + kLoadWord, reg, method_reg, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()); // reg = reg[index_in_cache] __ LoadFromOffset( kLoadWord, reg, reg, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex())); diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index ac99d56676..c8af727f78 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -2227,10 +2227,6 @@ void LocationsBuilderARM64::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* inv IntrinsicLocationsBuilderARM64 intrinsic(GetGraph()->GetArena()); if (intrinsic.TryDispatch(invoke)) { - LocationSummary* locations = invoke->GetLocations(); - if (locations->CanCall()) { - locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister()); - } return; } @@ -2269,11 +2265,20 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invok } else if (invoke->IsRecursive()) { __ Bl(&frame_entry_label_); } else { - Register current_method = - XRegisterFrom(invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex())); + Location current_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()); Register reg = XRegisterFrom(temp); + Register method_reg; + if (current_method.IsRegister()) { + method_reg = XRegisterFrom(current_method); + } else { + DCHECK(invoke->GetLocations()->Intrinsified()); + DCHECK(!current_method.IsValid()); + method_reg = reg; + __ Ldr(reg.X(), MemOperand(sp, kCurrentMethodStackOffset)); + } + // temp = current_method->dex_cache_resolved_methods_; - __ Ldr(reg.W(), MemOperand(current_method.X(), + __ Ldr(reg.W(), MemOperand(method_reg.X(), ArtMethod::DexCacheResolvedMethodsOffset().Int32Value())); // temp = temp[index_in_cache]; __ Ldr(reg.X(), MemOperand(reg, index_in_cache)); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index f6110a558e..135a2bd60d 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1231,10 +1231,6 @@ void LocationsBuilderX86::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invok IntrinsicLocationsBuilderX86 intrinsic(codegen_); if (intrinsic.TryDispatch(invoke)) { - LocationSummary* locations = invoke->GetLocations(); - if (locations->CanCall()) { - locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister()); - } return; } @@ -3237,7 +3233,7 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, if (current_method.IsRegister()) { method_reg = current_method.AsRegister<Register>(); } else { - DCHECK(IsBaseline()); + DCHECK(IsBaseline() || invoke->GetLocations()->Intrinsified()); DCHECK(!current_method.IsValid()); method_reg = reg; __ movl(reg, Address(ESP, kCurrentMethodStackOffset)); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index c9fe813f20..cf74d2e36e 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -380,13 +380,20 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo } else if (invoke->IsRecursive()) { __ call(&frame_entry_label_); } else { - LocationSummary* locations = invoke->GetLocations(); CpuRegister reg = temp.AsRegister<CpuRegister>(); - CpuRegister current_method = - locations->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<CpuRegister>(); + Location current_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()); + Register method_reg; + if (current_method.IsRegister()) { + method_reg = current_method.AsRegister<Register>(); + } else { + DCHECK(invoke->GetLocations()->Intrinsified()); + DCHECK(!current_method.IsValid()); + method_reg = reg.AsRegister(); + __ movq(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset)); + } // temp = temp->dex_cache_resolved_methods_; - __ movl(reg, Address( - current_method, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue())); + __ movl(reg, Address(CpuRegister(method_reg), + ArtMethod::DexCacheResolvedMethodsOffset().SizeValue())); // temp = temp[index_in_cache] __ movq(reg, Address( reg, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex()))); @@ -1336,10 +1343,6 @@ void LocationsBuilderX86_64::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* in IntrinsicLocationsBuilderX86_64 intrinsic(codegen_); if (intrinsic.TryDispatch(invoke)) { - LocationSummary* locations = invoke->GetLocations(); - if (locations->CanCall()) { - locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister()); - } return; } diff --git a/test/491-current-method/expected.txt b/test/491-current-method/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/491-current-method/expected.txt diff --git a/test/491-current-method/info.txt b/test/491-current-method/info.txt new file mode 100644 index 0000000000..e9678da769 --- /dev/null +++ b/test/491-current-method/info.txt @@ -0,0 +1,2 @@ +Regression test for optimizing that used to +crash in the presence of slow paths with intrinsics. diff --git a/test/491-current-method/src/Main.java b/test/491-current-method/src/Main.java new file mode 100644 index 0000000000..87ef05218d --- /dev/null +++ b/test/491-current-method/src/Main.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Main { + + // The code below is written in a way that will crash + // the generated code at the time of submission of this test. + // Therefore, changes to the register allocator may + // affect the reproducibility of the crash. + public static void $noinline$foo(int a, int b, int c) { + // The division on x86 will take EAX and EDX, leaving ECX + // to put the ART current method. + c = c / 42; + // We use the empty string for forcing the slow path. + // The slow path for charAt when it is intrinsified, will + // move the parameter to ECX, and therefore overwrite the ART + // current method. + "".charAt(c); + + // Do more things in the method to prevent inlining. + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + c = c / 42; + "".charAt(c); + } + + public static void main(String[] args) { + boolean didThrow = false; + try { + $noinline$foo(1, 2, 3); + } catch (Throwable e) { + didThrow = true; + } + + if (!didThrow) { + throw new Error("Expected an exception from charAt"); + } + } +} |