• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dexgen.dex.code;
18 
19 import com.android.dexgen.rop.code.RegisterSpecList;
20 import com.android.dexgen.rop.code.SourcePosition;
21 import com.android.dexgen.rop.cst.*;
22 import com.android.dexgen.rop.type.Type;
23 import com.android.dexgen.util.AnnotatedOutput;
24 import com.android.dexgen.util.Hex;
25 
26 import java.util.ArrayList;
27 
28 /**
29  * Pseudo-instruction which holds fill array data.
30  */
31 public final class ArrayData extends VariableSizeInsn {
32     /**
33      * {@code non-null;} address representing the instruction that uses this
34      * instance
35      */
36     private final CodeAddress user;
37 
38     /** {@code non-null;} initial values to be filled into an array */
39     private final ArrayList<Constant> values;
40 
41     /** non-null: type of constant that initializes the array */
42     private final Constant arrayType;
43 
44     /** Width of the init value element */
45     private final int elemWidth;
46 
47     /** Length of the init list */
48     private final int initLength;
49 
50     /**
51      * Constructs an instance. The output address of this instance is initially
52      * unknown ({@code -1}).
53      *
54      * @param position {@code non-null;} source position
55      * @param user {@code non-null;} address representing the instruction that
56      * uses this instance
57      * @param values {@code non-null;} initial values to be filled into an array
58      */
ArrayData(SourcePosition position, CodeAddress user, ArrayList<Constant> values, Constant arrayType)59     public ArrayData(SourcePosition position, CodeAddress user,
60                      ArrayList<Constant> values,
61                      Constant arrayType) {
62         super(position, RegisterSpecList.EMPTY);
63 
64         if (user == null) {
65             throw new NullPointerException("user == null");
66         }
67 
68         if (values == null) {
69             throw new NullPointerException("values == null");
70         }
71 
72         int sz = values.size();
73 
74         if (sz <= 0) {
75             throw new IllegalArgumentException("Illegal number of init values");
76         }
77 
78         this.arrayType = arrayType;
79 
80         if (arrayType == CstType.BYTE_ARRAY ||
81                 arrayType == CstType.BOOLEAN_ARRAY) {
82             elemWidth = 1;
83         } else if (arrayType == CstType.SHORT_ARRAY ||
84                 arrayType == CstType.CHAR_ARRAY) {
85             elemWidth = 2;
86         } else if (arrayType == CstType.INT_ARRAY ||
87                 arrayType == CstType.FLOAT_ARRAY) {
88             elemWidth = 4;
89         } else if (arrayType == CstType.LONG_ARRAY ||
90                 arrayType == CstType.DOUBLE_ARRAY) {
91             elemWidth = 8;
92         } else {
93             throw new IllegalArgumentException("Unexpected constant type");
94         }
95         this.user = user;
96         this.values = values;
97         initLength = values.size();
98     }
99 
100     /** {@inheritDoc} */
101     @Override
codeSize()102     public int codeSize() {
103         int sz = initLength;
104         // Note: the unit here is 16-bit
105         return 4 + ((sz * elemWidth) + 1) / 2;
106     }
107 
108     /** {@inheritDoc} */
109     @Override
writeTo(AnnotatedOutput out)110     public void writeTo(AnnotatedOutput out) {
111         int sz = values.size();
112 
113         out.writeShort(0x300 | DalvOps.NOP);
114         out.writeShort(elemWidth);
115         out.writeInt(initLength);
116 
117 
118         // For speed reasons, replicate the for loop in each case
119         switch (elemWidth) {
120             case 1: {
121                 for (int i = 0; i < sz; i++) {
122                     Constant cst = values.get(i);
123                     out.writeByte((byte) ((CstLiteral32) cst).getIntBits());
124                 }
125                 break;
126             }
127             case 2: {
128                 for (int i = 0; i < sz; i++) {
129                     Constant cst = values.get(i);
130                     out.writeShort((short) ((CstLiteral32) cst).getIntBits());
131                 }
132                 break;
133             }
134             case 4: {
135                 for (int i = 0; i < sz; i++) {
136                     Constant cst = values.get(i);
137                     out.writeInt(((CstLiteral32) cst).getIntBits());
138                 }
139                 break;
140             }
141             case 8: {
142                 for (int i = 0; i < sz; i++) {
143                     Constant cst = values.get(i);
144                     out.writeLong(((CstLiteral64) cst).getLongBits());
145                 }
146                 break;
147             }
148             default:
149                 break;
150         }
151 
152         // Pad one byte to make the size of data table multiples of 16-bits
153         if (elemWidth == 1 && (sz % 2 != 0)) {
154             out.writeByte(0x00);
155         }
156     }
157 
158     /** {@inheritDoc} */
159     @Override
withRegisters(RegisterSpecList registers)160     public DalvInsn withRegisters(RegisterSpecList registers) {
161         return new ArrayData(getPosition(), user, values, arrayType);
162     }
163 
164     /** {@inheritDoc} */
165     @Override
argString()166     protected String argString() {
167         StringBuffer sb = new StringBuffer(100);
168 
169         int sz = values.size();
170         for (int i = 0; i < sz; i++) {
171             sb.append("\n    ");
172             sb.append(i);
173             sb.append(": ");
174             sb.append(values.get(i).toHuman());
175         }
176 
177         return sb.toString();
178     }
179 
180     /** {@inheritDoc} */
181     @Override
listingString0(boolean noteIndices)182     protected String listingString0(boolean noteIndices) {
183         int baseAddress = user.getAddress();
184         StringBuffer sb = new StringBuffer(100);
185         int sz = values.size();
186 
187         sb.append("array-data // for fill-array-data @ ");
188         sb.append(Hex.u2(baseAddress));
189 
190         for (int i = 0; i < sz; i++) {
191             sb.append("\n  ");
192             sb.append(i);
193             sb.append(": ");
194             sb.append(values.get(i).toHuman());
195         }
196 
197         return sb.toString();
198     }
199 }
200