CodeVerify.c revision 99409883d9c4c0ffb49b070ce307bb33a9dfe9f1
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dalvik bytecode structural verifier.  The only public entry point
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (except for a few shared utility functions) is dvmVerifyCodeFlow().
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: might benefit from a signature-->class lookup cache.  Could avoid
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * some string-peeling and wouldn't need to compute hashes.
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we do too much stuff in here that could be done in the static
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verification pass.  It's convenient, because we have all of the
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary information, but it's more efficient to do it over in
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * DexVerify.c because in here we may have to process instructions
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * multiple times.
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "analysis/CodeVerify.h"
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "analysis/RegisterMap.h"
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexCatch.h"
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/InstrUtils.h"
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stddef.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to store the register data for many instructions, because
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we either only need it at branch points (for verification) or GC points
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and branches (for verification + type-precise register analysis).
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef enum RegisterTrackingMode {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTrackRegsBranches,
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTrackRegsGcPoints,
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTrackRegsAll
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} RegisterTrackingMode;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set this to enable dead code scanning.  This is not required, but it's
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * very useful when testing changes to the verifier (to make sure we're not
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * skipping over stuff) and for checking the optimized output from "dx".
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The only reason not to do it is that it slightly increases the time
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * required to perform verification.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEAD_CODE_SCAN  true
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool gDebugVerbose = false;      // TODO: remove this
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint gDvm__totalInstr = 0;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint gDvm__gcInstr = 0;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint gDvm__gcData = 0;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint gDvm__gcSimpleData = 0;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Selectively enable verbose debug logging -- use this to activate
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dumpRegTypes() calls for all instructions in the specified method.
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool doVerboseLogging(const Method* meth) {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;       /* COMMENT OUT to enable verbose debugging */
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const char* cd = "Landroid/net/http/Request;";
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const char* mn = "readResponse";
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V";
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (strcmp(meth->clazz->descriptor, cd) == 0 &&
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0);
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define SHOW_REG_DETAILS    (0 /*| DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS*/)
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need an extra "pseudo register" to hold the return type briefly.  It
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can be category 1 or 2, so we need two slots.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kExtraRegs  2
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define RESULT_REGISTER(_insnRegCount)  (_insnRegCount)
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Big fat collection of registers.
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct RegisterTable {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Array of RegType arrays, one per address in the method.  We only
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * set the pointers for certain addresses, based on what we're trying
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to accomplish.
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType**   addrRegs;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Number of registers we track for each instruction.  This is equal
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to the method's declared "registersSize" plus kExtraRegs.
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int         insnRegCountPlus;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * A single large alloc, with all of the storage needed for addrRegs.
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType*    regAlloc;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} RegisterTable;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkMergeTab(void);
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool isInitMethod(const Method* meth);
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType getInvocationThis(const RegType* insnRegs,\
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay);
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc, RegType checkType, bool* pOkay);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, UninitInstanceMap* uninitMap);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, RegType* workRegs, int insnIdx,
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap, int* pStartGuess);
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,\
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const RegType* addrRegs, int addr, const char* addrName,
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UninitInstanceMap* uninitMap, int displayFlags);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* bit values for dumpRegTypes() "displayFlags" */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum {
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DRT_SIMPLE          = 0,
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DRT_SHOW_REF_TYPES  = 0x01,
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DRT_SHOW_LOCALS     = 0x02,
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      RegType and UninitInstanceMap utility functions
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define __  kRegTypeUnknown
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _U  kRegTypeUninit
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _X  kRegTypeConflict
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _F  kRegTypeFloat
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _0  kRegTypeZero
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _1  kRegTypeOne
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _Z  kRegTypeBoolean
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _b  kRegTypePosByte
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _B  kRegTypeByte
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _s  kRegTypePosShort
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _S  kRegTypeShort
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _C  kRegTypeChar
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _I  kRegTypeInteger
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _J  kRegTypeLongLo
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _j  kRegTypeLongHi
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _D  kRegTypeDoubleLo
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define _d  kRegTypeDoubleHi
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merge result table for primitive values.  The table is symmetric along
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the diagonal.
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that 32-bit int/float do not merge into 64-bit long/double.  This
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is a register merge, not a widening conversion.  Only the "implicit"
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * widening within a category, e.g. byte to short, is allowed.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because Dalvik does not draw a distinction between int and float, we
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have to allow free exchange between 32-bit int/float and 64-bit
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * long/double.
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note that Uninit+Uninit=Uninit.  This holds true because we only
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * use this when the RegType value is exactly equal to kRegTypeUninit, which
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can only happen for the zeroeth entry in the table.
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "Unknown" never merges with anything known.  The only time a register
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * transitions from "unknown" to "known" is when we're executing code
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for the first time, and we handle that with a simple copy.
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconst char gDvmMergeTab[kRegTypeMAX][kRegTypeMAX] =
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* chk:  _  U  X  F  0  1  Z  b  B  s  S  C  I  J  j  D  d */
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*_*/ __,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*U*/ _X,_U,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*X*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*F*/ _X,_X,_X,_F,_F,_F,_F,_F,_F,_F,_F,_F,_F,_X,_X,_X,_X },
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*0*/ _X,_X,_X,_F,_0,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*1*/ _X,_X,_X,_F,_Z,_1,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*Z*/ _X,_X,_X,_F,_Z,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*b*/ _X,_X,_X,_F,_b,_b,_b,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*B*/ _X,_X,_X,_F,_B,_B,_B,_B,_B,_S,_S,_I,_I,_X,_X,_X,_X },
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*s*/ _X,_X,_X,_F,_s,_s,_s,_s,_S,_s,_S,_C,_I,_X,_X,_X,_X },
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*S*/ _X,_X,_X,_F,_S,_S,_S,_S,_S,_S,_S,_I,_I,_X,_X,_X,_X },
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*C*/ _X,_X,_X,_F,_C,_C,_C,_C,_I,_C,_I,_C,_I,_X,_X,_X,_X },
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*I*/ _X,_X,_X,_F,_I,_I,_I,_I,_I,_I,_I,_I,_I,_X,_X,_X,_X },
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*J*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_J,_X },
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*j*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_j },
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*D*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_D,_X },
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { /*d*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_d },
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef __
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _U
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _X
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _F
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _0
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _1
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _Z
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _b
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _B
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _s
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _S
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _C
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _I
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _J
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _j
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _D
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef _d
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify symmetry in the conversion table.
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkMergeTab(void)
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < kRegTypeMAX; i++) {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = i; j < kRegTypeMAX; j++) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvmMergeTab[i][j] != gDvmMergeTab[j][i]) {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("Symmetry violation: %d,%d vs %d,%d\n", i, j, j, i);
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether we can convert "srcType" to "checkType", where
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "checkType" is one of the category-1 non-reference types.
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 32-bit int and float are interchangeable.
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool canConvertTo1nr(RegType srcType, RegType checkType)
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char convTab
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        [kRegType1nrEND-kRegType1nrSTART+1][kRegType1nrEND-kRegType1nrSTART+1] =
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* chk: F  0  1  Z  b  B  s  S  C  I */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*F*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*0*/ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*1*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*Z*/ 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*b*/ 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*B*/ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*s*/ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*S*/ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*C*/ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { /*I*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    };
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(checkType >= kRegType1nrSTART && checkType <= kRegType1nrEND);
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (checkType < kRegType1nrSTART || checkType > kRegType1nrEND) {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("Unexpected checkType %d (srcType=%d)\n", checkType, srcType);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //printf("convTab[%d][%d] = %d\n", srcType, checkType,
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]);
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (srcType >= kRegType1nrSTART && srcType <= kRegType1nrEND)
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (bool) convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART];
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether the types are compatible.  In Dalvik, 64-bit doubles
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and longs are interchangeable.
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool canConvertTo2(RegType srcType, RegType checkType)
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ((srcType == kRegTypeLongLo || srcType == kRegTypeDoubleLo) &&
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (checkType == kRegTypeLongLo || checkType == kRegTypeDoubleLo));
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether or not "instrType" and "targetType" are compatible,
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for purposes of getting or setting a value in a field or array.  The
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * idea is that an instruction with a category 1nr type (say, aget-short
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or iput-boolean) is accessing a static field, instance field, or array
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * entry, and we want to make sure sure that the operation is legal.
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * At a minimum, source and destination must have the same width.  We
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * further refine this to assert that "short" and "char" are not
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compatible, because the sign-extension is different on the "get"
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * operations.  As usual, "float" and "int" are interoperable.
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're not considering the actual contents of the register, so we'll
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * never get "pseudo-types" like kRegTypeZero or kRegTypePosShort.  We
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * could get kRegTypeUnknown in "targetType" if a field or array class
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * lookup failed.  Category 2 types and references are checked elsewhere.
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkFieldArrayStore1nr(RegType instrType, RegType targetType)
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (instrType == targetType)
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;            /* quick positive; most common case */
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((instrType == kRegTypeInteger && targetType == kRegTypeFloat) ||
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (instrType == kRegTypeFloat && targetType == kRegTypeInteger))
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a VM PrimitiveType enum value to the equivalent RegType value.
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType primitiveTypeToRegType(PrimitiveType primType)
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
33099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    static const struct {
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegType         regType;        /* type equivalent */
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        PrimitiveType   primType;       /* verification */
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } convTab[] = {
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* must match order of enum in Object.h */
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeBoolean,      PRIM_BOOLEAN },
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeChar,         PRIM_CHAR },
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeFloat,        PRIM_FLOAT },
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeDoubleLo,     PRIM_DOUBLE },
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeByte,         PRIM_BYTE },
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeShort,        PRIM_SHORT },
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeInteger,      PRIM_INT },
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        { kRegTypeLongLo,       PRIM_LONG },
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // PRIM_VOID
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    };
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (primType < 0 || primType > (int) (sizeof(convTab) / sizeof(convTab[0])))
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return kRegTypeUnknown;
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(convTab[primType].primType == primType);
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return convTab[primType].regType;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new uninitialized instance map.
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The map is allocated and populated with address entries.  The addresses
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * appear in ascending order to allow binary searching.
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Very few methods have 10 or more new-instance instructions; the
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * majority have 0 or 1.  Occasionally a static initializer will have 200+.
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectUninitInstanceMap* dvmCreateUninitInstanceMap(const Method* meth,
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const InsnFlags* insnFlags, int newInstanceCount)
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnsSize = dvmGetMethodInsnsSize(meth);
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns = meth->insns;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isInit = false;
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx, addr;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isInitMethod(meth)) {
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newInstanceCount++;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        isInit = true;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate the header and map as a single unit.
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: consider having a static instance so we can avoid allocations.
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I don't think the verifier is guaranteed to be single-threaded when
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * running in the VM (rather than dexopt), so that must be taken into
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * account.
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int size = offsetof(UninitInstanceMap, map) +
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                newInstanceCount * sizeof(uninitMap->map[0]);
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uninitMap = calloc(1, size);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (uninitMap == NULL)
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uninitMap->numEntries = newInstanceCount;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = 0;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isInit) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        uninitMap->map[idx++].addr = kUninitThisArgAddr;
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through and find the new-instance instructions.
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (addr = 0; addr < insnsSize; /**/) {
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int width = dvmInsnGetWidth(insnFlags, addr);
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((*insns & 0xff) == OP_NEW_INSTANCE)
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uninitMap->map[idx++].addr = addr;
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        addr += width;
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insns += width;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx == newInstanceCount);
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return uninitMap;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free the map.
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeUninitInstanceMap(UninitInstanceMap* uninitMap)
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(uninitMap);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the class object associated with the instruction at "addr".
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the map slot index, or -1 if the address isn't listed in the map
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (shouldn't happen) or if a class is already associated with the address
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (bad bytecode).
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entries, once set, do not change -- a given address can only allocate
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one type of object.
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmSetUninitInstance(UninitInstanceMap* uninitMap, int addr,
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz)
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != NULL);
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* TODO: binary search when numEntries > 8 */
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (idx = uninitMap->numEntries - 1; idx >= 0; idx--) {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (uninitMap->map[idx].addr == addr) {
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (uninitMap->map[idx].clazz != NULL &&
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                uninitMap->map[idx].clazz != clazz)
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: addr %d already set to %p, not setting to %p\n",
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    addr, uninitMap->map[idx].clazz, clazz);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;          // already set to something else??
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uninitMap->map[idx].clazz = clazz;
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return idx;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOG_VFY("VFY: addr %d not found in uninit map\n", addr);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(false);      // shouldn't happen
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the class object at the specified index.
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetUninitInstance(const UninitInstanceMap* uninitMap, int idx)
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx >= 0 && idx < uninitMap->numEntries);
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return uninitMap->map[idx].clazz;
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* determine if "type" is actually an object reference (init/uninit/zero) */
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool regTypeIsReference(RegType type) {
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (type > kRegTypeMAX || type == kRegTypeUninit ||
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type == kRegTypeZero);
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* determine if "type" is an uninitialized object reference */
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool regTypeIsUninitReference(RegType type) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ((type & kRegTypeUninitMask) == kRegTypeUninit);
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* convert the initialized reference "type" to a ClassObject pointer */
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* (does not expect uninit ref types or "zero") */
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* regTypeInitializedReferenceToClass(RegType type)
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(regTypeIsReference(type) && type != kRegTypeZero);
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((type & 0x01) == 0) {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (ClassObject*) type;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOG_VFY("VFY: attempted to use uninitialized reference\n");
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* extract the index into the uninitialized instance map table */
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int regTypeToUninitIndex(RegType type) {
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(regTypeIsUninitReference(type));
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift;
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* convert the reference "type" to a ClassObject pointer */
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* regTypeReferenceToClass(RegType type,
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UninitInstanceMap* uninitMap)
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(regTypeIsReference(type) && type != kRegTypeZero);
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regTypeIsUninitReference(type)) {
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(uninitMap != NULL);
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(type));
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (ClassObject*) type;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* convert the ClassObject pointer to an (initialized) register type */
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline RegType regTypeFromClass(ClassObject* clazz) {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u4) clazz;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* return the RegType for the uninitialized reference in slot "uidx" */
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType regTypeFromUninitIndex(int uidx) {
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (u4) (kRegTypeUninit | (uidx << kRegTypeUninitShift));
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Signature operations
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Is this method a constructor?
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool isInitMethod(const Method* meth)
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (*meth->name == '<' && strcmp(meth->name+1, "init>") == 0);
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Is this method a class initializer?
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool isClassInitMethod(const Method* meth)
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (*meth->name == '<' && strcmp(meth->name+1, "clinit>") == 0);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up a class reference given as a simple string descriptor.
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* lookupClassByDescriptor(const Method* meth,
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* pDescriptor, bool* pOkay)
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The javac compiler occasionally puts references to nonexistent
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * classes in signatures.  For example, if you have a non-static
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * inner class with no constructor, the compiler provides
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a private <init> for you.  Constructing the class
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * requires <init>(parent), but the outer class can't call
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that because the method is private.  So the compiler
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * generates a package-scope <init>(parent,bogus) method that
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just calls the regular <init> (the "bogus" part being necessary
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to distinguish the signature of the synthetic method).
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Treating the bogus class as an instance of java.lang.Object
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * allows the verifier to process the class successfully.
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("Looking up '%s'\n", typeStr);
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindClassNoInit(pDescriptor, meth->clazz->classLoader);
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearOptException(dvmThreadSelf());
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strchr(pDescriptor, '$') != NULL) {
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("VFY: unable to find class referenced in signature (%s)\n",
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDescriptor);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to find class referenced in signature (%s)\n",
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDescriptor);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDescriptor[0] == '[') {
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We are looking at an array descriptor. */
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * There should never be a problem loading primitive arrays.
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid char in signature in '%s'\n",
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pDescriptor);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *pOkay = false;
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Try to continue with base array type.  This will let
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * us pass basic stuff (e.g. get array len) that wouldn't
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * fly with an Object.  This is NOT correct if the
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * missing type is a primitive array, but we should never
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * have a problem loading those.  (I'm not convinced this
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * is correct or even useful.  Just use Object here?)
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = dvmFindClassNoInit("[Ljava/lang/Object;",
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->clazz->classLoader);
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (pDescriptor[0] == 'L') {
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We are looking at a non-array reference descriptor;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * try to continue with base reference type.
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = gDvm.classJavaLangObject;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We are looking at a primitive type. */
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz == NULL) {
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsPrimitiveClass(clazz)) {
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = NULL;
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up a class reference in a signature.  Could be an arg or the
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return value.
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Advances "*pSig" to the last character in the signature (that is, to
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the ';').
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this is also expected to verify the signature.
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = *pSig;
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* endp = sig;
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sig != NULL && *sig == 'L');
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*++endp != ';' && *endp != '\0')
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*endp != ';') {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    endp++;    /* Advance past the ';'. */
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int typeLen = endp - sig;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char typeStr[typeLen+1]; /* +1 for the '\0' */
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(typeStr, sig, typeLen);
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typeStr[typeLen] = '\0';
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return lookupClassByDescriptor(meth, typeStr, pOkay);
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up an array class reference in a signature.  Could be an arg or the
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return value.
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Advances "*pSig" to the last character in the signature.
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this is also expected to verify the signature.
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* lookupSignatureArrayClass(const Method* meth,
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char** pSig, bool* pOkay)
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = *pSig;
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* endp = sig;
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sig != NULL && *sig == '[');
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* find the end */
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*++endp == '[' && *endp != '\0')
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ;
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*endp == 'L') {
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (*++endp != ';' && *endp != '\0')
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ;
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*endp != ';') {
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int typeLen = endp - sig +1;
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char typeStr[typeLen+1];
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(typeStr, sig, typeLen);
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typeStr[typeLen] = '\0';
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pSig = endp;
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return lookupClassByDescriptor(meth, typeStr, pOkay);
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the register types for the first instruction in the method based on
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the method signature.
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This has the side-effect of validating the signature.
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool setTypesFromSignature(const Method* meth, RegType* regTypes,
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap)
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexParameterIterator iterator;
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int actualArgs, expectedArgs, argStart;
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool okay = true;
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexParameterIteratorInit(&iterator, &meth->prototype);
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    argStart = meth->registersSize - meth->insSize;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    expectedArgs = meth->insSize;     /* long/double count as two */
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actualArgs = 0;
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(argStart >= 0);      /* should have been verified earlier */
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Include the "this" pointer.
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(meth)) {
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If this is a constructor for a class other than java.lang.Object,
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * mark the first ("this") argument as uninitialized.  This restricts
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field access until the superclass constructor is called.
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (isInitMethod(meth) && meth->clazz != gDvm.classJavaLangObject) {
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int uidx = dvmSetUninitInstance(uninitMap, kUninitThisArgAddr,
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            meth->clazz);
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(uidx == 0);
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = regTypeFromUninitIndex(uidx);
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = regTypeFromClass(meth->clazz);
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualArgs++;
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (;;) {
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor == NULL) {
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualArgs >= expectedArgs) {
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: expected %d args, found more (%s)\n",
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                expectedArgs, descriptor);
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (*descriptor) {
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'L':
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case '[':
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We assume that reference arguments are initialized.  The
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * only way it could be otherwise (assuming the caller was
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * verified) is if the current method is <init>, but in that
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * case it's effectively considered initialized the instant
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we reach here (in the sense that we can return without
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * doing anything or call virtual methods).
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz =
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lookupClassByDescriptor(meth, descriptor, &okay);
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!okay)
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bad_sig;
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'Z':
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeBoolean;
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'C':
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeChar;
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'B':
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeByte;
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'I':
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeInteger;
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'S':
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeShort;
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'F':
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeFloat;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'D':
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeDoubleLo;
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs +1] = kRegTypeDoubleHi;
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs += 2;
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'J':
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs] = kRegTypeLongLo;
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypes[argStart + actualArgs +1] = kRegTypeLongHi;
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs += 2;
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unexpected signature type char '%c'\n", *descriptor);
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actualArgs != expectedArgs) {
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bad_sig;
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor = dexProtoGetReturnType(&meth->prototype);
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Validate return type.  We don't do the type lookup; just want to make
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sure that it has the right format.  Only major difference from the
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method argument format is that 'V' is supported.
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (*descriptor) {
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'I':
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'C':
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'S':
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'B':
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'Z':
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*(descriptor+1) != '\0')
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case '[':
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* single/multi, object/primitive */
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (*++descriptor == '[')
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*descriptor == 'L') {
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (*++descriptor != ';' && *descriptor != '\0')
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ;
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (*descriptor != ';')
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bad_sig;
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (*(descriptor+1) != '\0')
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bad_sig;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'L':
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* could be more thorough here, but shouldn't be required */
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (*++descriptor != ';' && *descriptor != '\0')
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ;
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*descriptor != ';')
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bad_sig;
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//fail:
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    LOG_VFY_METH(meth, "VFY:  bad sig\n");
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//    return false;
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbad_sig:
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: bad signature '%s' for %s.%s\n",
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc, meth->clazz->descriptor, meth->name);
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(desc);
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the register type for the method.  We can't just use the
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * already-computed DalvikJniReturnType, because if it's a reference type
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to do the class lookup.
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returned references are assumed to be initialized.
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns kRegTypeUnknown for "void".
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType getMethodReturnType(const Method* meth)
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type;
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor = dexProtoGetReturnType(&meth->prototype);
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (*descriptor) {
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'I':
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeInteger;
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'C':
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeChar;
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'S':
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeShort;
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'B':
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeByte;
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'Z':
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeBoolean;
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeUnknown;
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeFloat;
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeDoubleLo;
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeLongLo;
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'L':
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case '[':
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool okay = true;
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* clazz =
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                lookupClassByDescriptor(meth, descriptor, &okay);
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(okay);
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type = regTypeFromClass(clazz);
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* we verified signature return type earlier, so this is impossible */
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeConflict;
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return type;
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a single-character signature value (i.e. a primitive type) to
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the corresponding RegType.  This is intended for access to object fields
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * holding primitive types.
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns kRegTypeUnknown for objects, arrays, and void.
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType primSigCharToRegType(char sigChar)
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type;
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (sigChar) {
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'I':
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeInteger;
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'C':
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeChar;
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'S':
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeShort;
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'B':
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeByte;
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'Z':
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeBoolean;
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeFloat;
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeDoubleLo;
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeLongLo;
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'L':
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case '[':
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeUnknown;
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        type = kRegTypeUnknown;
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return type;
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify the arguments to a method.  We're executing in "method", making
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a call to the method reference in vB.
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this is a "direct" invoke, we allow calls to <init>.  For calls to
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <init>, the first argument may be an uninitialized reference.  Otherwise,
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls to anything starting with '<' will be rejected, as will any
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uninitialized reference arguments.
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For non-static method calls, this will verify that the method call is
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * appropriate for the "this" argument.
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The method reference is in vBBBB.  The "isRange" parameter determines
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whether we use 0-4 "args" values or a range of registers defined by
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * vAA and vCCCC.
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Widening conversions on integers and references are allowed, but
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * narrowing conversions are not.
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the resolved method on success, NULL (and sets "*pOkay" to "false")
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on failure.
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount, const DecodedInstruction* pDecInsn,
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isSuper, bool* pOkay)
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* resMethod;
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* sigOriginal = NULL;
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Resolve the method.  This could be an abstract or concrete method
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * depending on what sort of call we're making.
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodType == METHOD_INTERFACE) {
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (resMethod == NULL) {
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* failed; print a meaningful failure message */
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexMethodId* pMethodId;
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* methodName;
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* methodDesc;
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* classDescriptor;
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB);
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodName = dexStringById(pDexFile, pMethodId->nameIdx);
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!gDvm.optimizing) {
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* dotMissingClass = dvmDescriptorToDot(classDescriptor);
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* dotMethClass = dvmDescriptorToDot(meth->clazz->descriptor);
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //char* curMethodDesc =
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    dexProtoCopyMethodDescriptor(&meth->prototype);
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Could not find method %s.%s, referenced from "
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 "method %s.%s\n",
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 dotMissingClass, methodName/*, methodDesc*/,
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 dotMethClass, meth->name/*, curMethodDesc*/);
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(dotMissingClass);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(dotMethClass);
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //free(curMethodDesc);
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n",
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmMethodTypeStr(methodType), pDecInsn->vB,
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            classDescriptor, methodName, methodDesc);
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(methodDesc);
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Only time you can explicitly call a method starting with '<' is when
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * making a "direct" invocation on "<init>".  There are additional
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * restrictions but we don't enforce them here.
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (resMethod->name[0] == '<') {
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodType != METHOD_DIRECT || !isInitMethod(resMethod)) {
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: invalid call to %s.%s\n",
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    resMethod->clazz->descriptor, resMethod->name);
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we're using invoke-super(method), make sure that the executing
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method's class' superclass has a vtable entry for the target method.
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isSuper) {
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(methodType == METHOD_VIRTUAL);
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* super = meth->clazz->super;
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (super == NULL || resMethod->methodIndex > super->vtableCount) {
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: invalid invoke-super from %s.%s to super %s.%s %s\n",
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->clazz->descriptor, meth->name,
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    (super == NULL) ? "-" : super->descriptor,
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    resMethod->name, desc);
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We use vAA as our expected arg count, rather than resMethod->insSize,
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because we need to match the call to the signature.  Also, we might
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might be calling through an abstract method definition (which doesn't
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have register count values).
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = sigOriginal;
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int expectedArgs = pDecInsn->vA;
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int actualArgs = 0;
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!isRange && expectedArgs > 5) {
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invalid arg count in non-range invoke (%d)\n",
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA);
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (expectedArgs > meth->outsSize) {
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invalid arg count (%d) exceeds outsSize (%d)\n",
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            expectedArgs, meth->outsSize);
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*sig++ != '(')
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bad_sig;
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Check the "this" argument, which must be an instance of the class
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that declared the method.  For an interface class, we don't do the
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * full interface merge, so we can't do a rigorous check here (which
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is okay since we have to do it at runtime).
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsStaticMethod(resMethod)) {
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* actualThisRef;
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegType actualArgType;
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            pOkay);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!*pOkay)
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: 'this' arg must be initialized\n");
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (methodType != METHOD_INTERFACE && actualArgType != kRegTypeZero) {
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualThisRef = regTypeReferenceToClass(actualArgType, uninitMap);
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmInstanceof(actualThisRef, resMethod->clazz)) {
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: 'this' arg '%s' not instance of '%s'\n",
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        actualThisRef->descriptor,
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resMethod->clazz->descriptor);
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto fail;
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualArgs++;
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Process the target method's signature.  This signature may or may not
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have been verified, so we can't assume it's properly formed.
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (*sig != '\0' && *sig != ')') {
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualArgs >= expectedArgs) {
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: expected %d args, found more (%c)\n",
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                expectedArgs, *sig);
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 getReg;
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (isRange)
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getReg = pDecInsn->vC + actualArgs;
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getReg = pDecInsn->arg[actualArgs];
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (*sig) {
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'L':
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz = lookupSignatureClass(meth, &sig, pOkay);
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!*pOkay)
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bad_sig;
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyRegisterType(insnRegs, insnRegCount, getReg,
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    regTypeFromClass(clazz), pOkay);
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!*pOkay) {
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: bad arg %d (into %s)\n",
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            actualArgs, clazz->descriptor);
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bad_sig;
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case '[':
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz =
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lookupSignatureArrayClass(meth, &sig, pOkay);
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!*pOkay)
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bad_sig;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifyRegisterType(insnRegs, insnRegCount, getReg,
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    regTypeFromClass(clazz), pOkay);
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!*pOkay) {
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: bad arg %d (into %s)\n",
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            actualArgs, clazz->descriptor);
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bad_sig;
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'Z':
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeBoolean, pOkay);
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'C':
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeChar, pOkay);
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'B':
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeByte, pOkay);
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'I':
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeInteger, pOkay);
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'S':
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeShort, pOkay);
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'F':
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeFloat, pOkay);
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs++;
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'D':
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeDoubleLo, pOkay);
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs += 2;
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'J':
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(insnRegs, insnRegCount, getReg,
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeLongLo, pOkay);
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            actualArgs += 2;
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: invocation target: bad signature type char '%c'\n",
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *sig);
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bad_sig;
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sig++;
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*sig != ')') {
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invocation target: bad signature '%s'\n", desc);
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(desc);
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bad_sig;
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actualArgs != expectedArgs) {
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bad_sig;
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(sigOriginal);
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return resMethod;
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbad_sig:
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (resMethod != NULL) {
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY:  rejecting call to %s.%s %s\n",
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resMethod->clazz->descriptor, resMethod->name, desc);
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(desc);
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(sigOriginal);
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pOkay = false;
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the class object for the type of data stored in a field.  This isn't
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stored in the Field struct, so we have to recover it from the signature.
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This only works for reference types.  Don't call this for primitive types.
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we can't find the class, we return java.lang.Object, so that
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verification can continue if a field is only accessed in trivial ways.
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* getFieldClass(const Method* meth, const Field* field)
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* fieldClass;
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* signature = field->signature;
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((*signature == 'L') || (*signature == '[')) {
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldClass = dvmFindClassNoInit(signature,
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->clazz->classLoader);
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fieldClass == NULL) {
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearOptException(dvmThreadSelf());
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("VFY: unable to find class '%s' for field %s.%s, trying Object\n",
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            field->signature, meth->clazz->descriptor, field->name);
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldClass = gDvm.classJavaLangObject;
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsPrimitiveClass(fieldClass));
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return fieldClass;
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Register operations
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the type of register N, verifying that the register is valid.
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pOkay" to false if the register number is out of range.
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline RegType getRegisterType(const RegType* insnRegs,
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount, u4 vsrc, bool* pOkay)
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type;
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (vsrc >= (u4) insnRegCount) {
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return kRegTypeUnknown;
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return insnRegs[vsrc];
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the value from a register, and cast it to a ClassObject.  Sets
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pOkay" to false if something fails.
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This fails if the register holds an uninitialized class.
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the register holds kRegTypeZero, this returns a NULL pointer.
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* getClassFromRegister(const RegType* insnRegs,
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount, u4 vsrc, bool* pOkay)
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = NULL;
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type;
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* get the element type of the array held in vsrc */
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay)
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if "always zero", we allow it to fail at runtime */
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (type == kRegTypeZero)
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!regTypeIsReference(type)) {
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vsrc, type);
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regTypeIsUninitReference(type)) {
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = regTypeInitializedReferenceToClass(type);
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the "this" pointer from a non-static method invocation.  This
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns the RegType so the caller can decide whether it needs the
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reference to be initialized or not.  (Can also return kRegTypeZero
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the reference can only be zero at this point.)
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The argument count is in vA, and the first argument is in vC, for both
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "simple" and "range" versions.  We just need to make sure vA is >= 1
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and then return vC.
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType getInvocationThis(const RegType* insnRegs,
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay)
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType thisType = kRegTypeUnknown;
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDecInsn->vA < 1) {
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invoke lacks 'this'\n");
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* get the element type of the array held in vsrc */
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pOkay);
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay) {
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: failed to get this from register %u\n", pDecInsn->vC);
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!regTypeIsReference(thisType)) {
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vC, thisType);
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return thisType;
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the type of register N, verifying that the register is valid.  If
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "newType" is the "Lo" part of a 64-bit value, register N+1 will be
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set to "newType+1".
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pOkay" to false if the register number is out of range.
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void setRegisterType(RegType* insnRegs, const int insnRegCount,
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vdst, RegType newType, bool* pOkay)
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("set-reg v%u = %d\n", vdst, newType);
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (newType) {
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeUnknown:
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeBoolean:
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeOne:
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeByte:
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypePosByte:
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeShort:
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypePosShort:
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeChar:
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeInteger:
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeFloat:
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeZero:
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vdst >= (u4) insnRegCount) {
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[vdst] = newType;
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeLongLo:
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeDoubleLo:
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vdst+1 >= (u4) insnRegCount) {
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[vdst] = newType;
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[vdst+1] = newType+1;
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeLongHi:
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeDoubleHi:
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* should never set these explicitly */
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeUninit:
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (regTypeIsReference(newType)) {
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (vdst >= (u4) insnRegCount) {
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *pOkay = false;
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[vdst] = newType;
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * In most circumstances we won't see a reference to a primitive
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class here (e.g. "D"), since that would mean the object in the
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * register is actually a primitive type.  It can happen as the
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * result of an assumed-successful check-cast instruction in
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * which the second argument refers to a primitive class.  (In
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * practice, such an instruction will always throw an exception.)
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This is not an issue for instructions like const-class, where
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the object in the register is a java.lang.Class instance.
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* bad - fall through */
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeConflict:      // should only be set during a merge
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("Unexpected set type %d\n", newType);
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that the contents of the specified register have the specified
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * type (or can be converted to it through an implicit widening conversion).
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In theory we could use this to modify the type of the source register,
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * e.g. a generic 32-bit constant, once used as a float, would thereafter
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * remain a float.  There is no compelling reason to require this though.
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "vsrc" is a reference, both it and the "vsrc" register must be
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialized ("vsrc" may be Zero).  This will verify that the value in
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the register is an instance of checkType, or if checkType is an
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interface, verify that the register implements checkType.
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc, RegType checkType, bool* pOkay)
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (vsrc >= (u4) insnRegCount) {
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType srcType = insnRegs[vsrc];
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("check-reg v%u = %d\n", vsrc, checkType);
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (checkType) {
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeFloat:
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeBoolean:
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypePosByte:
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeByte:
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypePosShort:
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeShort:
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeChar:
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeInteger:
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!canConvertTo1nr(srcType, checkType)) {
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc, srcType, checkType);
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeLongLo:
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeDoubleLo:
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vsrc+1 >= (u4) insnRegCount) {
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register2 v%u out of range (%d)\n",
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc, insnRegCount);
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (insnRegs[vsrc+1] != srcType+1) {
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!canConvertTo2(srcType, checkType)) {
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vsrc, srcType, checkType);
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeLongHi:
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeDoubleHi:
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeZero:
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeOne:
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeUnknown:
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeConflict:
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* should never be checking for these explicitly */
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kRegTypeUninit:
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure checkType is initialized reference */
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!regTypeIsReference(checkType)) {
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unexpected check type %d\n", checkType);
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (regTypeIsUninitReference(checkType)) {
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure srcType is initialized reference or always-NULL */
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!regTypeIsReference(srcType)) {
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (regTypeIsUninitReference(srcType)) {
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* if the register isn't Zero, make sure it's an instance of check */
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (srcType != kRegTypeZero) {
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* srcClass = regTypeInitializedReferenceToClass(srcType);
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* checkClass = regTypeInitializedReferenceToClass(checkType);
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(srcClass != NULL);
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(checkClass != NULL);
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsInterfaceClass(checkClass)) {
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * All objects implement all interfaces as far as the
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * verifier is concerned.  The runtime has to sort it out.
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * See comments above findCommonSuperclass.
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (srcClass != checkClass &&
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !dvmImplements(srcClass, checkClass))
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: %s does not implement %s\n",
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            srcClass->descriptor, checkClass->descriptor);
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    *pOkay = false;
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                */
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmInstanceof(srcClass, checkClass)) {
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: %s is not instance of %s\n",
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            srcClass->descriptor, checkClass->descriptor);
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    *pOkay = false;
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the type of the "result" register.  Mostly this exists to expand
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "insnRegCount" to encompass the result register.
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType newType, bool* pOkay)
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setRegisterType(insnRegs, insnRegCount + kExtraRegs,
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RESULT_REGISTER(insnRegCount), newType, pOkay);
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Update all registers holding "uninitType" to instead hold the
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * corresponding initialized reference type.  This is called when an
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * appropriate <init> method is invoked -- all copies of the reference
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * must be marked as initialized.
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap, RegType uninitType, bool* pOkay)
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType initType;
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, changed;
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(uninitType));
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uninitType, regTypeToUninitIndex(uninitType));
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initType = regTypeFromClass(clazz);
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    changed = 0;
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < insnRegCount; i++) {
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (insnRegs[i] == uninitType) {
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[i] = initType;
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            changed++;
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("VFY: marked %d registers as initialized\n", changed);
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(changed > 0);
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return;
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're creating a new instance of class C at address A.  Any registers
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * holding instances previously created at address A must be initialized
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by now.  If not, we mark them as "conflict" to prevent them from being
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used (otherwise, markRefsAsInitialized would mark the old ones and the
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * new ones at the same time).
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void markUninitRefsAsInvalid(RegType* insnRegs, int insnRegCount,
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap, RegType uninitType)
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, changed;
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    changed = 0;
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < insnRegCount; i++) {
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (insnRegs[i] == uninitType) {
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnRegs[i] = kRegTypeConflict;
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            changed++;
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //if (changed)
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    LOGD("VFY: marked %d uninitialized registers as invalid\n", changed);
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the start of the register set for the specified instruction in
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the current method.
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline RegType* getRegisterLine(const RegisterTable* regTable,
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int insnIdx)
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return regTable->addrRegs[insnIdx];
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy a bunch of registers.
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void copyRegisters(RegType* dst, const RegType* src,
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numRegs)
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(dst, src, numRegs * sizeof(RegType));
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a bunch of registers.
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns 0 if they match.  Using this for a sort is unwise, since the
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * value can change based on machine endianness.
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline int compareRegisters(const RegType* src1, const RegType* src2,
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numRegs)
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return memcmp(src1, src2, numRegs * sizeof(RegType));
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Register type categories, for type checking.
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec says category 1 includes boolean, byte, char, short, int, float,
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reference, and returnAddress.  Category 2 includes long and double.
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We treat object references separately, so we have "category1nr".  We
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * don't support jsr/ret, so there is no "returnAddress" type.
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef enum TypeCategory {
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTypeCategoryUnknown = 0,
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTypeCategory1nr,           // byte, char, int, float, boolean
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTypeCategory2,             // long, double
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kTypeCategoryRef,           // object reference
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} TypeCategory;
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if "type" matches "cat".  All we're really looking for here is that
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're not mixing and matching 32-bit and 64-bit quantities, and we're
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not mixing references with numerics.  (For example, the arguments to
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "a < b" could be integers of different sizes, but they must both be
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * integers.  Dalvik is less specific about int vs. float, so we treat them
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as equivalent here.)
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For category 2 values, "type" must be the "low" half of the value.
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pOkay" to false if not.
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkTypeCategory(RegType type, TypeCategory cat, bool* pOkay)
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (cat) {
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kTypeCategory1nr:
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (type) {
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeFloat:
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeZero:
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeOne:
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeBoolean:
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypePosByte:
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeByte:
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypePosShort:
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeShort:
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeChar:
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeInteger:
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kTypeCategory2:
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (type) {
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeLongLo:
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeDoubleLo:
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kTypeCategoryRef:
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type != kRegTypeZero && !regTypeIsReference(type))
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For a category 2 register pair, verify that "typeh" is the appropriate
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * high part for "typel".
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does not verify that "typel" is in fact the low part of a 64-bit
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * register pair.
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkWidePair(RegType typel, RegType typeh, bool* pOkay)
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((typeh != typel+1))
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement category-1 "move" instructions.  Copy a 32-bit value from
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vsrc" to "vdst".
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "insnRegCount" is the number of registers available.  The "vdst" and
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vsrc" values are checked against this.
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc, TypeCategory cat, bool* pOkay)
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay)
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(type, cat, pOkay);
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay)
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay) {
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement category-2 "move" instructions.  Copy a 64-bit value from
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "vsrc" to "vdst".  This copies both halves of the register.
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc, bool* pOkay)
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pOkay);
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay) {
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(typel, kTypeCategory2, pOkay);
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkWidePair(typel, typeh, pOkay);
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay)
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay) {
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement "move-result".  Copy the category-1 value from the result
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * register to another register, and reset the result register.
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We can't just call copyRegister1 with an altered insnRegCount,
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because that would affect the test on "vdst" as well.
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vdst, TypeCategory cat, bool* pOkay)
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type;
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc;
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    vsrc = RESULT_REGISTER(insnRegCount);
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay)
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(type, cat, pOkay);
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay) {
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insnRegs[vsrc] = kRegTypeUnknown;
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay) {
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vdst, vsrc, cat, type);
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implement "move-result-wide".  Copy the category-2 value from the result
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * register to another register, and reset the result register.
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We can't just call copyRegister2 with an altered insnRegCount,
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because that would affect the test on "vdst" as well.
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vdst, bool* pOkay)
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType typel, typeh;
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 vsrc;
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    vsrc = RESULT_REGISTER(insnRegCount);
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1, pOkay);
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay) {
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(typel, kTypeCategory2, pOkay);
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkWidePair(typel, typeh, pOkay);
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay) {
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insnRegs[vsrc] = kRegTypeUnknown;
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insnRegs[vsrc+1] = kRegTypeUnknown;
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!*pOkay) {
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vdst, vsrc, typel, typeh);
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify types for a simple two-register instruction (e.g. "neg-int").
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "dstType" is stored into vA, and "srcType" is verified against vB.
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkUnop(RegType* insnRegs, const int insnRegCount,
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're performing an operation like "and-int/2addr" that can be
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * performed on booleans as well as integers.  We get no indication of
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean-ness, but we can infer it from the types of the arguments.
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assumes we've already validated reg1/reg2.
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if both args are Boolean, Zero, or One.
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool upcastBooleanOp(RegType* insnRegs, const int insnRegCount,
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 reg1, u4 reg2)
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType type1, type2;
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    type1 = insnRegs[reg1];
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    type2 = insnRegs[reg2];
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero ||
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type1 == kRegTypeOne) &&
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (type2 == kRegTypeBoolean || type2 == kRegTypeZero ||
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type2 == kRegTypeOne))
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify types for A two-register instruction with a literal constant
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (e.g. "add-int/lit8").  "dstType" is stored into vA, and "srcType" is
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verified against vB.
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "checkBooleanOp" is set, we use the constant value in vC.
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkLitop(RegType* insnRegs, const int insnRegCount,
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool checkBooleanOp, bool* pOkay)
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay && checkBooleanOp) {
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dstType == kRegTypeInteger);
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* check vB with the call, then check the constant manually */
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            && (pDecInsn->vC == 0 || pDecInsn->vC == 1))
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dstType = kRegTypeBoolean;
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify types for a simple three-register instruction (e.g. "add-int").
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "dstType" is stored into vA, and "srcType1"/"srcType2" are verified
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * against vB/vC.
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkBinop(RegType* insnRegs, const int insnRegCount,
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType srcType2, bool checkBooleanOp, bool* pOkay)
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1, pOkay);
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2, pOkay);
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay && checkBooleanOp) {
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dstType == kRegTypeInteger);
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dstType = kRegTypeBoolean;
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify types for a binary "2addr" operation.  "srcType1"/"srcType2"
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are verified against vA/vB, then "dstType" is stored into vA.
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType srcType2, bool checkBooleanOp, bool* pOkay)
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1, pOkay);
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2, pOkay);
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay && checkBooleanOp) {
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dstType == kRegTypeInteger);
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dstType = kRegTypeBoolean;
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Register merge
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "class depth" of a class.  This is the distance from the
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class to the top of the tree, chasing superclass links.  java.lang.Object
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has a class depth of 0.
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int getClassDepth(ClassObject* clazz)
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depth = 0;
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (clazz->super != NULL) {
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = clazz->super;
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        depth++;
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return depth;
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given two classes, walk up the superclass tree to find a common
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ancestor.  (Called from findCommonSuperclass().)
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: consider caching the class depth in the class object so we don't
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have to search for it here.
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* digForSuperclass(ClassObject* c1, ClassObject* c2)
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int depth1, depth2;
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    depth1 = getClassDepth(c1);
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    depth2 = getClassDepth(c2);
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDebugVerbose) {
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("COMMON: %s(%d) + %s(%d)\n",
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            c1->descriptor, depth1, c2->descriptor, depth2);
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* pull the deepest one up */
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (depth1 > depth2) {
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (depth1 > depth2) {
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            c1 = c1->super;
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depth1--;
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (depth2 > depth1) {
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            c2 = c2->super;
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            depth2--;
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* walk up in lock-step */
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (c1 != c2) {
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        c1 = c1->super;
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        c2 = c2->super;
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(c1 != NULL && c2 != NULL);
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDebugVerbose) {
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("      : --> %s\n", c1->descriptor);
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return c1;
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merge two array classes.  We can't use the general "walk up to the
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass" merge because the superclass of an array is always Object.
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We want String[] + Integer[] = Object[].  This works for higher dimensions
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as well, e.g. String[][] + Integer[][] = Object[][].
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If Foo1 and Foo2 are subclasses of Foo, Foo1[] + Foo2[] = Foo[].
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If Class implements Type, Class[] + Type[] = Type[].
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the dimensions don't match, we want to convert to an array of Object
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with the least dimension, e.g. String[][] + String[][][][] = Object[][].
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This gets a little awkward because we may have to ask the VM to create
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a new array type with the appropriate element and dimensions.  However, we
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shouldn't be doing this often.
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findCommonArraySuperclass(ClassObject* c1, ClassObject* c2)
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* arrayClass = NULL;
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* commonElem;
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, numDims;
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(c1->arrayDim > 0);
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(c2->arrayDim > 0);
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (c1->arrayDim == c2->arrayDim) {
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //commonElem = digForSuperclass(c1->elementClass, c2->elementClass);
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        commonElem = findCommonSuperclass(c1->elementClass, c2->elementClass);
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        numDims = c1->arrayDim;
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c1->arrayDim < c2->arrayDim)
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            numDims = c1->arrayDim;
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            numDims = c2->arrayDim;
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        commonElem = c1->super;     // == java.lang.Object
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* walk from the element to the (multi-)dimensioned array type */
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < numDims; i++) {
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        arrayClass = dvmFindArrayClassForElement(commonElem);
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        commonElem = arrayClass;
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("ArrayMerge '%s' + '%s' --> '%s'\n",
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        c1->descriptor, c2->descriptor, arrayClass->descriptor);
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return arrayClass;
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the first common superclass of the two classes.  We're not
2133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interested in common interfaces.
2134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The easiest way to do this for concrete classes is to compute the "class
2136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * depth" of each, move up toward the root of the deepest one until they're
2137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * at the same depth, then walk both up to the root until they match.
2138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If both classes are arrays of non-primitive types, we need to merge
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * based on array depth and element type.
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If one class is an interface, we check to see if the other class/interface
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (or one of its predecessors) implements the interface.  If so, we return
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interface; otherwise, we return Object.
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: we continue the tradition of "lazy interface handling".  To wit,
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * suppose we have three classes:
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   One implements Fancy, Free
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   Two implements Fancy, Free
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   Three implements Free
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * where Fancy and Free are unrelated interfaces.  The code requires us
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to merge One into Two.  Ideally we'd use a common interface, which
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * gives us a choice between Fancy and Free, and no guidance on which to
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * use.  If we use Free, we'll be okay when Three gets merged in, but if
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we choose Fancy, we're hosed.  The "ideal" solution is to create a
2156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set of common interfaces and carry that around, merging further references
2157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into it.  This is a pain.  The easy solution is to simply boil them
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * down to Objects and let the runtime invokeinterface call fail, which
2159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is what we do.
2160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2)
2162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsPrimitiveClass(c1) && !dvmIsPrimitiveClass(c2));
2164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (c1 == c2)
2166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return c1;
2167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(c1) && dvmImplements(c2, c1)) {
2169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDebugVerbose)
2170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("COMMON/I1: %s + %s --> %s\n",
2171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                c1->descriptor, c2->descriptor, c1->descriptor);
2172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return c1;
2173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(c2) && dvmImplements(c1, c2)) {
2175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDebugVerbose)
2176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("COMMON/I2: %s + %s --> %s\n",
2177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                c1->descriptor, c2->descriptor, c2->descriptor);
2178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return c2;
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsArrayClass(c1) && dvmIsArrayClass(c2) &&
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        !dvmIsPrimitiveClass(c1->elementClass) &&
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        !dvmIsPrimitiveClass(c2->elementClass))
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return findCommonArraySuperclass(c1, c2);
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return digForSuperclass(c1, c2);
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merge two RegType values.
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pChanged" to "true" if the result doesn't match "type1".
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic RegType mergeTypes(RegType type1, RegType type2, bool* pChanged)
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType result;
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Check for trivial case so we don't have to hit memory.
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (type1 == type2)
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type1;
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Use the table if we can, and reject any attempts to merge something
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * from the table with a reference type.
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The uninitialized table entry at index zero *will* show up as a
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * simple kRegTypeUninit value.  Since this cannot be merged with
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anything but itself, the rules do the right thing.
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (type1 < kRegTypeMAX) {
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type2 < kRegTypeMAX) {
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = gDvmMergeTab[type1][type2];
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* simple + reference == conflict, usually */
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (type1 == kRegTypeZero)
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = type2;
2221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = kRegTypeConflict;
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type2 < kRegTypeMAX) {
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* reference + simple == conflict, usually */
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (type2 == kRegTypeZero)
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = type1;
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            else
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = kRegTypeConflict;
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* merging two references */
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regTypeIsUninitReference(type1) ||
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeIsUninitReference(type2))
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* can't merge uninit with anything but self */
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = kRegTypeConflict;
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz1 = regTypeInitializedReferenceToClass(type1);
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz2 = regTypeInitializedReferenceToClass(type2);
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* mergedClass;
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mergedClass = findCommonSuperclass(clazz1, clazz2);
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(mergedClass != NULL);
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result = regTypeFromClass(mergedClass);
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != type1)
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pChanged = true;
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Control can transfer to "nextInsn".
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Merge the registers from "workRegs" into "regTypes" at "nextInsn", and
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set the "changed" flag on the target address if the registers have changed.
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void updateRegisters(const Method* meth, InsnFlags* insnFlags,
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, int nextInsn, const RegType* workRegs)
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType* targetRegs = getRegisterLine(regTable, nextInsn);
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount = meth->registersSize;
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmInsnIsBranchTarget(insnFlags, nextInsn)) {
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("insnFlags[0x%x]=0x%08x\n", nextInsn, insnFlags[nextInsn]);
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE(" In %s.%s %s\n",
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->clazz->descriptor, meth->name, meth->descriptor);
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) {
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We haven't processed this instruction before, and we haven't
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * touched the registers here, so there's nothing to "merge".  Copy
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the registers over and mark it as changed.  (This is the only
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * way a register can transition out of "unknown", so this is not
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * just an optimization.)
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("COPY into 0x%04x\n", nextInsn);
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyRegisters(targetRegs, workRegs, insnRegCount + kExtraRegs);
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInsnSetChanged(insnFlags, nextInsn, true);
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDebugVerbose) {
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("MERGE into 0x%04x\n", nextInsn);
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dumpRegTypes(meth, insnFlags, targetRegs, 0, "targ", NULL, 0);
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dumpRegTypes(meth, insnFlags, workRegs, 0, "work", NULL, 0);
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* merge registers, set Changed only if different */
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool changed = false;
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i;
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < insnRegCount + kExtraRegs; i++) {
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed);
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDebugVerbose) {
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI(" RESULT (changed=%d)\n", changed);
2303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dumpRegTypes(meth, insnFlags, targetRegs, 0, "rslt", NULL, 0);
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (changed)
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmInsnSetChanged(insnFlags, nextInsn, true);
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Utility functions
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up an instance field, specified by "fieldIdx", that is going to be
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * accessed in object "objType".  This resolves the field and then verifies
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the class containing the field is an instance of the reference in
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "objType".
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible for "objType" to be kRegTypeZero, meaning that we might
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have a null reference.  This is a runtime problem, so we allow it,
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * skipping some of the type checks.
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In general, "objType" must be an initialized reference.  However, we
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allow it to be uninitialized if this is an "<init>" method and the field
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is declared within the "objType" class.
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns an InstField on success, returns NULL and sets "*pOkay" to false
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on failure.
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic InstField* getInstField(const Method* meth,
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    InstField* instField = NULL;
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* objClass;
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool mustBeLocal = false;
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!regTypeIsReference(objType)) {
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: attempt to access field of non-reference type %d\n",
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType);
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    instField = dvmOptResolveInstField(meth->clazz, fieldIdx);
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (instField == NULL) {
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (objType == kRegTypeZero)
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Access to fields in uninitialized objects is allowed if this is
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the <init> method for the object and the field in question is
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * declared by this class.
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    objClass = regTypeReferenceToClass(objType, uninitMap);
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(objClass != NULL);
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regTypeIsUninitReference(objType)) {
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isInitMethod(meth) || meth->clazz != objClass) {
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mustBeLocal = true;
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmInstanceof(objClass, instField->field.clazz)) {
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                instField->field.clazz->descriptor, instField->field.name,
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                objClass->descriptor);
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mustBeLocal) {
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* for uninit ref, make sure it's defined by this class, not super */
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (instField < objClass->ifields ||
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField >= objClass->ifields + objClass->ifieldCount)
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    instField->field.name, objClass->descriptor);
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return instField;
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up a static field.
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a StaticField on success, returns NULL and sets "*pOkay" to false
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on failure.
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic StaticField* getStaticField(const Method* meth, int fieldIdx,
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StaticField* staticField;
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx);
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (staticField == NULL) {
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexFieldId* pFieldId;
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pFieldId = dexGetFieldId(pDexFile, fieldIdx);
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringById(pDexFile, pFieldId->nameIdx),
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return staticField;
2428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "field" is marked "final", make sure this is the either <clinit>
2432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or <init> as appropriate.
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pOkay" to false on failure.
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkFinalFieldAccess(const Method* meth, const Field* field,
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsFinalField(field))
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure we're in the same class */
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (meth->clazz != field->clazz) {
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            field->clazz->descriptor, field->name);
2446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pOkay = false;
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The EMMA code coverage tool generates a static method that
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * modifies a private static final field.  The method is only
2453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * called by <clinit>, so the code is reasonable if not quite
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * kosher.  (Attempting to *compile* code that does something
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * like that will earn you a quick thumbs-down from javac.)
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The verifier in another popular VM doesn't complain about this,
2458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * so we're going to allow classes to modify their own static
2459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * final fields outside of class initializers.  Further testing
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * showed that modifications to instance fields are also allowed.
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure we're in the right kind of constructor */
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsStaticField(field)) {
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isClassInitMethod(meth)) {
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY_METH(meth,
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "VFY: can't modify final static field outside <clinit>\n");
2468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isInitMethod(meth)) {
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY_METH(meth,
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "VFY: can't modify final field outside <init>\n");
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *pOkay = false;
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make sure that the register type is suitable for use as an array index.
2482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets "*pOkay" to false if not.
2484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void checkArrayIndexType(const Method* meth, RegType regType,
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
2487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*pOkay) {
2489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The 1nr types are interchangeable at this level.  We could
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * do something special if we can definitively identify it as a
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * float, but there's no real value in doing so.
2493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(regType, kTypeCategory1nr, pOkay);
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!*pOkay) {
2496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
2497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regType);
2498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check constraints on constructor return.  Specifically, make sure that
2504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the "this" argument got initialized.
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "this" argument to <init> uses code offset kUninitThisArgAddr, which
2507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * puts it at the start of the list in slot 0.  If we see a register with
2508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an uninitialized slot 0 reference, we know it somehow didn't get
2509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialized.
2510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well.
2512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkConstructorReturn(const Method* meth, const RegType* insnRegs,
2514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount)
2515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!isInitMethod(meth))
2519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
2520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot);
2522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < insnRegCount; i++) {
2524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (insnRegs[i] == uninitThis) {
2525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: <init> returning without calling superclass init\n");
2526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
2527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that the target instruction is not "move-exception".  It's important
2534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the only way to execute a move-exception is as the first instruction
2535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of an exception handler.
2536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if all is well, "false" if the target instruction is
2538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * move-exception.
2539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkMoveException(const Method* meth, int insnIdx,
2541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* logNote)
2542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth));
2544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) {
2546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY("VFY: invalid use of move-exception\n");
2547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For the "move-exception" instruction at "insnIdx", which must be at an
2554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception handler address, determine the first common superclass of
2555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * all exceptions that can land here.  (For javac output, we're probably
2556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * looking at multiple spans of bytecode covered by one "try" that lands
2557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * at an exception-specific "catch", but in general the handler could be
2558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shared for multiple exceptions.)
2559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if no matching exception handler can be found, or if the
2561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception is not a subclass of Throwable.
2562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx)
2564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode;
2566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile;
2567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* commonSuper = NULL;
2568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 handlersSize;
2569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 offset;
2570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 i;
2571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = meth->clazz->pDvmDex->pDexFile;
2573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pCode = dvmGetMethodCode(meth);
2574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCode->triesSize != 0) {
2576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        handlersSize = dexGetHandlersSize(pCode);
2577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset = dexGetFirstHandlerOffset(pCode);
2578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        handlersSize = 0;
2580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset = 0;
2581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < handlersSize; i++) {
2584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexCatchIterator iterator;
2585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexCatchIteratorInit(&iterator, pCode, offset);
2586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
2588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler == NULL) {
2591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler->address == (u4) insnIdx) {
2595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz;
2596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (handler->typeIdx == kDexNoIndex)
2598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz = gDvm.classJavaLangThrowable;
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                else
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx);
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (clazz == NULL) {
2603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
2604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        handler->typeIdx,
2605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dexStringByTypeIdx(pDexFile, handler->typeIdx));
2606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
2607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (commonSuper == NULL)
2608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        commonSuper = clazz;
2609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    else
2610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        commonSuper = findCommonSuperclass(clazz, commonSuper);
2611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
2616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (commonSuper == NULL) {
2619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY_METH(meth,
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
2621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return commonSuper;
2624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the RegisterTable.
2628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Every instruction address can have a different set of information about
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * what's in which register, but for verification purposes we only need to
2631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * store it at branch target addresses (because we merge into that).
2632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * By zeroing out the storage we are effectively initializing the register
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * information to kRegTypeUnknown.
2635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initRegisterTable(const Method* meth, const InsnFlags* insnFlags,
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, RegisterTrackingMode trackRegsFor)
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnsSize = dvmGetMethodInsnsSize(meth);
2640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    regTable->insnRegCountPlus = meth->registersSize + kExtraRegs;
2643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    regTable->addrRegs = (RegType**) calloc(insnsSize, sizeof(RegType*));
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regTable->addrRegs == NULL)
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(insnsSize > 0);
2648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "All" means "every address that holds the start of an instruction".
2651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "Branches" and "GcPoints" mean just those addresses.
2652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "GcPoints" fills about half the addresses, "Branches" about 15%.
2654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int interestingCount = 0;
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //int insnCount = 0;
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < insnsSize; i++) {
2659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool interesting;
2660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (trackRegsFor) {
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsAll:
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsOpcode(insnFlags, i);
2664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsGcPoints:
2666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          dvmInsnIsBranchTarget(insnFlags, i);
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsBranches:
2670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsBranchTarget(insnFlags, i);
2671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interesting)
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interestingCount++;
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* count instructions, for display only */
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //if (dvmInsnIsOpcode(insnFlags, i))
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    insnCount++;
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    regTable->regAlloc = (RegType*)
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        calloc(regTable->insnRegCountPlus * interestingCount, sizeof(RegType));
2687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regTable->regAlloc == NULL)
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType* regPtr = regTable->regAlloc;
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < insnsSize; i++) {
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool interesting;
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (trackRegsFor) {
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsAll:
2696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsOpcode(insnFlags, i);
2697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsGcPoints:
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                          dvmInsnIsBranchTarget(insnFlags, i);
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kTrackRegsBranches:
2703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interesting = dvmInsnIsBranchTarget(insnFlags, i);
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (interesting) {
2711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTable->addrRegs[i] = regPtr;
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regPtr += regTable->insnRegCountPlus;
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("Tracking registers for %d, total %d of %d(%d) (%d%%)\n",
2717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    TRACK_REGS_FOR, interestingCount, insnCount, insnsSize,
2718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    (interestingCount*100) / insnCount);
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(regPtr - regTable->regAlloc ==
2721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        regTable->insnRegCountPlus * interestingCount);
2722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(regTable->addrRegs[0] != NULL);
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that the arguments in a filled-new-array instruction are valid.
2729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "resClass" is the class refered to by pDecInsn->vB.
2731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void verifyFilledNewArrayRegs(const Method* meth,
2733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const RegType* insnRegs, const int insnRegCount,
2734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
2735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool* pOkay)
2736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 argCount = pDecInsn->vA;
2738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType expectedType;
2739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    PrimitiveType elemType;
2740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int ui;
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsArrayClass(resClass));
2743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    elemType = resClass->elementClass->primitiveType;
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (elemType == PRIM_NOT) {
2745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expectedType = regTypeFromClass(resClass->elementClass);
2746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        expectedType = primitiveTypeToRegType(elemType);
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("filled-new-array: %s -> %d\n", resClass->descriptor, expectedType);
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Verify each register.  If "argCount" is bad, verifyRegisterType()
2753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will run off the end of the list and fail.  It's legal, if silly,
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for argCount to be zero.
2755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ui = 0; ui < argCount; ui++) {
2757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 getReg;
2758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (isRange)
2760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getReg = pDecInsn->vC + ui;
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getReg = pDecInsn->arg[ui];
2763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType, pOkay);
2765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!*pOkay) {
2766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
2767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
2768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Entry point and driver loop
2776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
2777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entry point for the detailed code-flow analysis.
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmVerifyCodeFlow(const Method* meth, InsnFlags* insnFlags,
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap)
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnsSize = dvmGetMethodInsnsSize(meth);
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns = meth->insns;
2788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const bool generateRegisterMap = gDvm.generateRegisterMaps;
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, offset;
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isConditional;
2791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable regTable;
2792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&regTable, 0, sizeof(regTable));
2794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    checkMergeTab();     // only need to do this if table gets updated
2797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We rely on these for verification of const-class, const-string,
2801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and throw instructions.  Make sure we have them.
2802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangClass == NULL)
2804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangClass =
2805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClassNoInit("Ljava/lang/Class;");
2806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangString == NULL)
2807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangString =
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClassNoInit("Ljava/lang/String;");
2809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangThrowable == NULL)
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangThrowable =
2811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
2812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangObject == NULL)
2813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangObject =
2814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClassNoInit("Ljava/lang/Object;");
2815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (meth->registersSize * insnsSize > 2*1024*1024) {
2817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* should probably base this on actual memory requirements */
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY_METH(meth,
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "VFY: arbitrarily rejecting large method (regs=%d count=%d)\n",
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->registersSize, insnsSize);
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create register lists, and initialize them to "Unknown".  If we're
2826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * also going to create the register map, we need to retain the
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * register lists for a larger set of addresses.
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!initRegisterTable(meth, insnFlags, &regTable,
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches))
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Initialize the types of the registers that correspond to the
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method arguments.  We can determine this from the method signature.
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!setTypesFromSignature(meth, regTable.addrRegs[0], uninitMap))
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run the verifier.
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!doCodeVerification(meth, insnFlags, &regTable, uninitMap))
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Generate a register map.
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (generateRegisterMap) {
2850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterMap* pMap;
2851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        VerifierData vd;
2852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vd.method = meth;
2854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vd.insnsSize = insnsSize;
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vd.insnRegCount = meth->registersSize;
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vd.insnFlags = insnFlags;
2857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vd.addrRegs = regTable.addrRegs;
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pMap = dvmGenerateRegisterMapV(&vd);
2860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pMap != NULL) {
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Tuck it into the Method struct.  It will either get used
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * directly or, if we're in dexopt, will be packed up and
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * appended to the DEX file.
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmSetRegisterMap((Method*)meth, pMap);
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Success.
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(regTable.addrRegs);
2877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(regTable.regAlloc);
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Grind through the instructions.
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit
2885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the first instruction, process it (setting additional "changed" bits),
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and repeat until there are no more.
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * v3 4.11.1.1
2889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - (N/A) operand stack is always the same size
2890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - operand stack [registers] contain the correct types of values
2891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - local variables [registers] contain the correct types of values
2892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - methods are invoked with the appropriate arguments
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - fields are assigned using values of appropriate types
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - opcodes have the correct type values in operand registers
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - there is never an uninitialized class instance in a local variable in
2896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   code protected by an exception handler (operand stack is okay, because
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   the operand stack is discarded when an exception is thrown) [can't
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   know what's a local var w/o the debug info -- should fall out of
2899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   register typing]
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * v3 4.11.1.2
2902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - execution cannot fall off the end of the code
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (We also do many of the items described in the "static checks" sections,
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because it's easier to do them here.)
2906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need an array of RegType values, one per register, for every
2908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instruction.  In theory this could become quite large -- up to several
2909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * megabytes for a monster function.  For self-preservation we reject
2910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything that requires more than a certain amount of memory.  (Typical
2911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "large" should be on the order of 4K code units * 8 registers.)  This
2912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will likely have to be adjusted.
2913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The spec forbids backward branches when there's an uninitialized reference
2916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a register.  The idea is to prevent something like this:
2917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   loop:
2918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     move r1, r0
2919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     new-instance r0, MyClass
2920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     ...
2921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     if-eq rN, loop  // once
2922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   initialize r0
2923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This leaves us with two different instances, both allocated by the
2925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * same instruction, but only one is initialized.  The scheme outlined in
2926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing
2927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * backward branches.  We achieve identical results without restricting
2928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code reordering by specifying that you can't execute the new-instance
2929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instruction if a register contains an uninitialized instance created
2930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by that same instrutcion.
2931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, UninitInstanceMap* uninitMap)
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnsSize = dvmGetMethodInsnsSize(meth);
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns = meth->insns;
2937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType workRegs[meth->registersSize + kExtraRegs];
2938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool debugVerbose = false;
2940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int insnIdx, startGuess, prevAddr;
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Begin by marking the first instruction as "changed".
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInsnSetChanged(insnFlags, 0, true);
2946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (doVerboseLogging(meth)) {
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        IF_LOGI() {
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)\n",
2951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->clazz->descriptor, meth->name, desc,
2952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->insSize, meth->registersSize);
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI(" ------ [0    4    8    12   16   20   24   28   32   36\n");
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
2955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        debugVerbose = true;
2957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDebugVerbose = true;
2958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDebugVerbose = false;
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startGuess = 0;
2963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Continue until no instructions are marked "changed".
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
2968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Find the first marked one.  Use "startGuess" as a way to find
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * one quickly.
2971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmInsnIsChanged(insnFlags, insnIdx))
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (insnIdx == insnsSize) {
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (startGuess != 0) {
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* try again, starting from the top */
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startGuess = 0;
2981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* all flags are clear */
2984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We carry the working set of registers from instruction to
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * instruction.  If this address can be the target of a branch
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (or throw) instruction, or if we're skipping around chasing
2992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "changed" flags, we need to load the set of registers from
2993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the table.
2994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Because we always prefer to continue on to the next instruction,
2996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we should never have a situation where we have a stray
2997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "changed" flag set on an instruction that isn't a branch target.
2998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
3000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(insnRegs != NULL);
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            copyRegisters(workRegs, insnRegs, meth->registersSize + kExtraRegs);
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (debugVerbose) {
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    SHOW_REG_DETAILS);
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (debugVerbose) {
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    SHOW_REG_DETAILS);
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Sanity check: retrieve the stored register line (assuming
3018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * a full table) and make sure it actually matches.
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (insnRegs != NULL &&
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                compareRegisters(workRegs, insnRegs,
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->registersSize + kExtraRegs) != 0)
3024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("HUH? workRegs diverged in %s.%s %s\n",
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->clazz->descriptor, meth->name, desc);
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(desc);
3029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dumpRegTypes(meth, insnFlags, workRegs, 0, "work",
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dumpRegTypes(meth, insnFlags, insnRegs, 0, "insn",
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("process %s.%s %s %d\n",
3038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx);
3039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!verifyInstruction(meth, insnFlags, regTable, workRegs, insnIdx,
3040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                uninitMap, &startGuess))
3041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("+++ %s bailing at %d\n", meth->name, insnIdx);
3043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
3047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            static const int gcMask = kInstrCanBranch | kInstrCanSwitch |
3049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                      kInstrCanThrow | kInstrCanReturn;
3050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            OpCode opCode = *(meth->insns + insnIdx) & 0xff;
3051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int flags = dexGetInstrFlags(gDvm.instrFlags, opCode);
3052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* 8, 16, 32, or 32*n -bit regs */
3054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regWidth = (meth->registersSize + 7) / 8;
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regWidth == 3)
3056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regWidth = 4;
3057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regWidth > 4) {
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regWidth = ((regWidth + 3) / 4) * 4;
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (false) {
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("WOW: %d regs -> %d  %s.%s\n",
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->registersSize, regWidth,
3062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->clazz->descriptor, meth->name);
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //x = true;
3064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((flags & gcMask) != 0) {
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* this is a potential GC point */
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gDvm__gcInstr++;
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (insnsSize < 256)
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    gDvm__gcData += 1;
3073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                else
3074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    gDvm__gcData += 2;
3075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gDvm__gcData += regWidth;
3076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm__gcSimpleData += regWidth;
3078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm__totalInstr++;
3080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Clear "changed" and mark as visited.
3085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInsnSetVisited(insnFlags, insnIdx, true);
3087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInsnSetChanged(insnFlags, insnIdx, false);
3088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (DEAD_CODE_SCAN) {
3091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Scan for dead code.  There's nothing "evil" about dead code, but it
3093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * indicates a flaw somewhere down the line, possibly in the verifier.
3094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int deadStart = -1;
3096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (insnIdx = 0; insnIdx < insnsSize;
3097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnIdx += dvmInsnGetWidth(insnFlags, insnIdx))
3098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Switch-statement data doesn't get "visited" by scanner.  It
3101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * may or may not be preceded by a padding NOP.
3102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int instr = meth->insns[insnIdx];
3104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (instr == kPackedSwitchSignature ||
3105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                instr == kSparseSwitchSignature ||
3106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                instr == kArrayDataSignature ||
3107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (instr == OP_NOP &&
3108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 (meth->insns[insnIdx+1] == kPackedSwitchSignature ||
3109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                  meth->insns[insnIdx+1] == kSparseSwitchSignature ||
3110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                  meth->insns[insnIdx+1] == kArrayDataSignature)))
3111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmInsnSetVisited(insnFlags, insnIdx, true);
3113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmInsnIsVisited(insnFlags, insnIdx)) {
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (deadStart < 0)
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    deadStart = insnIdx;
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (deadStart >= 0) {
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                IF_LOGD() {
3120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    char* desc =
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dexProtoCopyMethodDescriptor(&meth->prototype);
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        deadStart, insnIdx-1,
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->clazz->descriptor, meth->name, desc);
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(desc);
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                deadStart = -1;
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (deadStart >= 0) {
3132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            IF_LOGD() {
3133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    deadStart, insnIdx-1,
3136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->clazz->descriptor, meth->name, desc);
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(desc);
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
3146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Perform verification for a single instruction.
3151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This requires fully decoding the instruction to determine the effect
3153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it has on registers.
3154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finds zero or more following instructions and sets the "changed" flag
3156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if execution at that point needs to be (re-)evaluated.  Register changes
3157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are merged into "regTypes" at the target addresses.  Does not set or
3158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * clear any other flags in "insnFlags".
3159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,
3161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegisterTable* regTable, RegType* workRegs, int insnIdx,
3162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UninitInstanceMap* uninitMap, int* pStartGuess)
3163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnsSize = dvmGetMethodInsnsSize(meth);
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns = meth->insns + insnIdx;
3166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
3167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Once we finish decoding the instruction, we need to figure out where
3170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we can go from here.  There are three possible ways to transfer
3171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * control to another statement:
3172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (1) Continue to the next instruction.  Applies to all but
3174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     unconditional branches, method returns, and exception throws.
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (2) Branch to one or more possible locations.  Applies to branches
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     and switch statements.
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (3) Exception handlers.  Applies to any instruction that can
3178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     throw an exception that is handled by an encompassing "try"
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     block.  (We simplify this to be any instruction that can
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     throw any exception.)
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can also return, in which case there is no successor instruction
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * from this point.
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The behavior can be determined from the InstrFlags.
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType entryRegs[meth->registersSize + kExtraRegs];
3190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* resClass;
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* className;
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int branchTarget = 0;
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int insnRegCount = meth->registersSize;
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RegType tmpType;
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DecodedInstruction decInsn;
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool justSetResult = false;
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool okay = true;
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&decInsn, 0x81, sizeof(decInsn));
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make a copy of the previous register state.  If the instruction
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * throws an exception, we merge *this* into the destination rather
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * than workRegs, because we don't want the result from the "successful"
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * code path (e.g. a check-cast that "improves" a type) to be visible
3211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to the exception handler.
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
3215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyRegisters(entryRegs, workRegs, meth->registersSize + kExtraRegs);
3216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memset(entryRegs, 0xdd,
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (meth->registersSize + kExtraRegs) * sizeof(RegType));
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (decInsn.opCode) {
3224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NOP:
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * A "pure" NOP has no effect on anything.  Data tables start with
3227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a signature that looks like a NOP; if we see one of these in
3228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the course of executing code then we have a problem.
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (decInsn.vA != 0) {
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: encountered data table in instruction stream\n");
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE:
3237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_FROM16:
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_16:
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kTypeCategory1nr, &okay);
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_WIDE:
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_WIDE_FROM16:
3244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_WIDE_16:
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &okay);
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_OBJECT:
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_OBJECT_FROM16:
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_OBJECT_16:
3250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kTypeCategoryRef, &okay);
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The move-result instructions copy data out of a "pseudo-register"
3256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with the results from the last method invocation.  In practice we
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might want to hold the result in an actual CPU register, so the
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Dalvik spec requires that these only appear immediately after an
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * invoke or filled-new-array.
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * These calls invalidate the "result" register.  (This is now
3262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * redundant with the reset done below, but it can make the debug info
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * easier to read in some cases.)
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_RESULT:
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kTypeCategory1nr, &okay);
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_RESULT_WIDE:
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &okay);
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_RESULT_OBJECT:
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kTypeCategoryRef, &okay);
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MOVE_EXCEPTION:
3278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * This statement can only appear as the first instruction in an
3280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception handler (though not all exception handlers need to
3281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have one of these).  We verify that as part of extracting the
3282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception type from the catch block list.
3283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "resClass" will hold the closest common superclass of all
3285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exceptions that can be handled here.
3286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = getCaughtExceptionType(meth, insnIdx);
3288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(resClass), &okay);
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RETURN_VOID:
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay && getMethodReturnType(meth) != kRegTypeUnknown) {
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: return-void not expected\n");
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RETURN:
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the method signature */
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType = getMethodReturnType(meth);
3308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
3309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: return-32 not expected\n");
3311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the register contents */
3313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                &okay);
3315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
3316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
3318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RETURN_WIDE:
3321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
3322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
3323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType, returnTypeHi;
3324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the method signature */
3326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getMethodReturnType(meth);
3327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(returnType, kTypeCategory2, &okay);
3328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: return-wide not expected\n");
3330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the register contents */
3332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                &okay);
3334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnTypeHi = getRegisterType(workRegs, insnRegCount,
3335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vA +1, &okay);
3336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (okay) {
3337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                checkTypeCategory(returnType, kTypeCategory2, &okay);
3338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                checkWidePair(returnType, returnTypeHi, &okay);
3339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay) {
3341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
3342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    decInsn.vA);
3343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RETURN_OBJECT:
3347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
3348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
3349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType = getMethodReturnType(meth);
3350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(returnType, kTypeCategoryRef, &okay);
3351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay) {
3352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: return-object not expected\n");
3353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* returnType is the *expected* return type, not register value */
3357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(returnType != kRegTypeZero);
3358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(!regTypeIsUninitReference(returnType));
3359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Verify that the reference in vAA is an instance of the type
3362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in "returnType".  The Zero type is allowed here.  If the
3363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method is declared to return an interface, then any
3364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * initialized reference is acceptable.
3365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Note getClassFromRegister fails if the register holds an
3367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * uninitialized reference, so we do not allow them to be
3368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * returned.
3369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* declClass;
3371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            declClass = regTypeInitializedReferenceToClass(returnType);
3373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vA, &okay);
3375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass != NULL) {
3378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsInterfaceClass(declClass) &&
3379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !dvmInstanceof(resClass, declClass))
3380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
3381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: returning %s, declared %s\n",
3382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            resClass->descriptor, declClass->descriptor);
3383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_4:
3391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_16:
3392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST:
3393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* could be boolean, int, float, or a null reference */
3394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA,
3395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDetermineCat1Const((s4)decInsn.vB), &okay);
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_HIGH16:
3398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* could be boolean, int, float, or a null reference */
3399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA,
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDetermineCat1Const((s4) decInsn.vB << 16), &okay);
3401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_WIDE_16:
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_WIDE_32:
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_WIDE:
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_WIDE_HIGH16:
3406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* could be long or double; default to long and allow conversion */
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA,
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, &okay);
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_STRING:
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_STRING_JUMBO:
3412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(gDvm.classJavaLangString != NULL);
3413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA,
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regTypeFromClass(gDvm.classJavaLangString), &okay);
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CONST_CLASS:
3417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(gDvm.classJavaLangClass != NULL);
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure we can resolve the class; access check is important */
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vB, badClassDesc, meth->clazz->descriptor);
3425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(gDvm.classJavaLangClass), &okay);
3429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MONITOR_ENTER:
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MONITOR_EXIT:
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
3435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay && !regTypeIsReference(tmpType)) {
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: monitor op on non-object\n");
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CHECK_CAST:
3442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If this instruction succeeds, we will promote register vA to
3444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the type in vB.  (This could be a demotion -- not expected, so
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we don't try to address it.)
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If it fails, an exception is thrown, which we deal with later
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * by ignoring the update to decInsn.vA when branching to a handler.
3449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vB, badClassDesc, meth->clazz->descriptor);
3456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType origType;
3459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!regTypeIsReference(origType)) {
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(resClass), &okay);
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INSTANCE_OF:
3474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure we're checking a reference type */
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
3476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!regTypeIsReference(tmpType)) {
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
3480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure we can resolve the class; access check is important */
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
3486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
3490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vC, badClassDesc, meth->clazz->descriptor);
3491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* result is boolean */
3494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeBoolean, &okay);
3496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ARRAY_LENGTH:
3500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = getClassFromRegister(workRegs, insnRegCount,
3501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vB, &okay);
3502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass != NULL && !dvmIsArrayClass(resClass)) {
3505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: array-length on non-array\n");
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEW_INSTANCE:
3514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We can check for interface and abstract classes here, but we
3516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * can't reject them.  We can ask the optimizer to replace the
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * instructions with a magic "always throw InstantiationError"
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * instruction.  (Not enough bytes to sub in a method call.)
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
3521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vB, badClassDesc, meth->clazz->descriptor);
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType uninitType;
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* add resolved class to uninit map if not already there */
3531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int uidx = dvmSetUninitInstance(uninitMap, insnIdx, resClass);
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(uidx >= 0);
3533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            uninitType = regTypeFromUninitIndex(uidx);
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Any registers holding previous allocations from this address
3537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that have not yet been initialized must be marked invalid.
3538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            markUninitRefsAsInvalid(workRegs, insnRegCount, uninitMap,
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                uninitType);
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* add the new uninitialized reference to the register ste */
3543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                uninitType, &okay);
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEW_ARRAY:
3548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
3549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
3553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vC, badClassDesc, meth->clazz->descriptor);
3554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!dvmIsArrayClass(resClass)) {
3556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: new-array on non-array class\n");
3557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* make sure "size" register is valid type */
3560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
3561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                kRegTypeInteger, &okay);
3562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* set register type to array class */
3563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(resClass), &okay);
3565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FILLED_NEW_ARRAY:
3568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FILLED_NEW_ARRAY_RANGE:
3569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
3570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass == NULL) {
3571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLogUnableToResolveClass(badClassDesc, meth);
3573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
3574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                decInsn.vB, badClassDesc, meth->clazz->descriptor);
3575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!dvmIsArrayClass(resClass)) {
3577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: filled-new-array on non-array class\n");
3578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            okay = false;
3579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
3581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the arguments to the instruction */
3583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
3584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resClass, isRange, &okay);
3585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* filled-array result goes into "result" register */
3586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setResultRegisterType(workRegs, insnRegCount,
3587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(resClass), &okay);
3588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justSetResult = true;
3589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CMPL_FLOAT:
3593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CMPG_FLOAT:
3594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
3595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
3597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CMPL_DOUBLE:
3602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CMPG_DOUBLE:
3603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
3604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
3606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_CMP_LONG:
3611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
3612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
3614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            &okay);
3617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_THROW:
3620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = getClassFromRegister(workRegs, insnRegCount,
3621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA, &okay);
3622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay && resClass != NULL) {
3623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
3624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
3625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_GOTO:
3632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_GOTO_16:
3633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_GOTO_32:
3634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no effect on or use of registers */
3635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_PACKED_SWITCH:
3638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPARSE_SWITCH:
3639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify that vAA is an integer, or can be converted to one */
3640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
3641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, &okay);
3642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FILL_ARRAY_DATA:
3645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType valueType;
3647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const u2 *arrayData;
3648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u2 elemWidth;
3649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Similar to the verification done for APUT */
3651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vA, &okay);
3653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* resClass can be null if the reg type is Zero */
3657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass == NULL)
3658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
3661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resClass->elementClass->primitiveType == PRIM_NOT ||
3662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resClass->elementClass->primitiveType == PRIM_VOID)
3663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
3664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid fill-array-data on %s\n",
3665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueType = primitiveTypeToRegType(
3671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    resClass->elementClass->primitiveType);
3672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(valueType != kRegTypeUnknown);
3673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Now verify if the element width in the table matches the element
3676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * width declared in the array
3677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
3679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arrayData[0] != kArrayDataSignature) {
3680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid magic for array-data\n");
3681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (resClass->elementClass->primitiveType) {
3686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_BOOLEAN:
3687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_BYTE:
3688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     elemWidth = 1;
3689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     break;
3690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_CHAR:
3691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_SHORT:
3692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     elemWidth = 2;
3693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     break;
3694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_FLOAT:
3695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_INT:
3696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     elemWidth = 4;
3697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     break;
3698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_DOUBLE:
3699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_LONG:
3700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     elemWidth = 8;
3701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     break;
3702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default:
3703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     elemWidth = 0;
3704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     break;
3705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Since we don't compress the data in Dex, expect to see equal
3709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * width of data stored in the table and expected from the array
3710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class.
3711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arrayData[1] != elemWidth) {
3713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
3714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        arrayData[1], elemWidth);
3715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_EQ:
3721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_NE:
3722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType type1, type2;
3724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool tmpResult;
3725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
3727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
3728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* both references? */
3732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regTypeIsReference(type1) && regTypeIsReference(type2))
3733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* both category-1nr? */
3736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(type1, kTypeCategory1nr, &okay);
3737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(type2, kTypeCategory1nr, &okay);
3738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay) {
3739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
3740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_LT:
3745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_GE:
3746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_GT:
3747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_LE:
3748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
3749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
3752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay) {
3753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
3754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB,&okay);
3757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
3760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay) {
3761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
3762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_EQZ:
3766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_NEZ:
3767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
3768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (regTypeIsReference(tmpType))
3771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
3773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: expected cat-1 arg to if\n");
3775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_LTZ:
3777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_GEZ:
3778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_GTZ:
3779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IF_LEZ:
3780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
3781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
3784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
3785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY("VFY: expected cat-1 arg to if\n");
3786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET:
3789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
3790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aget_1nr_common;
3791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_BOOLEAN:
3792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
3793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aget_1nr_common;
3794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_BYTE:
3795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
3796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aget_1nr_common;
3797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_CHAR:
3798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
3799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aget_1nr_common;
3800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_SHORT:
3801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
3802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aget_1nr_common;
3803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectaget_1nr_common:
3804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType srcType, indexType;
3806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
3808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
3809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkArrayIndexType(meth, indexType, &okay);
3810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vB, &okay);
3815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass != NULL) {
3818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* verify the class */
3819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
3820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    resClass->elementClass->primitiveType == PRIM_NOT)
3821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
3822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aget-1nr target %s\n",
3823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* make sure array type matches instruction */
3829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                srcType = primitiveTypeToRegType(
3830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        resClass->elementClass->primitiveType);
3831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!checkFieldArrayStore1nr(tmpType, srcType)) {
3833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
3834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            " inst type=%d (on %s)\n",
3835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        srcType, tmpType, resClass->descriptor);
3836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpType, &okay);
3843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_WIDE:
3847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType dstType, indexType;
3849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
3851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
3852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkArrayIndexType(meth, indexType, &okay);
3853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vB, &okay);
3858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass != NULL) {
3861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* verify the class */
3862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
3863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    resClass->elementClass->primitiveType == PRIM_NOT)
3864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
3865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aget-wide target %s\n",
3866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* try to refine "dstType" */
3872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                switch (resClass->elementClass->primitiveType) {
3873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_LONG:
3874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dstType = kRegTypeLongLo;
3875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case PRIM_DOUBLE:
3877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dstType = kRegTypeDoubleLo;
3878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default:
3880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aget-wide on %s\n",
3881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dstType = kRegTypeUnknown;
3883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
3887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Null array ref; this code path will fail at runtime.  We
3889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * know this is either long or double, and we don't really
3890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * discriminate between those during verification, so we
3891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * call it a long.
3892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeLongLo;
3894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType, &okay);
3897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AGET_OBJECT:
3901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType dstType, indexType;
3903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
3905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
3906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkArrayIndexType(meth, indexType, &okay);
3907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* get the class of the array we're pulling an object from */
3911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vB, &okay);
3913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass != NULL) {
3916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* elementClass;
3917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(resClass != NULL);
3919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsArrayClass(resClass)) {
3920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: aget-object on non-array class\n");
3921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(resClass->elementClass != NULL);
3925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Find the element class.  resClass->elementClass indicates
3928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the basic type, which won't be what we want for a
3929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * multi-dimensional array.
3930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (resClass->descriptor[1] == '[') {
3932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(resClass->arrayDim > 1);
3933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    elementClass = dvmFindArrayClass(&resClass->descriptor[1],
3934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        resClass->classLoader);
3935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (resClass->descriptor[1] == 'L') {
3936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(resClass->arrayDim == 1);
3937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    elementClass = resClass->elementClass;
3938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
3939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
3940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
3941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
3942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = regTypeFromClass(elementClass);
3946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
3947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The array reference is NULL, so the current code path will
3949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * throw an exception.  For proper merging with later code
3950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * paths, and correct handling of "if-eqz" tests on the
3951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * result of the array get, we want to treat this as a null
3952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * reference.
3953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeZero;
3955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
3957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType, &okay);
3958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
3960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT:
3961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
3962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aput_1nr_common;
3963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_BOOLEAN:
3964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
3965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aput_1nr_common;
3966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_BYTE:
3967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
3968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aput_1nr_common;
3969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_CHAR:
3970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
3971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aput_1nr_common;
3972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_SHORT:
3973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
3974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto aput_1nr_common;
3975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectaput_1nr_common:
3976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
3977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType srcType, dstType, indexType;
3978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
3980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
3981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkArrayIndexType(meth, indexType, &okay);
3982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* make sure the source register has the correct type */
3986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
3988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!canConvertTo1nr(srcType, tmpType)) {
3989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
3990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    srcType, tmpType);
3991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
3992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resClass = getClassFromRegister(workRegs, insnRegCount,
3996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vB, &okay);
3997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
3998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* resClass can be null if the reg type is Zero */
4001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resClass == NULL)
4002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resClass->elementClass->primitiveType == PRIM_NOT)
4006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
4007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
4008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* verify that instruction matches array */
4013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dstType = primitiveTypeToRegType(
4014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    resClass->elementClass->primitiveType);
4015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dstType != kRegTypeUnknown);
4016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!checkFieldArrayStore1nr(tmpType, dstType)) {
4018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
4019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor, tmpType, dstType);
4020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_WIDE:
4026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkArrayIndexType(meth, tmpType, &okay);
4029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
4030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
4033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
4034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType typeHi =
4035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
4036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(tmpType, kTypeCategory2, &okay);
4037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkWidePair(tmpType, typeHi, &okay);
4038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
4040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = getClassFromRegister(workRegs, insnRegCount,
4043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vB, &okay);
4044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
4045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass != NULL) {
4047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* verify the class and try to refine "dstType" */
4048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resClass->elementClass->primitiveType == PRIM_NOT)
4050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
4051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid aput-wide on %s\n",
4052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
4053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (resClass->elementClass->primitiveType) {
4058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case PRIM_LONG:
4059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case PRIM_DOUBLE:
4060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* these are okay */
4061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
4063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid aput-wide on %s\n",
4064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resClass->descriptor);
4065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_APUT_OBJECT:
4071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkArrayIndexType(meth, tmpType, &okay);
4074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
4075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* get the ref we're storing; Zero is okay, Uninit is not */
4078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resClass = getClassFromRegister(workRegs, insnRegCount,
4079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA, &okay);
4080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!okay)
4081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resClass != NULL) {
4083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* arrayClass;
4084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* elementClass;
4085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Get the array class.  If the array ref is null, we won't
4088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * have type information (and we'll crash at runtime with a
4089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * null pointer exception).
4090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            arrayClass = getClassFromRegister(workRegs, insnRegCount,
4092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            decInsn.vB, &okay);
4093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (arrayClass != NULL) {
4095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* see if the array holds a compatible type */
4096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsArrayClass(arrayClass)) {
4097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aput-object on %s\n",
4098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            arrayClass->descriptor);
4099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
4104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Find the element class.  resClass->elementClass indicates
4105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the basic type, which won't be what we want for a
4106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * multi-dimensional array.
4107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
4108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * All we want to check here is that the element type is a
4109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * reference class.  We *don't* check instanceof here, because
4110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * you can still put a String into a String[] after the latter
4111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * has been cast to an Object[].
4112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
4113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (arrayClass->descriptor[1] == '[') {
4114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(arrayClass->arrayDim > 1);
4115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    elementClass = dvmFindArrayClass(&arrayClass->descriptor[1],
4116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        arrayClass->classLoader);
4117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
4118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(arrayClass->arrayDim == 1);
4119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    elementClass = arrayClass->elementClass;
4120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (elementClass->primitiveType != PRIM_NOT) {
4122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invalid aput-object of %s into %s\n",
4123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            resClass->descriptor, arrayClass->descriptor);
4124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET:
4132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
4133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iget_1nr_common;
4134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_BOOLEAN:
4135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
4136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iget_1nr_common;
4137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_BYTE:
4138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
4139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iget_1nr_common;
4140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_CHAR:
4141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
4142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iget_1nr_common;
4143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_SHORT:
4144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
4145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iget_1nr_common;
4146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectiget_1nr_common:
4147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType objType, fieldType;
4151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* make sure the field's type is compatible with expectation */
4162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldType = primSigCharToRegType(instField->field.signature[0]);
4163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldType == kRegTypeUnknown ||
4164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                !checkFieldArrayStore1nr(tmpType, fieldType))
4165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
4166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
4167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.clazz->descriptor,
4168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.name, tmpType, fieldType);
4169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
4174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_WIDE:
4177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType dstType;
4179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType objType;
4182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the type, which should be prim */
4192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (instField->field.signature[0]) {
4193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D':
4194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeDoubleLo;
4195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J':
4197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeLongLo;
4198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
4200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid iget-wide of %s.%s\n",
4201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.clazz->descriptor,
4202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.name);
4203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeUnknown;
4204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (okay) {
4208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                setRegisterType(workRegs, insnRegCount, decInsn.vA,
4209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dstType, &okay);
4210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_OBJECT:
4214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType objType;
4218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldClass = getFieldClass(meth, &instField->field);
4228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldClass == NULL) {
4229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* class not found or primitive type */
4230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: unable to recover field class from '%s'\n",
4231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    instField->field.signature);
4232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (okay) {
4236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(!dvmIsPrimitiveClass(fieldClass));
4237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                setRegisterType(workRegs, insnRegCount, decInsn.vA,
4238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    regTypeFromClass(fieldClass), &okay);
4239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT:
4243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
4244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iput_1nr_common;
4245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_BOOLEAN:
4246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
4247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iput_1nr_common;
4248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_BYTE:
4249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
4250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iput_1nr_common;
4251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_CHAR:
4252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
4253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iput_1nr_common;
4254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_SHORT:
4255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
4256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto iput_1nr_common;
4257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectiput_1nr_common:
4258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType srcType, fieldType, objType;
4260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* make sure the source register has the correct type */
4264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!canConvertTo1nr(srcType, tmpType)) {
4267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
4268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    srcType, tmpType);
4269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &instField->field, &okay);
4282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* get type of field we're storing into */
4286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldType = primSigCharToRegType(instField->field.signature[0]);
4287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldType == kRegTypeUnknown ||
4288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                !checkFieldArrayStore1nr(tmpType, fieldType))
4289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
4290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
4291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.clazz->descriptor,
4292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.name, tmpType, fieldType);
4293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_WIDE:
4299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
4300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
4301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType typeHi =
4302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
4303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(tmpType, kTypeCategory2, &okay);
4304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkWidePair(tmpType, typeHi, &okay);
4305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
4307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType objType;
4310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &instField->field, &okay);
4320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the type, which should be prim */
4324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (instField->field.signature[0]) {
4325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D':
4326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J':
4327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* these are okay (and interchangeable) */
4328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
4330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
4331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.clazz->descriptor,
4332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instField->field.name);
4333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_OBJECT:
4339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* valueClass;
4342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InstField* instField;
4343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType objType, valueType;
4344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &okay);
4351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &instField->field, &okay);
4354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldClass = getFieldClass(meth, &instField->field);
4358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldClass == NULL) {
4359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: unable to recover field class from '%s'\n",
4360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    instField->field.signature);
4361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!regTypeIsReference(valueType)) {
4370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA, instField->field.name,
4372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fieldClass->descriptor);
4373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (valueType != kRegTypeZero) {
4377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                valueClass = regTypeInitializedReferenceToClass(valueType);
4378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (valueClass == NULL) {
4379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA);
4381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* allow if field is any interface or field is base class */
4385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsInterfaceClass(fieldClass) &&
4386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !dvmInstanceof(valueClass, fieldClass))
4387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
4388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            valueClass->descriptor, fieldClass->descriptor,
4390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            instField->field.clazz->descriptor,
4391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            instField->field.name);
4392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET:
4400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
4401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sget_1nr_common;
4402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_BOOLEAN:
4403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
4404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sget_1nr_common;
4405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_BYTE:
4406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
4407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sget_1nr_common;
4408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_CHAR:
4409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
4410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sget_1nr_common;
4411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_SHORT:
4412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
4413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sget_1nr_common;
4414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsget_1nr_common:
4415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType fieldType;
4418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Make sure the field's type is compatible with expectation.
4425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can get ourselves into trouble if we mix & match loads
4426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * and stores with different widths, so rather than just checking
4427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "canConvertTo1nr" we require that the field types have equal
4428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * widths.  (We can't generally require an exact type match,
4429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * because e.g. "int" and "float" are interchangeable.)
4430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldType = primSigCharToRegType(staticField->field.signature[0]);
4432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
4434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.clazz->descriptor,
4435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.name, tmpType, fieldType);
4436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
4441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_WIDE:
4444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType dstType;
4447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the type, which should be prim */
4452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (staticField->field.signature[0]) {
4453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D':
4454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeDoubleLo;
4455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J':
4457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeLongLo;
4458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
4460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid sget-wide of %s.%s\n",
4461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        staticField->field.clazz->descriptor,
4462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        staticField->field.name);
4463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dstType = kRegTypeUnknown;
4464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (okay) {
4468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                setRegisterType(workRegs, insnRegCount, decInsn.vA,
4469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dstType, &okay);
4470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SGET_OBJECT:
4474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldClass = getFieldClass(meth, &staticField->field);
4482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldClass == NULL) {
4483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: unable to recover field class from '%s'\n",
4484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.signature);
4485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsPrimitiveClass(fieldClass)) {
4489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: attempt to get prim field with sget-object\n");
4490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setRegisterType(workRegs, insnRegCount, decInsn.vA,
4494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regTypeFromClass(fieldClass), &okay);
4495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT:
4498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeInteger;
4499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sput_1nr_common;
4500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_BOOLEAN:
4501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeBoolean;
4502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sput_1nr_common;
4503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_BYTE:
4504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeByte;
4505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sput_1nr_common;
4506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_CHAR:
4507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeChar;
4508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sput_1nr_common;
4509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_SHORT:
4510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = kRegTypeShort;
4511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto sput_1nr_common;
4512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsput_1nr_common:
4513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType srcType, fieldType;
4515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* make sure the source register has the correct type */
4518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!canConvertTo1nr(srcType, tmpType)) {
4521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
4522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    srcType, tmpType);
4523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &staticField->field, &okay);
4531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Get type of field we're storing into.  We know that the
4536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * contents of the register match the instruction, but we also
4537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * need to ensure that the instruction matches the field type.
4538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Using e.g. sput-short to write into a 32-bit integer field
4539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * can lead to trouble if we do 16-bit writes.
4540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldType = primSigCharToRegType(staticField->field.signature[0]);
4542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
4544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.clazz->descriptor,
4545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.name, tmpType, fieldType);
4546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_WIDE:
4552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
4553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
4554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType typeHi =
4555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
4556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkTypeCategory(tmpType, kTypeCategory2, &okay);
4557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkWidePair(tmpType, typeHi, &okay);
4558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (okay) {
4560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &staticField->field, &okay);
4566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* check the type, which should be prim */
4570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (staticField->field.signature[0]) {
4571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D':
4572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J':
4573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* these are okay */
4574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
4576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
4577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        staticField->field.clazz->descriptor,
4578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        staticField->field.name);
4579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SPUT_OBJECT:
4585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* fieldClass;
4587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* valueClass;
4588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            StaticField* staticField;
4589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType valueType;
4590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            staticField = getStaticField(meth, decInsn.vB, &okay);
4592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            checkFinalFieldAccess(meth, &staticField->field, &okay);
4595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldClass = getFieldClass(meth, &staticField->field);
4599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fieldClass == NULL) {
4600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: unable to recover field class from '%s'\n",
4601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    staticField->field.signature);
4602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &okay);
4608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!regTypeIsReference(valueType)) {
4611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA, staticField->field.name,
4613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        fieldClass->descriptor);
4614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                okay = false;
4615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (valueType != kRegTypeZero) {
4618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                valueClass = regTypeInitializedReferenceToClass(valueType);
4619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (valueClass == NULL) {
4620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.vA);
4622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* allow if field is any interface or field is base class */
4626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmIsInterfaceClass(fieldClass) &&
4627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !dvmInstanceof(valueClass, fieldClass))
4628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
4629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            valueClass->descriptor, fieldClass->descriptor,
4631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            staticField->field.clazz->descriptor,
4632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            staticField->field.name);
4633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_VIRTUAL:
4641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_VIRTUAL_RANGE:
4642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_SUPER:
4643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_SUPER_RANGE:
4644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* calledMethod;
4646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType;
4647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isRange;
4648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isSuper;
4649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isRange =  (decInsn.opCode == OP_INVOKE_VIRTUAL_RANGE ||
4651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isSuper =  (decInsn.opCode == OP_INVOKE_SUPER ||
4653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
4657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            isSuper, &okay);
4658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getMethodReturnType(calledMethod);
4661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
4662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justSetResult = true;
4663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_DIRECT:
4666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_DIRECT_RANGE:
4667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType;
4669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* calledMethod;
4670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isRange;
4671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isRange =  (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
4673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &decInsn, uninitMap, METHOD_DIRECT, isRange,
4675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            false, &okay);
4676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Some additional checks when calling <init>.  We know from
4681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the invocation arg check that the "this" argument is an
4682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * instance of calledMethod->clazz.  Now we further restrict
4683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that to require that calledMethod->clazz is the same as
4684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * this->clazz or this->super, allowing the latter only if
4685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the "this" argument is the same as the "this" argument to
4686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * this method (which implies that we're in <init> ourselves).
4687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (isInitMethod(calledMethod)) {
4689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegType thisType;
4690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                thisType = getInvocationThis(workRegs, insnRegCount,
4691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &decInsn, &okay);
4692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!okay)
4693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* no null refs allowed (?) */
4696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (thisType == kRegTypeZero) {
4697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: unable to initialize null ref\n");
4698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* thisClass;
4703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                thisClass = regTypeReferenceToClass(thisType, uninitMap);
4705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(thisClass != NULL);
4706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* must be in same class or in superclass */
4708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (calledMethod->clazz == thisClass->super) {
4709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (thisClass != meth->clazz) {
4710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        LOG_VFY("VFY: invoke-direct <init> on super only "
4711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "allowed for 'this' in <init>");
4712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        okay = false;
4713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
4714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
4715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }  else if (calledMethod->clazz != thisClass) {
4716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: invoke-direct <init> must be on current "
4717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "class or super\n");
4718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* arg must be an uninitialized reference */
4723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!regTypeIsUninitReference(thisType)) {
4724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: can only initialize the uninitialized\n");
4725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
4730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Replace the uninitialized reference with an initialized
4731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * one, and clear the entry in the uninit map.  We need to
4732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * do this for all registers that have the same object
4733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * instance in them, not just the "this" register.
4734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
4735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int uidx = regTypeToUninitIndex(thisType);
4736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
4737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    thisType, &okay);
4738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!okay)
4739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getMethodReturnType(calledMethod);
4742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setResultRegisterType(workRegs, insnRegCount,
4743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                returnType, &okay);
4744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justSetResult = true;
4745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_STATIC:
4748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_STATIC_RANGE:
4749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType returnType;
4751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* calledMethod;
4752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isRange;
4753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isRange =  (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
4755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &decInsn, uninitMap, METHOD_STATIC, isRange,
4757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            false, &okay);
4758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getMethodReturnType(calledMethod);
4762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
4763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justSetResult = true;
4764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_INTERFACE:
4767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_INTERFACE_RANGE:
4768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegType /*thisType,*/ returnType;
4770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* absMethod;
4771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool isRange;
4772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            isRange =  (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
4774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            &decInsn, uninitMap, METHOD_INTERFACE, isRange,
4776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            false, &okay);
4777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0       /* can't do this here, fails on dalvik test 052-verifier-fun */
4781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Get the type of the "this" arg, which should always be an
4783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * interface class.  Because we don't do a full merge on
4784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * interface classes, this might have reduced to Object.
4785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            thisType = getInvocationThis(workRegs, insnRegCount,
4787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        &decInsn, &okay);
4788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!okay)
4789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thisType == kRegTypeZero) {
4792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* null pointer always passes (and always fails at runtime) */
4793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
4794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* thisClass;
4795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                thisClass = regTypeInitializedReferenceToClass(thisType);
4797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (thisClass == NULL) {
4798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: interface call on uninitialized\n");
4799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
4804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Either "thisClass" needs to be the interface class that
4805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * defined absMethod, or absMethod's class needs to be one
4806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * of the interfaces implemented by "thisClass".  (Or, if
4807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * we couldn't complete the merge, this will be Object.)
4808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
4809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (thisClass != absMethod->clazz &&
4810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    thisClass != gDvm.classJavaLangObject &&
4811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !dvmImplements(thisClass, absMethod->clazz))
4812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
4813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
4814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            absMethod->name, thisClass->descriptor);
4815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    okay = false;
4816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
4817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We don't have an object instance, so we can't find the
4823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * concrete method.  However, all of the type information is
4824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in the abstract method, so we're good.
4825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnType = getMethodReturnType(absMethod);
4827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
4828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            justSetResult = true;
4829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEG_INT:
4833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NOT_INT:
4834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, &okay);
4836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEG_LONG:
4838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NOT_LONG:
4839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeLongLo, &okay);
4841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEG_FLOAT:
4843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeFloat, &okay);
4845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_NEG_DOUBLE:
4847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeDoubleLo, &okay);
4849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_LONG:
4851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeInteger, &okay);
4853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_FLOAT:
4855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeInteger, &okay);
4857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_DOUBLE:
4859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeInteger, &okay);
4861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_LONG_TO_INT:
4863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeLongLo, &okay);
4865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_LONG_TO_FLOAT:
4867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeLongLo, &okay);
4869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_LONG_TO_DOUBLE:
4871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeLongLo, &okay);
4873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FLOAT_TO_INT:
4875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeFloat, &okay);
4877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FLOAT_TO_LONG:
4879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeFloat, &okay);
4881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_FLOAT_TO_DOUBLE:
4883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeFloat, &okay);
4885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DOUBLE_TO_INT:
4887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeDoubleLo, &okay);
4889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DOUBLE_TO_LONG:
4891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeDoubleLo, &okay);
4893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DOUBLE_TO_FLOAT:
4895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeDoubleLo, &okay);
4897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_BYTE:
4899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeByte, kRegTypeInteger, &okay);
4901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_CHAR:
4903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeChar, kRegTypeInteger, &okay);
4905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INT_TO_SHORT:
4907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkUnop(workRegs, insnRegCount, &decInsn,
4908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeShort, kRegTypeInteger, &okay);
4909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_INT:
4912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_INT:
4913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_INT:
4914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_INT:
4915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_INT:
4916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHL_INT:
4917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHR_INT:
4918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_USHR_INT:
4919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
4921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_INT:
4923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_INT:
4924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_INT:
4925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
4927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_LONG:
4929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_LONG:
4930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_LONG:
4931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_LONG:
4932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_LONG:
4933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_LONG:
4934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_LONG:
4935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_LONG:
4936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
4938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHL_LONG:
4940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHR_LONG:
4941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_USHR_LONG:
4942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* shift distance is Int, making these different from other binops */
4943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
4945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_FLOAT:
4947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_FLOAT:
4948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_FLOAT:
4949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_FLOAT:
4950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_FLOAT:
4951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
4953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_DOUBLE:
4955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_DOUBLE:
4956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_DOUBLE:
4957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_DOUBLE:
4958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_DOUBLE:
4959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop(workRegs, insnRegCount, &decInsn,
4960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
4961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_INT_2ADDR:
4963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_INT_2ADDR:
4964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_INT_2ADDR:
4965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_INT_2ADDR:
4966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHL_INT_2ADDR:
4967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHR_INT_2ADDR:
4968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_USHR_INT_2ADDR:
4969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
4970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
4971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_INT_2ADDR:
4973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_INT_2ADDR:
4974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_INT_2ADDR:
4975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
4976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
4977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_INT_2ADDR:
4979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
4980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
4981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_LONG_2ADDR:
4983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_LONG_2ADDR:
4984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_LONG_2ADDR:
4985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_LONG_2ADDR:
4986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_LONG_2ADDR:
4987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_LONG_2ADDR:
4988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_LONG_2ADDR:
4989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_LONG_2ADDR:
4990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
4991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
4992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHL_LONG_2ADDR:
4994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHR_LONG_2ADDR:
4995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_USHR_LONG_2ADDR:
4996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
4997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
4998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
4999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_FLOAT_2ADDR:
5000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_FLOAT_2ADDR:
5001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_FLOAT_2ADDR:
5002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_FLOAT_2ADDR:
5003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_FLOAT_2ADDR:
5004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
5005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
5006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_DOUBLE_2ADDR:
5008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SUB_DOUBLE_2ADDR:
5009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_DOUBLE_2ADDR:
5010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_DOUBLE_2ADDR:
5011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_DOUBLE_2ADDR:
5012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkBinop2addr(workRegs, insnRegCount, &decInsn,
5013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
5014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_INT_LIT16:
5016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RSUB_INT:
5017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_INT_LIT16:
5018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_INT_LIT16:
5019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_INT_LIT16:
5020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkLitop(workRegs, insnRegCount, &decInsn,
5021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, false, &okay);
5022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_INT_LIT16:
5024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_INT_LIT16:
5025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_INT_LIT16:
5026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkLitop(workRegs, insnRegCount, &decInsn,
5027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, true, &okay);
5028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_ADD_INT_LIT8:
5030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_RSUB_INT_LIT8:
5031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_MUL_INT_LIT8:
5032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_DIV_INT_LIT8:
5033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_REM_INT_LIT8:
5034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHL_INT_LIT8:
5035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_SHR_INT_LIT8:
5036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_USHR_INT_LIT8:
5037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkLitop(workRegs, insnRegCount, &decInsn,
5038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, false, &okay);
5039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_AND_INT_LIT8:
5041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_OR_INT_LIT8:
5042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_XOR_INT_LIT8:
5043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkLitop(workRegs, insnRegCount, &decInsn,
5044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kRegTypeInteger, kRegTypeInteger, true, &okay);
5045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Verifying "quickened" instructions is tricky, because we have
5050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * discarded the original field/method information.  The byte offsets
5051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and vtable indices only have meaning in the context of an object
5052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance.
5053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If a piece of code declares a local reference variable, assigns
5055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * null to it, and then issues a virtual method call on it, we
5056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cannot evaluate the method call during verification.  This situation
5057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * isn't hard to handle, since we know the call will always result in an
5058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NPE, and the arguments and return value don't matter.  Any code that
5059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * depends on the result of the method call is inaccessible, so the
5060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fact that we can't fully verify anything that comes after the bad
5061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call is not a problem.
5062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We must also consider the case of multiple code paths, only some of
5064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which involve a null reference.  We can completely verify the method
5065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if we sidestep the results of executing with a null reference.
5066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For example, if on the first pass through the code we try to do a
5067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * virtual method invocation through a null ref, we have to skip the
5068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method checks and have the method return a "wildcard" type (which
5069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * merges with anything to become that other thing).  The move-result
5070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will tell us if it's a reference, single-word numeric, or double-word
5071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * value.  We continue to perform the verification, and at the end of
5072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the function any invocations that were never fully exercised are
5073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * marked as null-only.
5074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We would do something similar for the field accesses.  The field's
5076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * type, once known, can be used to recover the width of short integers.
5077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the object reference was null, the field-get returns the "wildcard"
5078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * type, which is acceptable for any operation.
5079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_EXECUTE_INLINE:
5081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_DIRECT_EMPTY:
5082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_QUICK:
5083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_WIDE_QUICK:
5084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IGET_OBJECT_QUICK:
5085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_QUICK:
5086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_WIDE_QUICK:
5087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_IPUT_OBJECT_QUICK:
5088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_VIRTUAL_QUICK:
5089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_VIRTUAL_QUICK_RANGE:
5090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_SUPER_QUICK:
5091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_INVOKE_SUPER_QUICK_RANGE:
5092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = false;
5093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* these should never appear */
5096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_3E:
5097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_3F:
5098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_40:
5099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_41:
5100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_42:
5101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_43:
5102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_73:
5103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_79:
5104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_7A:
5105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E3:
5106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E4:
5107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E5:
5108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E6:
5109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E7:
5110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E8:
5111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_E9:
5112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_EA:
5113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_EB:
5114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_EC:
5115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_ED:
5116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_EF:
5117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_F1:
5118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_FC:
5119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_FD:
5120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_FE:
5121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case OP_UNUSED_FF:
5122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        okay = false;
5123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
5124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DO NOT add a "default" clause here.  Without it the compiler will
5127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * complain if an instruction is missing (which is desirable).
5128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!okay) {
5132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
5133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            decInsn.opCode, insnIdx);
5134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
5135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we didn't just set the result register, clear it out.  This
5139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * ensures that you can only use "move-result" immediately after the
5140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * result is set.
5141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!justSetResult) {
5143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int reg = RESULT_REGISTER(insnRegCount);
5144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown;
5145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle "continue".  Tag the next consecutive instruction.
5149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanContinue) != 0) {
5151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
5152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (insnIdx+insnWidth >= insnsSize) {
5153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY_METH(meth,
5154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "VFY: execution can walk off end of code area (from 0x%x)\n",
5155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx);
5156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
5157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
5160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The only way to get to a move-exception instruction is to get
5161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * thrown there.  Make sure the next instruction isn't one.
5162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkMoveException(meth, insnIdx+insnWidth, "next"))
5164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
5165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
5167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We want to update the registers and set the "changed" flag on the
5168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * next instruction (if necessary).  We may not be storing register
5169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * changes for all addresses, so for non-branch targets we just
5170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * compare "entry" vs. "work" to see if we've changed anything.
5171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
5172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (getRegisterLine(regTable, insnIdx+insnWidth) != NULL) {
5173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth,
5174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                workRegs);
5175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
517699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            /*
517799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project             * We didn't record register data for the next entry, so we have
517899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project             * to assume that something has changed and re-evaluate it.
517999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project             */
518099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
5181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle "branch".  Tag the branch target.
5186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * NOTE: instructions like OP_EQZ provide information about the state
5188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the register when the branch is taken or not taken.  For example,
5189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * somebody could get a reference field, check it for zero, and if the
5190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * branch is taken immediately store that register in a boolean field
5191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * since the value is known to be zero.  We do not currently account for
5192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that, and will reject the code.
5193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanBranch) != 0) {
5195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool isConditional;
5196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget,
5198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                &isConditional))
5199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
5200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* should never happen after static verification */
5201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG_VFY_METH(meth, "VFY: bad branch at %d\n", insnIdx);
5202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
5203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
5205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
5206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!checkMoveException(meth, insnIdx+branchTarget, "branch"))
5208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
5209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
521099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /* update branch target, set "changed" if appropriate */
5211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget,
5212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            workRegs);
5213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle "switch".  Tag all possible branch targets.
5217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We've already verified that the table is structurally sound, so we
5219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just need to walk through and tag the targets.
5220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanSwitch) != 0) {
5222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16);
5223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const u2* switchInsns = insns + offsetToSwitch;
5224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int switchCount = switchInsns[1];
5225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int offsetToTargets, targ;
5226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((*insns & 0xff) == OP_PACKED_SWITCH) {
5228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* 0=sig, 1=count, 2/3=firstKey */
5229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            offsetToTargets = 4;
5230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
5231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* 0=sig, 1=count, 2..count*2 = keys */
5232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((*insns & 0xff) == OP_SPARSE_SWITCH);
5233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            offsetToTargets = 2 + 2*switchCount;
5234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify each switch target */
5237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (targ = 0; targ < switchCount; targ++) {
5238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int offset, absOffset;
5239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* offsets are 32-bit, and only partly endian-swapped */
5241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            offset = switchInsns[offsetToTargets + targ*2] |
5242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16);
5243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            absOffset = insnIdx + offset;
5244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(absOffset >= 0 && absOffset < insnsSize);
5246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!checkMoveException(meth, absOffset, "switch"))
5248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
5249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            updateRegisters(meth, insnFlags, regTable, absOffset, workRegs);
5251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Handle instructions that can throw and that are sitting in a
5256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "try" block.  (If they're not in a "try" block when they throw,
5257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * control transfers out of the method.)
5258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
5260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
5261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
5262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexCode* pCode = dvmGetMethodCode(meth);
5263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexCatchIterator iterator;
5264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
5266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (;;) {
5267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
5268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (handler == NULL) {
5270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
5271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
5272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* note we use entryRegs, not workRegs */
5274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                updateRegisters(meth, insnFlags, regTable, handler->address,
5275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    entryRegs);
5276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
5277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
5281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update startGuess.  Advance to the next instruction of that's
5282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * possible, otherwise use the branch target if one was found.  If
5283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * neither of those exists we're in a return or throw; leave startGuess
5284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * alone and let the caller sort it out.
5285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((nextFlags & kInstrCanContinue) != 0) {
5287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx);
5288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if ((nextFlags & kInstrCanBranch) != 0) {
5289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* we're still okay if branchTarget is zero */
5290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pStartGuess = insnIdx + branchTarget;
5291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(*pStartGuess >= 0 && *pStartGuess < insnsSize &&
5294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
5295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
5297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
5299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
5300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
5301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
5303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * callback function used in dumpRegTypes to print local vars
5304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * valid at a given address.
5305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
5306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress,
5307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char *name, const char *descriptor,
5308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char *signature)
5309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
5310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int addr = *((int *)cnxt);
5311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (addr >= (int) startAddress && addr < (int) endAddress)
5313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
5314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("        %2d: '%s' %s\n", reg, name, descriptor);
5315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
5317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
5319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the register types for the specifed address to the log file.
5320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
5321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,
5322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const RegType* addrRegs, int addr, const char* addrName,
5323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const UninitInstanceMap* uninitMap, int displayFlags)
5324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
5325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int regCount = meth->registersSize;
5326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int fullRegCount = regCount + kExtraRegs;
5327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr);
5328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
5329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth));
5331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1;
5333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char regChars[regCharSize +1];
5334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(regChars, ' ', regCharSize);
5335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    regChars[0] = '[';
5336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (regCount == 0)
5337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        regChars[1] = ']';
5338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
5339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']';
5340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    regChars[regCharSize] = '\0';
5341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //const RegType* addrRegs = getRegisterLine(regTable, addr);
5343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < regCount + kExtraRegs; i++) {
5345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char tch;
5346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (addrRegs[i]) {
5348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeUnknown:       tch = '.';  break;
5349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeConflict:      tch = 'X';  break;
5350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeFloat:         tch = 'F';  break;
5351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeZero:          tch = '0';  break;
5352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeOne:           tch = '1';  break;
5353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeBoolean:       tch = 'Z';  break;
5354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypePosByte:       tch = 'b';  break;
5355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeByte:          tch = 'B';  break;
5356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypePosShort:      tch = 's';  break;
5357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeShort:         tch = 'S';  break;
5358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeChar:          tch = 'C';  break;
5359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeInteger:       tch = 'I';  break;
5360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeLongLo:        tch = 'J';  break;
5361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeLongHi:        tch = 'j';  break;
5362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeDoubleLo:      tch = 'D';  break;
5363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kRegTypeDoubleHi:      tch = 'd';  break;
5364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
5365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regTypeIsReference(addrRegs[i])) {
5366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (regTypeIsUninitReference(addrRegs[i]))
5367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    tch = 'U';
5368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                else
5369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    tch = 'L';
5370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
5371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tch = '*';
5372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
5373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
5374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
5375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (i < regCount)
5378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regChars[1 + i + (i/4)] = tch;
5379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
5380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regChars[1 + i + (i/4) + 2] = tch;
5381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (addr == 0 && addrName != NULL)
5384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%c%s %s\n", branchTarget ? '>' : ' ', addrName, regChars);
5385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
5386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%c0x%04x %s\n", branchTarget ? '>' : ' ', addr, regChars);
5387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (displayFlags & DRT_SHOW_REF_TYPES) {
5389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < regCount + kExtraRegs; i++) {
5390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero)
5391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
5392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ClassObject* clazz;
5393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz = regTypeReferenceToClass(addrRegs[i], uninitMap);
5395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmValidateObject((Object*)clazz));
5396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i < regCount) {
5397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGI("        %2d: 0x%08x %s%s\n",
5398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        i, addrRegs[i],
5399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor);
5401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
5402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGI("        RS: 0x%08x %s%s\n",
5403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        addrRegs[i],
5404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor);
5406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
5407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
5408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
5409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (displayFlags & DRT_SHOW_LOCALS) {
5411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile,
5412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmGetMethodCode(meth),
5413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->clazz->descriptor,
5414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->prototype.protoIdx,
5415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->accessFlags,
5416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                NULL, logLocalsCb, &addr);
5417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
5418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
5419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5420