|  | // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  | package com.android.tools.r8.ir.code; | 
|  |  | 
|  | import com.android.tools.r8.graph.DexItemFactory; | 
|  | import com.android.tools.r8.graph.DexType; | 
|  | import com.android.tools.r8.ir.code.CatchHandlers.CatchHandler; | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import com.google.common.collect.ImmutableSet; | 
|  | import java.util.ArrayList; | 
|  | import java.util.Iterator; | 
|  | import java.util.List; | 
|  | import java.util.Set; | 
|  | import java.util.function.BiConsumer; | 
|  |  | 
|  | public class CatchHandlers<T> implements Iterable<CatchHandler<T>> { | 
|  |  | 
|  | public static class CatchHandler<T> { | 
|  |  | 
|  | public final DexType guard; | 
|  | public final T target; | 
|  |  | 
|  | public CatchHandler(DexType guard, T target) { | 
|  | this.guard = guard; | 
|  | this.target = target; | 
|  | } | 
|  | } | 
|  |  | 
|  | private final List<DexType> guards; | 
|  | private final List<T> targets; | 
|  | private Set<T> uniqueTargets; | 
|  |  | 
|  | public static final CatchHandlers<Integer> EMPTY_INDICES = new CatchHandlers<>(); | 
|  | public static final CatchHandlers<BasicBlock> EMPTY_BASIC_BLOCK = new CatchHandlers<>(); | 
|  |  | 
|  | private CatchHandlers() { | 
|  | guards = ImmutableList.of(); | 
|  | targets = ImmutableList.of(); | 
|  | } | 
|  |  | 
|  | public CatchHandlers(List<DexType> guards, List<T> targets) { | 
|  | assert !guards.isEmpty(); | 
|  | assert guards.size() == targets.size(); | 
|  | // Guava ImmutableList does not support null elements. | 
|  | this.guards = ImmutableList.copyOf(guards); | 
|  | this.targets = ImmutableList.copyOf(targets); | 
|  | } | 
|  |  | 
|  | public boolean isEmpty() { | 
|  | return size() == 0; | 
|  | } | 
|  |  | 
|  | public int size() { | 
|  | assert guards.size() == targets.size(); | 
|  | return guards.size(); | 
|  | } | 
|  |  | 
|  | public List<DexType> getGuards() { | 
|  | return guards; | 
|  | } | 
|  |  | 
|  | public List<T> getAllTargets() { | 
|  | return targets; | 
|  | } | 
|  |  | 
|  | public Set<T> getUniqueTargets() { | 
|  | if (uniqueTargets == null) { | 
|  | uniqueTargets = ImmutableSet.copyOf(targets); | 
|  | } | 
|  | return uniqueTargets; | 
|  | } | 
|  |  | 
|  | public boolean hasCatchAll(DexItemFactory factory) { | 
|  | return getGuards().size() > 0 | 
|  | && getGuards().get(getGuards().size() - 1) == factory.throwableType; | 
|  | } | 
|  |  | 
|  | public CatchHandlers<T> removeGuard(DexType guardToBeRemoved) { | 
|  | List<DexType> newGuards = new ArrayList<>(); | 
|  | List<T> newTargets = new ArrayList<>(); | 
|  | forEach( | 
|  | (guard, target) -> { | 
|  | if (guard != guardToBeRemoved) { | 
|  | newGuards.add(guard); | 
|  | newTargets.add(target); | 
|  | } | 
|  | }); | 
|  | return new CatchHandlers<>(newGuards, newTargets); | 
|  | } | 
|  |  | 
|  | public void forEach(BiConsumer<DexType, T> consumer) { | 
|  | for (int i = 0; i < size(); ++i) { | 
|  | consumer.accept(guards.get(i), targets.get(i)); | 
|  | } | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public Iterator<CatchHandler<T>> iterator() { | 
|  | return new Iterator<CatchHandler<T>>() { | 
|  |  | 
|  | private int nextIndex = 0; | 
|  |  | 
|  | @Override | 
|  | public boolean hasNext() { | 
|  | return nextIndex < size(); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public CatchHandler<T> next() { | 
|  | DexType guard = guards.get(nextIndex); | 
|  | T target = targets.get(nextIndex); | 
|  | ++nextIndex; | 
|  | return new CatchHandler<>(guard, target); | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean equals(Object o) { | 
|  | if (this == o) { | 
|  | return true; | 
|  | } | 
|  | if (!(o instanceof CatchHandlers)) { | 
|  | return false; | 
|  | } | 
|  | CatchHandlers<?> that = (CatchHandlers<?>) o; | 
|  | return guards.equals(that.guards) && targets.equals(that.targets); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int hashCode() { | 
|  | return 31 * guards.hashCode() + targets.hashCode(); | 
|  | } | 
|  | } |