|  | // 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.conversion; | 
|  |  | 
|  | import com.android.tools.r8.dex.code.DexInstruction; | 
|  | import com.android.tools.r8.dex.code.DexSwitchPayload; | 
|  | import java.util.Collection; | 
|  | import java.util.HashMap; | 
|  | import java.util.Map; | 
|  |  | 
|  | /** | 
|  | * Helper class for resolving payload information during IR construction. | 
|  | */ | 
|  | public class SwitchPayloadResolver { | 
|  |  | 
|  | public static class PayloadData { | 
|  |  | 
|  | public final static int NO_SIZE = -1; | 
|  | public int userOffset; | 
|  | public int[] absoluteTargets = null; | 
|  | public int[] keys = null; | 
|  | public int size = NO_SIZE; | 
|  |  | 
|  | public PayloadData(int userOffset) { | 
|  | this.userOffset = userOffset; | 
|  | } | 
|  | } | 
|  |  | 
|  | private final Map<Integer, DexSwitchPayload> unresolvedPayload = new HashMap<>(); | 
|  | private final Map<Integer, PayloadData> payloadToData = new HashMap<>(); | 
|  |  | 
|  | public void addPayloadUser(DexInstruction dex) { | 
|  | int offset = dex.getOffset(); | 
|  | int payloadOffset = offset + dex.getPayloadOffset(); | 
|  | payloadToData.put(payloadOffset, new PayloadData(offset)); | 
|  | if (unresolvedPayload.containsKey(payloadOffset)) { | 
|  | DexSwitchPayload payload = unresolvedPayload.remove(payloadOffset); | 
|  | resolve(payload); | 
|  | } | 
|  | } | 
|  |  | 
|  | public void resolve(DexSwitchPayload payload) { | 
|  | int payloadOffset = payload.getOffset(); | 
|  | PayloadData data = payloadToData.get(payloadOffset); | 
|  | if (data == null) { | 
|  | unresolvedPayload.put(payloadOffset, payload); | 
|  | return; | 
|  | } | 
|  |  | 
|  | int[] targets = payload.switchTargetOffsets(); | 
|  | int[] absoluteTargets = new int[targets.length]; | 
|  | for (int i = 0; i < targets.length; i++) { | 
|  | absoluteTargets[i] = data.userOffset + targets[i]; | 
|  | } | 
|  | data.absoluteTargets = absoluteTargets; | 
|  | data.keys = payload.keys(); | 
|  | data.size = payload.numberOfKeys(); | 
|  | } | 
|  |  | 
|  | public int[] absoluteTargets(DexInstruction dex) { | 
|  | assert dex.isIntSwitch(); | 
|  | return absoluteTargets(dex.getOffset() + dex.getPayloadOffset()); | 
|  | } | 
|  |  | 
|  | public int[] absoluteTargets(int payloadOffset) { | 
|  | return payloadToData.get(payloadOffset).absoluteTargets; | 
|  | } | 
|  |  | 
|  | public int[] getKeys(int payloadOffset) { | 
|  | return payloadToData.get(payloadOffset).keys; | 
|  | } | 
|  |  | 
|  | public int getSize(int payloadOffset) { | 
|  | return payloadToData.get(payloadOffset).size; | 
|  | } | 
|  |  | 
|  | public Collection<PayloadData> payloadDataSet() { | 
|  | return payloadToData.values(); | 
|  | } | 
|  |  | 
|  | public void clear() { | 
|  | payloadToData.clear(); | 
|  | } | 
|  | } |