diff options
-rw-r--r-- | compiler/optimizing/block_builder.cc | 12 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 12 | ||||
-rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 8 | ||||
-rw-r--r-- | test/689-multi-catch/expected.txt | 0 | ||||
-rw-r--r-- | test/689-multi-catch/info.txt | 2 | ||||
-rw-r--r-- | test/689-multi-catch/src/Main.java | 32 |
6 files changed, 56 insertions, 10 deletions
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc index 3672cce4c5..a5f78cafe0 100644 --- a/compiler/optimizing/block_builder.cc +++ b/compiler/optimizing/block_builder.cc @@ -315,8 +315,16 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() { CatchHandlerIterator iterator(handlers_ptr); for (; iterator.HasNext(); iterator.Next()) { uint32_t address = iterator.GetHandlerAddress(); - if (catch_blocks.find(address) != catch_blocks.end()) { + auto existing = catch_blocks.find(address); + if (existing != catch_blocks.end()) { // Catch block already processed. + TryCatchInformation* info = existing->second->GetTryCatchInformation(); + if (iterator.GetHandlerTypeIndex() != info->GetCatchTypeIndex()) { + // The handler is for multiple types. We could record all the types, but + // doing class resolution here isn't ideal, and it's unclear whether wasting + // the space in TryCatchInformation is worth it. + info->SetInvalidTypeIndex(); + } continue; } @@ -337,7 +345,7 @@ void HBasicBlockBuilder::InsertTryBoundaryBlocks() { catch_blocks.Put(address, catch_block); catch_block->SetTryCatchInformation( - new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); + new (allocator_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_)); } handlers_ptr = iterator.EndDataPointer(); } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 686a2deb0b..48fb611da2 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -895,7 +895,7 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { explicit TryCatchInformation(const HTryBoundary& try_entry) : try_entry_(&try_entry), catch_dex_file_(nullptr), - catch_type_index_(DexFile::kDexNoIndex16) { + catch_type_index_(dex::TypeIndex::Invalid()) { DCHECK(try_entry_ != nullptr); } @@ -914,9 +914,9 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { bool IsCatchBlock() const { return catch_dex_file_ != nullptr; } - bool IsCatchAllTypeIndex() const { + bool IsValidTypeIndex() const { DCHECK(IsCatchBlock()); - return !catch_type_index_.IsValid(); + return catch_type_index_.IsValid(); } dex::TypeIndex GetCatchTypeIndex() const { @@ -929,6 +929,10 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { return *catch_dex_file_; } + void SetInvalidTypeIndex() { + catch_type_index_ = dex::TypeIndex::Invalid(); + } + private: // One of possibly several TryBoundary instructions entering the block's try. // Only set for try blocks. @@ -936,7 +940,7 @@ class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> { // Exception type information. Only set for catch blocks. const DexFile* catch_dex_file_; - const dex::TypeIndex catch_type_index_; + dex::TypeIndex catch_type_index_; }; static constexpr size_t kNoLifetime = -1; diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 61e7a60ea9..4929e0a3a1 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -699,14 +699,14 @@ void ReferenceTypePropagation::RTPVisitor::VisitLoadException(HLoadException* in DCHECK(instr->GetBlock()->IsCatchBlock()); TryCatchInformation* catch_info = instr->GetBlock()->GetTryCatchInformation(); - if (catch_info->IsCatchAllTypeIndex()) { - instr->SetReferenceTypeInfo( - ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false)); - } else { + if (catch_info->IsValidTypeIndex()) { UpdateReferenceTypeInfo(instr, catch_info->GetCatchTypeIndex(), catch_info->GetCatchDexFile(), /* is_exact= */ false); + } else { + instr->SetReferenceTypeInfo( + ReferenceTypeInfo::Create(handle_cache_->GetThrowableClassHandle(), /* is_exact= */ false)); } } diff --git a/test/689-multi-catch/expected.txt b/test/689-multi-catch/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/689-multi-catch/expected.txt diff --git a/test/689-multi-catch/info.txt b/test/689-multi-catch/info.txt new file mode 100644 index 0000000000..0778ea83c0 --- /dev/null +++ b/test/689-multi-catch/info.txt @@ -0,0 +1,2 @@ +Regression test for the optimizing compiler which used +to wrongly type an exception in a multi-catch handler. diff --git a/test/689-multi-catch/src/Main.java b/test/689-multi-catch/src/Main.java new file mode 100644 index 0000000000..18a17f9e2e --- /dev/null +++ b/test/689-multi-catch/src/Main.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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. + */ + +public class Main { + public static void main(String[] args) { + try { + willThrow(); + } catch (IllegalStateException | NullPointerException e) { + if (e instanceof NullPointerException) { + return; + } + throw new Error("Expected NullPointerException"); + } + } + + public static void willThrow() { + throw new NullPointerException(); + } +} |