• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 package com.android.tools.r8.code;
5 
6 import com.android.tools.r8.graph.ObjectToOffsetMapping;
7 import com.android.tools.r8.naming.ClassNameMapper;
8 import com.android.tools.r8.utils.StringUtils;
9 import java.nio.ShortBuffer;
10 import java.util.Arrays;
11 
12 public class SparseSwitchPayload extends SwitchPayload {
13 
14   public final int size;
15   public final int[] keys;
16   public final /* offset */ int[] targets;
17 
SparseSwitchPayload(int high, BytecodeStream stream)18   public SparseSwitchPayload(int high, BytecodeStream stream) {
19     super(high, stream);
20     size = read16BitValue(stream);
21     keys = new int[size];
22     for (int i = 0; i < size; i++) {
23       keys[i] = readSigned32BitValue(stream);
24     }
25 
26     targets = new int[size];
27     for (int i = 0; i < size; i++) {
28       targets[i] = readSigned32BitValue(stream);
29     }
30   }
31 
SparseSwitchPayload(int[] keys, int[] targets)32   public SparseSwitchPayload(int[] keys, int[] targets) {
33     assert targets.length > 0;  // Empty switches should be eliminated.
34     this.size = targets.length;
35     this.keys = keys;
36     this.targets = targets;
37   }
38 
isPayload()39   public boolean isPayload() {
40     return true;
41   }
42 
write(ShortBuffer dest, ObjectToOffsetMapping mapping)43   public void write(ShortBuffer dest, ObjectToOffsetMapping mapping) {
44     writeFirst(2, dest);  // Pseudo-opcode = 0x0200
45     write16BitValue(size, dest);
46     for (int i = 0; i < size; i++) {
47       write32BitValue(keys[i], dest);
48     }
49     for (int i = 0; i < size; i++) {
50       write32BitValue(targets[i], dest);
51     }
52   }
53 
54   @Override
equals(Object other)55   public boolean equals(Object other) {
56     if (!super.equals(other)) {
57       return false;
58     }
59     SparseSwitchPayload that = (SparseSwitchPayload) other;
60     return size == that.size && Arrays.equals(keys, that.keys) && Arrays
61         .equals(targets, that.targets);
62   }
63 
64   @Override
hashCode()65   public int hashCode() {
66     int result = super.hashCode();
67     result = 31 * result + size;
68     result = 31 * result + Arrays.hashCode(keys);
69     result = 31 * result + Arrays.hashCode(targets);
70     return result;
71   }
72 
getSize()73   public int getSize() {
74     return 2 + (2 * keys.length) + (2 * targets.length);
75   }
76 
77   @Override
numberOfKeys()78   public int numberOfKeys() {
79     return size;
80   }
81 
82   @Override
keys()83   public int[] keys() {
84     return keys;
85   }
86 
switchTargetOffsets()87   public int[] switchTargetOffsets() {
88     return targets;
89   }
90 
toString(ClassNameMapper naming)91   public String toString(ClassNameMapper naming) {
92     StringBuilder builder = new StringBuilder("[SparseSwitchPayload]\n");
93     for (int i = 0; i < size; i++) {
94       StringUtils.appendLeftPadded(builder, keys[i] + " -> " + targets[i] + "\n", 20);
95     }
96     return super.toString(naming) + builder.toString();
97   }
98 
toSmaliString(Instruction payloadUser)99   public String toSmaliString(Instruction payloadUser) {
100     StringBuilder builder = new StringBuilder();
101     builder.append("    ");
102     builder.append(".sparse-switch");
103     builder.append("\n");
104     for (int i = 0; i < keys.length; i++) {
105       builder.append("      ");
106       builder.append("0x");
107       builder.append(StringUtils.hexString(keys[i], 8));
108       builder.append(" -> :label_");
109       builder.append(payloadUser.getOffset() + targets[i]);
110       builder.append("  # ");
111       builder.append(keys[i]);
112       builder.append("\n");
113     }
114     builder.append("    ");
115     builder.append(".end sparse-switch");
116     return builder.toString();
117   }
118 }
119