Class.cpp revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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 * Class loading, including bootstrap class loader, linking, and
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialization.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define LOG_CLASS_LOADING 0
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexClass.h"
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stddef.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/stat.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <cutils/process_name.h>
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/types.h>
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on Linking and Verification
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe basic way to retrieve a class is to load it, make sure its superclass
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand interfaces are available, prepare its fields, and return it.  This gets
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta little more complicated when multiple threads can be trying to retrieve
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe class simultaneously, requiring that we use the class object's monitor
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectto keep things orderly.
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe linking (preparing, resolving) of a class can cause us to recursively
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectload superclasses and interfaces.  Barring circular references (e.g. two
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses that are superclasses of each other), this will complete without
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe loader attempting to access the partially-linked class.
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWith verification, the situation is different.  If we try to verify
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectevery class as we load it, we quickly run into trouble.  Even the lowly
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.Object requires CloneNotSupportedException; follow the list
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectof referenced classes and you can head down quite a trail.  The trail
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecteventually leads back to Object, which is officially not fully-formed yet.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe VM spec (specifically, v2 5.4.1) notes that classes pulled in during
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification do not need to be prepared or verified.  This means that we
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectare allowed to have loaded but unverified classes.  It further notes that
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe class must be verified before it is initialized, which allows us to
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdefer verification for all classes until class init.  You can't execute
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcode or access fields in an uninitialized class, so this is safe.
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIt also allows a more peaceful coexistence between verified and
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunverifiable code.  If class A refers to B, and B has a method that
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectrefers to a bogus class C, should we allow class A to be verified?
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf A only exercises parts of B that don't use class C, then there is
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnothing wrong with running code in A.  We can fully verify both A and B,
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand allow execution to continue until B causes initialization of C.  The
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectVerifyError is thrown close to the point of use.
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis gets a little weird with java.lang.Class, which is the only class
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthat can be instantiated before it is initialized.  We have to force
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectinitialization right after the class is created, because by definition we
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthave instances of it on the heap, and somebody might get a class object and
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstart making virtual calls on it.  We can end up going recursive during
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification of java.lang.Class, but we avoid that by checking to see if
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification is already in progress before we try to initialize it.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on class loaders and interaction with optimization / verification
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIn what follows, "pre-verification" and "optimization" are the steps
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectperformed by the dexopt command, which attempts to verify and optimize
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses as part of unpacking jar files and storing the DEX data in the
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdalvik-cache directory.  These steps are performed by loading the DEX
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfiles directly, without any assistance from ClassLoader instances.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen we pre-verify and optimize a class in a DEX file, we make some
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectassumptions about where the class loader will go to look for classes.
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we can't guarantee those assumptions, e.g. because a class ("AppClass")
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectreferences something not defined in the bootstrap jars or the AppClass jar,
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwe can't pre-verify or optimize the class.
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe VM doesn't define the behavior of user-defined class loaders.
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor example, suppose application class AppClass, loaded by UserLoader,
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthas a method that creates a java.lang.String.  The first time
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAppClass.stringyMethod tries to do something with java.lang.String, it
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectasks UserLoader to find it.  UserLoader is expected to defer to its parent
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectloader, but isn't required to.  UserLoader might provide a replacement
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor String.
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe can run into trouble if we pre-verify AppClass with the assumption that
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.String will come from core.jar, and don't verify this assumption
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectat runtime.  There are two places that an alternate implementation of
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.String can come from: the AppClass jar, or from some other jar
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthat UserLoader knows about.  (Someday UserLoader will be able to generate
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsome bytecode and call DefineClass, but not yet.)
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo handle the first situation, the pre-verifier will explicitly check for
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconflicts between the class being optimized/verified and the bootstrap
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses.  If an app jar contains a class that has the same package and
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclass name as a class in a bootstrap jar, the verification resolver refuses
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectto find either, which will block pre-verification and optimization on
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses that reference ambiguity.  The VM will postpone verification of
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe app class until first load.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor the second situation, we need to ensure that all references from a
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpre-verified class are satisified by the class' jar or earlier bootstrap
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjars.  In concrete terms: when resolving a reference to NewClass,
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwhich was caused by a reference in class AppClass, we check to see if
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAppClass was pre-verified.  If so, we require that NewClass comes out
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectof either the AppClass jar or one of the jars in the bootstrap path.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(We may not control the class loaders, but we do manage the DEX files.
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe can verify that it's either (loader==null && dexFile==a_boot_dex)
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projector (loader==UserLoader && dexFile==AppClass.dexFile).  Classes from
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDefineClass can't be pre-verified, so this doesn't apply.)
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis should ensure that you can't "fake out" the pre-verifier by creating
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta user-defined class loader that replaces system classes.  It should
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectalso ensure that you can write such a loader and have it work in the
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexpected fashion; all you lose is some performance due to "just-in-time
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification" and the lack of DEX optimizations.
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThere is a "back door" of sorts in the class resolution check, due to
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe fact that the "class ref" entries are shared between the bytecode
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand meta-data references (e.g. annotations and exception handler lists).
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe class references in annotations have no bearing on class verification,
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectso when a class does an annotation query that causes a class reference
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectindex to be resolved, we don't want to fail just because the calling
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclass was pre-verified and the resolved class is in some random DEX file.
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe successful resolution adds the class to the "resolved classes" table,
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectso when optimized bytecode references it we don't repeat the resolve-time
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcheck.  We can avoid this by not updating the "resolved classes" table
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwhen the class reference doesn't come out of something that has been
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchecked by the verifier, but that has a nonzero performance impact.
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSince the ultimate goal of this test is to catch an unusual situation
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(user-defined class loaders redefining core classes), the added caution
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmay not be worth the performance hit.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap);
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeCpeArray(ClassPathEntry* cpe);
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassFromLoaderNoInit(
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor, Object* loader);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassNoInit(const char* descriptor, Object* loader,\
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex);
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex(DvmDex* pDvmDex,
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, Object* loader);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,\
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeJniArgInfo(const DexProto* proto);
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadSFieldFromDex(ClassObject* clazz,
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexSField, StaticField* sfield);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadIFieldFromDex(ClassObject* clazz,
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexIField, InstField* field);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeMethodInnards(Method* meth);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createVtable(ClassObject* clazz);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createIftable(ClassObject* clazz);
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool insertMethodStubs(ClassObject* clazz);
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool computeFieldOffsets(ClassObject* clazz);
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwEarlierClassFailure(ClassObject* clazz);
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Logs information about a class loading with given timestamp.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: In the case where we fail in dvmLinkClass() and log the class as closing (type='<'),
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it would probably be better to use a new type code to indicate the failure.  This change would
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * require a matching change in the parser and analysis code in frameworks/base/tools/preload.
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logClassLoadWithTime(char type, ClassObject* clazz, u8 time) {
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pid_t ppid = getppid();
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pid_t pid = getpid();
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int tid = (unsigned int) pthread_self();
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOG(LOG_INFO, "PRELOAD", "%c%d:%d:%d:%s:%d:%s:%lld\n", type, ppid, pid, tid,
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        get_process_name(), (int) clazz->classLoader, clazz->descriptor,
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        time);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Logs information about a class loading.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logClassLoad(char type, ClassObject* clazz) {
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    logClassLoadWithTime(type, clazz, dvmGetThreadCpuTimeNsec());
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Some LinearAlloc unit tests.
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linearAllocTests()
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* fiddle;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int try = 1;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (try) {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 0:
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fiddle = dvmLinearAlloc(NULL, 3200-28);
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(NULL, fiddle);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 1:
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fiddle = dvmLinearAlloc(NULL, 3200-24);
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(NULL, fiddle);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 2:
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fiddle = dvmLinearAlloc(NULL, 3200-20);
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(NULL, fiddle);
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 3:
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fiddle = dvmLinearAlloc(NULL, 3200-16);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(NULL, fiddle);
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 4:
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fiddle = dvmLinearAlloc(NULL, 3200-12);
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(NULL, fiddle);
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 896);
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 20);      // watch addr of this alloc
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 1);
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'q';
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 4096);
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'x';
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[4095] = 'y';
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearFree(NULL, fiddle);
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 0);
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearRealloc(NULL, fiddle, 12);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[11] = 'z';
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearRealloc(NULL, fiddle, 5);
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle = dvmLinearAlloc(NULL, 17001);
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'x';
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[17000] = 'y';
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* str = dvmLinearStrdup(NULL, "This is a test!");
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("GOT: '%s'\n", str);
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearAllocDump(NULL);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearFree(NULL, str);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the bootstrap class loader.
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call this after the bootclasspath string has been finalized.
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmClassStartup(void)
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* unlinkedClass;
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make this a requirement -- don't currently support dirs in path */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(gDvm.bootClassPathStr, ".") == 0) {
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("ERROR: must specify non-'.' bootclasspath\n");
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses =
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.pBootLoaderAlloc = dvmLinearAllocCreate(NULL);
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.pBootLoaderAlloc == NULL)
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        linearAllocTests();
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(0);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Class serial number.  We start with a high value to make it distinct
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in binary dumps (e.g. hprof).
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classSerialNumber = 0x50000000;
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* This placeholder class is used while a ClassObject is
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * loading/linking so those not in the know can still say
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "obj->clazz->...".
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlinkedClass = &gDvm.unlinkedJavaLangClassObject;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(unlinkedClass, 0, sizeof(*unlinkedClass));
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Set obj->clazz to NULL so anyone who gets too interested
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the fake class will crash.
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DVM_OBJECT_INIT(&unlinkedClass->obj, NULL);
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unlinkedClass->descriptor = "!unlinkedClass";
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetClassSerialNumber(unlinkedClass);
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.unlinkedJavaLangClass = unlinkedClass;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Process the bootstrap class path.  This means opening the specified
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DEX or Jar files and possibly running them through the optimizer.
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.bootClassPath == NULL);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    processClassPath(gDvm.bootClassPathStr, true);
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPath == NULL)
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up.
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClassShutdown(void)
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard all system-loaded classes */
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableFree(gDvm.loadedClasses);
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses = NULL;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard primitive classes created for arrays */
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < PRIM_MAX; i++)
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFreeClassInnards(gDvm.primitiveClass[i]);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* this closes DEX files, JAR files, etc. */
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeCpeArray(gDvm.bootClassPath);
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = NULL;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearAllocDestroy(NULL);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Bootstrap class loader
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a ClassPathEntry array.
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpClassPath(const ClassPathEntry* cpe)
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx = 0;
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* kindStr;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDir:       kindStr = "dir";    break;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:       kindStr = "jar";    break;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:       kindStr = "dex";    break;
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:            kindStr = "???";    break;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  %2d: type=%s %s %p\n", idx, kindStr, cpe->fileName, cpe->ptr);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (CALC_CACHE_STATS && cpe->kind == kCpeJar) {
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DvmDex* pDvmDex = dvmGetJarFileDex(pJarFile);
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpAtomicCacheStats(pDvmDex->pInterfaceCache);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        idx++;
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of the bootstrap class path.
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpBootClassPath(void)
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClassPath(gDvm.bootClassPath);
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the class path contains the specified path.
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmClassPathContains(const ClassPathEntry* cpe, const char* path)
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(cpe->fileName, path) == 0)
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free an array of ClassPathEntry structs.
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We release the contents of each entry, then free the array itself.
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeCpeArray(ClassPathEntry* cpe)
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpeStart = cpe;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe == NULL)
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free JarFile */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmJarFileFree((JarFile*) cpe->ptr);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free RawDexFile */
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmRawDexFileFree((RawDexFile*) cpe->ptr);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* e.g. kCpeDir */
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cpe->ptr == NULL);
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cpe->fileName);
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(cpeStart);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Prepare a ClassPathEntry struct, which at this point only has a valid
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filename.  We need to figure out what kind of file it is, and for
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * everything other than directories we need to open it up and see
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * what's inside.
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap)
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile* pJarFile = NULL;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RawDexFile* pRawDexFile = NULL;
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct stat sb;
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cc = stat(cpe->fileName, &sb);
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cc < 0) {
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Unable to stat classpath element '%s'\n", cpe->fileName);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (S_ISDIR(sb.st_mode)) {
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The directory will usually have .class files in subdirectories,
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * which may be a few levels down.  Doing a recursive scan and
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * caching the results would help us avoid hitting the filesystem
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * on misses.  Whether or not this is of measureable benefit
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * depends on a number of factors, but most likely it is not
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * worth the effort (especially since most of our stuff will be
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in DEX or JAR).
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeDir;
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cpe->ptr == NULL);
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeJar;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->ptr = pJarFile;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: do we still want to support "raw" DEX files in the classpath?
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0)
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeDex;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->ptr = pRawDexFile;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a colon-separated list of directories, Zip files, and DEX files
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into an array of ClassPathEntry structs.
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we're unable to load a bootstrap class path entry, we fail.  This
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is necessary to preserve the dependencies implied by optimized DEX files
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (e.g. if the same class appears in multiple places).
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * During normal startup we fail if there are no entries, because we won't
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * get very far without the basic language support classes, but if we're
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * optimizing a DEX file we allow it.
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpe = NULL;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangle;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* end;
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx, count;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pathStr != NULL);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mangle = strdup(pathStr);
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through and essentially strtok() the string.  Get a count of
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the #of elements while we're at it.
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the path was constructed strangely (e.g. ":foo::bar:") this will
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * over-allocate, which isn't ideal but is mostly harmless.
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = 1;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (cp = mangle; *cp != '\0'; cp++) {
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == ':') {   /* separates two entries */
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    end = cp;
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage.  We over-alloc by one so we can set an "end" marker.
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe = (ClassPathEntry*) calloc(count+1, sizeof(ClassPathEntry));
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set the global pointer so the DEX file dependency stuff can find it.
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Go through a second time, pulling stuff out.
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cp = mangle;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = 0;
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cp < end) {
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '\0') {
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leading, trailing, or doubled ':'; ignore it */
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassPathEntry tmp;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.kind = kCpeUnknown;
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.fileName = strdup(cp);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.ptr = NULL;
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* drop an end marker here so DEX loader can walk unfinished list */
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].kind = kCpeLastEntry;
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].fileName = NULL;
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].ptr = NULL;
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!prepareCpe(&tmp, isBootstrap)) {
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGD("Failed on '%s' (boot=%d)\n", tmp.fileName, isBootstrap);
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* drop from list and continue on */
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(tmp.fileName);
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (isBootstrap || gDvm.optimizing) {
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* if boot path entry or we're optimizing, this is fatal */
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(cpe);
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    cpe = NULL;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto bail;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* copy over, pointers and all */
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (tmp.fileName[0] != '/')
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Non-absolute bootclasspath entry '%s'\n",
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        tmp.fileName);
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cpe[idx] = tmp;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                idx++;
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp += strlen(cp) +1;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx <= count);
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (idx == 0 && !gDvm.optimizing) {
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("ERROR: no valid entries found in bootclasspath '%s'\n", pathStr);
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cpe);
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe = NULL;
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("  (filled %d of %d slots)\n", idx, count);
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put end marker in over-alloc slot */
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].kind = kCpeLastEntry;
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].fileName = NULL;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].ptr = NULL;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dumpClassPath(cpe);
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangle);
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the DEX files we loaded from the bootstrap class path for a DEX
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file that has the class with the matching descriptor.
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the matching DEX file and DexClassDef entry if found, otherwise
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns NULL.
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic DvmDex* searchBootPathForClass(const char* descriptor,
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef** ppClassDef)
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pFoundDef = NULL;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pFoundFile = NULL;
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...\n",
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGV("+++  checking '%s' (%d)\n", cpe->fileName, cpe->kind);
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDir:
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Directory entries ('%s') not supported in bootclasspath\n",
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cpe->fileName);
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JarFile* pJarFile = (JarFile*) cpe->ptr;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetJarFileDex(pJarFile);
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr;
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetRawDexFileDex(pRawDexFile);
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unknown kind %d\n", cpe->kind);
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Special handling during verification + optimization.
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The DEX optimizer needs to load classes from the DEX file it's working
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * on.  Rather than trying to insert it into the bootstrap class path
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * or synthesizing a class loader to manage it, we just make it available
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here.  It logically comes after all existing entries in the bootstrap
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class path.
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPathOptExtra != NULL) {
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef =
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor);
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pClassDef != NULL) {
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* found */
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundDef = pClassDef;
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundFile = gDvm.bootClassPathOptExtra;
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfound:
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ppClassDef = pFoundDef;
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pFoundFile;
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the "extra" DEX, which becomes a de facto member of the bootstrap
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class set.
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetBootPathExtraDex(DvmDex* pDvmDex)
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPathOptExtra = pDvmDex;
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the #of entries in the bootstrap class path.
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Used for ClassLoader.getResources().)
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetBootPathSize(void)
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry)
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe - gDvm.bootClassPath;
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a resource with the specified name in entry N of the boot class path.
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We return a newly-allocated String of one of these forms:
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   file://path/name
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   jar:file://path!/name
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Where "path" is the bootstrap class path entry and "name" is the string
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * passed into this method.  "path" needs to be an absolute path (starting
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with '/'); if it's not we'd need to "absolutify" it as part of forming
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the URL string.
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectStringObject* dvmGetBootPathResource(const char* name, int idx)
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int kUrlOverhead = 13;        // worst case for Jar URL
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* urlObj = NULL;
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ searching for resource '%s' in %d(%s)\n",
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        name, idx, cpe[idx].fileName);
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we could use direct array index, but I don't entirely trust "idx" */
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (idx-- && cpe->kind != kCpeLastEntry)
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe->kind == kCpeLastEntry) {
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1];
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (cpe->kind) {
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeDir:
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(urlBuf, "file://%s/%s", cpe->fileName, name);
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (access(urlBuf+7, F_OK) != 0)
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeJar:
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dexZipFindEntry(&pJarFile->archive, name) == NULL)
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name);
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeDex:
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("No resources in DEX files\n");
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ using URL='%s'\n", urlBuf);
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    urlObj = dvmCreateStringFromCstr(urlBuf, ALLOC_DEFAULT);
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return urlObj;
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class list management
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* search for these criteria in the Class hash table */
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ClassMatchCriteria {
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     loader;
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ClassMatchCriteria;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kInitLoaderInc  4       /* must be power of 2 */
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine if "loader" appears in clazz' initiating loader list.
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class hash table lock must be held when calling here, since
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it's also used when updating a class' initiating loader list.
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: switch to some sort of lock-free data structure so we don't have
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to grab the lock to do a lookup.  Among other things, this would improve
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the speed of compareDescriptorClasses().
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader)
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The bootstrap class loader can't be just an initiating loader for
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anything (it's always the defining loader if the class is visible
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to it).  We don't put defining loaders in the initiating list.
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader == NULL)
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Scan the list for a match.  The list is expected to be short.
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = clazz->initiatingLoaderCount-1; i >= 0; --i) {
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->initiatingLoaders[i] == loader) {
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("+++ found initiating match %p in %s\n",
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    loader, clazz->descriptor);
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "loader" to clazz's initiating loader set, unless it's the defining
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader.
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the common case this will be a short list, so we don't need to do
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything too fancy here.
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This locks gDvm.loadedClasses for synchronization, so don't hold it
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * when calling here.
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddInitiatingLoader(ClassObject* clazz, Object* loader)
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != clazz->classLoader) {
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(loader != NULL);
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Adding %p to '%s' init list\n", loader, clazz->descriptor);
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.loadedClasses);
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Make sure nobody snuck in.  The penalty for adding twice is
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pretty minor, and probably outweighs the O(n^2) hit for
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * checking before every add, so we may not want to do this.
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (false && dvmLoaderInInitiatingList(clazz, loader)) {
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WOW: simultaneous add of initiating class loader\n");
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The list never shrinks, so we just keep a count of the
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * number of elements in it, and reallocate the buffer when
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we run off the end.
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The pointer is initially NULL, so we *do* want to call realloc
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when count==0.
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((clazz->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) {
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object** newList;
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newList = (Object**) realloc(clazz->initiatingLoaders,
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        (clazz->initiatingLoaderCount + kInitLoaderInc)
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * sizeof(Object*));
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (newList == NULL) {
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* this is mainly a cache, so it's not the EotW */
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail_unlock;
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initiatingLoaders = newList;
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("Expanded init list to %d (%s)\n",
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->initiatingLoaderCount+kInitLoaderInc,
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor);
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->initiatingLoaders[clazz->initiatingLoaderCount++] = loader;
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.loadedClasses);
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.)
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entries in the class hash table are stored as { descriptor, d-loader }
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * tuples.  If the hashed class descriptor matches the requested descriptor,
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the hashed defining class loader matches the requested class
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader, we're good.  If only the descriptor matches, we check to see if the
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader is in the hashed class' initiating loader list.  If so, we
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can return "true" immediately and skip some of the loadClass melodrama.
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must lock the hash table before calling here.
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns 0 if a matching entry is found, nonzero otherwise.
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByCrit(const void* vclazz, const void* vcrit)
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit;
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 &&
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == pCrit->loader ||
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (pCrit->loader != NULL &&
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, pCrit->loader)) ));
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //if (match)
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    LOGI("+++ %s %p matches existing %s %p\n",
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        pCrit->descriptor, pCrit->loader,
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        clazz->descriptor, clazz->classLoader);
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instead of a ClassMatchCriteria.
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByClass(const void* vclazz, const void* vaddclazz)
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* addClazz = (const ClassObject*) vaddclazz;
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 &&
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == addClazz->classLoader ||
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (addClazz->classLoader != NULL &&
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) ));
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search through the hash table to find an entry with a matching descriptor
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and an initiating class loader that matches "loader".
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The table entries are hashed on descriptor only, because they're unique
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on *defining* class loader, not *initiating* class loader.  This isn't
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * great, because it guarantees we will have to probe when multiple
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loaders are used.
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note this does NOT try to load a class; it just finds a class that
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has already been loaded.
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "unprepOkay" is set, this will return classes that have been added
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the hash table but are not yet fully loaded and linked.  Otherwise,
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * such classes are ignored.  (The only place that should set "unprepOkay"
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is findClassNoInit(), which will wait for the prep to finish.)
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if not found.
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmLookupClass(const char* descriptor, Object* loader,
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool unprepOkay)
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassMatchCriteria crit;
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.descriptor = descriptor;
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.loader = loader;
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(descriptor);
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p\n",
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThreadSelf()->threadId, descriptor, loader);
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit,
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByCrit, false);
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been added to the hash table but isn't ready for use.
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're going to act like we didn't see it, so that the caller will
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * go through the full "find class" path, which includes locking the
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * object and waiting until it's ready.  We could do that lock/wait
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here, but this is an extremely rare case, and it's simpler to have
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the wait-for-class code centralized.
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (found != NULL && !unprepOkay && !dvmIsClassLinked(found)) {
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Ignoring not-yet-ready %s, using slow path\n",
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((ClassObject*)found)->descriptor);
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        found = NULL;
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) found;
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new class to the hash table.
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class is considered "new" if it doesn't match on both the class
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor and the defining class loader.
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we should probably have separate hash tables for each
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader. This could speed up dvmLookupClass and
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * other common operations. It does imply a VM-visible data structure
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for each ClassLoader object with loaded classes, which we don't
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have yet.
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmAddClassToHash(ClassObject* clazz)
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(clazz->descriptor);
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz,
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByClass, true);
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p\n",
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader,
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (found == (void*) clazz), clazz);
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmCheckClassTablePerf();
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* can happen if two threads load the same class simultaneously */
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (found == (void*) clazz);
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute hash value for a class.
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 hashcalcClass(const void* item)
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor);
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check the performance of the "loadedClasses" hash table.
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCheckClassTablePerf(void)
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hashcmpClassByClass);
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove a class object from the hash table.
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeClassFromHash(ClassObject* clazz)
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ removeClassFromHash '%s'\n", clazz->descriptor);
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash = dvmComputeUtf8Hash(clazz->descriptor);
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz))
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Hash table remove failed on class '%s'\n", clazz->descriptor);
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class creation
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set clazz->serialNumber to the next available value.
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This usually happens *very* early in class creation, so don't expect
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything else in the class to be ready.
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetClassSerialNumber(ClassObject* clazz)
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 oldValue, newValue;
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->serialNumber == 0);
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do {
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldValue = gDvm.classSerialNumber;
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newValue = oldValue + 1;
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (!ATOMIC_CMP_SWAP(&gDvm.classSerialNumber, oldValue, newValue));
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->serialNumber = (u4) oldValue;
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded and initialized if it has not already been.
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If necessary, the superclass will be loaded.
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClass(const char* descriptor, Object* loader)
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindClassNoInit(descriptor, loader);
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded if it has not already been, as will its
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass.  It will not be initialized.
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClassNoInit(const char* descriptor,
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* loader)
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(descriptor != NULL);
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //assert(loader != NULL);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*descriptor == '[') {
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Array class.  Find in table, generate if not found.
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return dvmFindArrayClass(descriptor, loader);
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Regular class.  Find in table, load if not found.
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (loader != NULL) {
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return findClassFromLoaderNoInit(descriptor, loader);
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return dvmFindSystemClassNoInit(descriptor);
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified class
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader.  This calls out to let the ClassLoader object do its thing.
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns with NULL and an exception raised on error.
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader)
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        descriptor, loader);
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(loader != NULL);
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do we already have it?
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class loader code does the "is it already loaded" check as
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * well.  However, this call is much faster than calling through
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * interpreted code.  Doing this does mean that in the common case
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (365 out of 420 calls booting the sim) we're doing the
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * lookup-by-descriptor twice.  It appears this is still a win, so
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm keeping it in.
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmLookupClass(descriptor, loader, false);
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL) {
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Already loaded: %s %p\n", descriptor, loader);
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return clazz;
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dotName = NULL;
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = NULL;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* excep;
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* loadClass;
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dotName = dvmDescriptorToDot(descriptor);
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dotName == NULL) {
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT);
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (nameObj == NULL) {
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: cache the vtable offset
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass",
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 "(Ljava/lang/String;)Ljava/lang/Class;");
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loadClass == NULL) {
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Couldn't find loadClass in ClassLoader\n");
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceClassPrepBegin();
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Invoke loadClass().  This will probably result in a couple of
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exceptions being thrown, because the ClassLoader.loadClass()
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation eventually calls VMClassLoader.loadClass to see if
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the bootstrap class loader can find it before doing its own load.
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethod(self, loadClass, loader, &result, nameObj);
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = (ClassObject*) result.l;
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceClassPrepEnd();
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    excep = dvmGetException(self);
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excep != NULL) {
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dotName, loader, excep->clazz->descriptor);
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc(excep, self);
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowChainedExceptionWithClassMessage(
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(excep, self);
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = NULL;
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz != NULL);
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddInitiatingLoader(clazz, loader);
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor, clazz->classLoader, loader, clazz);
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(dotName);
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified DEX file.
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Used by class loaders to instantiate a class object from a
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-managed DEX.
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* classLoader)
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pDvmDex != NULL);
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, classLoader, pDvmDex);
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), scanning through the
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath if it hasn't already been loaded.
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" looks like "Landroid/debug/Stuff;".
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Uses NULL as the defining class loader.
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClass(const char* descriptor)
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClassNoInit(descriptor);
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), searching for it in the
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath.
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, NULL, NULL);
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor). If it's not already loaded,
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we load it and link it, but don't execute <clinit>. (The VM has
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specific limitations on which events can cause initialization.)
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we need to return an indication of whether we loaded the class or
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used an existing definition.  If somebody deliberately tries to load a
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class twice in the same class loader, they should get a LinkageError,
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but inadvertent simultaneous class references should "just work".
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex)
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool profilerNotified = false;
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != NULL) {
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex->pDexFile);
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't expect an exception to be raised at this point.  The
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception handling code is good about managing this.  This *can*
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * happen if a JNI lookup fails and the JNI code doesn't do any
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * error checking before doing another class lookup, so we may just
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want to clear this and restore it on exit.  If we don't, some kinds
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of failures can't be detected without rearranging other stuff.
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Most often when we hit this situation it means that something is
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * broken in the VM or in JNI code, so I'm keeping it in place (and
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * making it an informative abort rather than an assert).
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Class lookup %s attemped while exception %s pending\n",
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            descriptor, dvmGetException(self)->clazz->descriptor);
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpAllThreads(false);
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmLookupClass(descriptor, loader, true);
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepBegin();
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        profilerNotified = true;
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u8 startTime = dvmGetThreadCpuTimeNsec();
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL) {
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);     /* shouldn't be here otherwise */
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL || pClassDef == NULL) {
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowExceptionWithClassMessage(
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Ljava/lang/NoClassDefFoundError;", descriptor);
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* found a match, try to load it */
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* class was found but had issues */
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Lock the class while we link it so other threads must wait for us
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to finish.  Set the "initThreadId" so we can identify recursive
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * invocation.
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->initThreadId = self->threadId;
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add to hash table so lookups succeed.
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * [Are circular references possible when linking a class?]
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->classLoader == loader);
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmAddClassToHash(clazz)) {
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Another thread must have loaded the class after we
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * started but before we finished.  Discard what we've
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * done and leave some hints for the GC.
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (Yes, this happens.)
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let the GC free the class.
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Grab the winning class.
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = dvmLookupClass(descriptor, loader, true);
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz != NULL);
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto got_class;
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoadWithTime('>', clazz, startTime);
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Prepare and resolve.
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmLinkClass(clazz, false)) {
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Make note of the error and clean up the class.
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            removeClassFromHash(clazz);
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFreeClassInnards(clazz);
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let any waiters know.
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmObjectNotifyAll(self, (Object*) clazz);
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, get_process_name());
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: It would probably be better to use a new type code here (instead of '<') to
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * indicate the failure.  This change would require a matching change in the parser
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * and analysis code in frameworks/base/tools/preload.
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            logClassLoad('<', clazz);
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.optimizing) {
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* happens with "external" libs */
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Link of class '%s' failed\n", descriptor);
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Link of class '%s' failed\n", descriptor);
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectNotifyAll(self, (Object*) clazz);
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add class stats to global counters.
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: these should probably be atomic ops.
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numLoadedClasses++;
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods +=
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethodCount + clazz->directMethodCount;
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredInstFields += clazz->ifieldCount;
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Cache pointers to basic classes.  We want to use these in
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * various places, and it's easiest to initialize them on first
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * use rather than trying to force them to initialize (startup
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * ordering makes it weird).
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classJavaLangObject == NULL &&
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(descriptor, "Ljava/lang/Object;") == 0)
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* It should be impossible to get here with anything
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * but the bootclasspath loader.
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.classJavaLangObject = clazz;
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('<', clazz);
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectgot_class:
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can race with other threads for class linking.  We should
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never get here recursively; doing so indicates that two
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes have circular dependencies.
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * One exception: we force discovery of java.lang.Class in
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * dvmLinkClass(), and Class has Object as its superclass.  So
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * if the first thing we ever load is Object, we will init
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Object->Class->Object.  The easiest way to avoid this is to
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * ensure that Object is never the first thing we look up, so
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we get Foo->Class->Object instead.
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsClassLinked(clazz) &&
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->initThreadId == self->threadId)
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Recursive link on class %s\n", clazz->descriptor);
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmUnlockObject(self, (Object*) clazz);
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowExceptionWithClassMessage(
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz = NULL;
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("WAITING  for '%s' (owner=%d)\n",
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor, clazz->initThreadId);
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Somebody else tried to load this and failed.  We need to raise
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * an exception and report failure.
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check some invariants */
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz));
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.classJavaLangClass != NULL);
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->obj.clazz == gDvm.classJavaLangClass);
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != gDvm.classJavaLangObject) {
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->super == NULL) {
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Non-Object has no superclass (gDvm.classJavaLangObject=%p)\n",
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gDvm.classJavaLangObject);
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->vtableCount,
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->virtualMethodCount);
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtableCount >= clazz->virtualMethodCount);
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Normally class objects are initialized before we instantiate them,
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but we can't do that with java.lang.Class (chicken, meet egg).  We
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * do it explicitly here.
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The verifier could call here to find Class while verifying Class,
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * so we need to check for CLASS_VERIFYING as well as !initialized.
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == gDvm.classJavaLangClass && !dvmIsClassInitialized(clazz) &&
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        !(clazz->status == CLASS_VERIFYING))
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ explicitly initializing %s\n", clazz->descriptor);
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInitClass(clazz);
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_PROFILER
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (profilerNotified)
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepEnd();
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != NULL || dvmCheckException(self));
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * encoded data pointer in addition to the other arguments.
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData, Object* classLoader)
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* newClass = NULL;
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make sure the aren't any "bonus" flags set, since we use them for
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * runtime state.
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Invalid file flags in class %s: %04x\n",
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            descriptor, pClassDef->accessFlags);
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage for the class object on the GC heap, so that other
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects can have references to it.  We bypass the usual mechanism
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (allocObject), because we don't have all the bits and pieces yet.
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that we assume that java.lang.Class does not override
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finalize().
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newClass == NULL)
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Until the class is loaded and linked, use a placeholder
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * obj->clazz value as a hint to the GC.  We don't want
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the GC trying to scan the object while it's full of Idx
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * values.  Also, the real java.lang.Class may not exist
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * yet.
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DVM_OBJECT_INIT(&newClass->obj, gDvm.unlinkedJavaLangClass);
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetClassSerialNumber(newClass);
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->descriptor = descriptor;
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(newClass->descriptorAlloc == NULL);
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->accessFlags = pClassDef->accessFlags;
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->classLoader = classLoader;
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->pDvmDex = pDvmDex;
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->primitiveType = PRIM_NOT;
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff the superclass index into the object pointer field.  The linker
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pulls it out and replaces it with a resolved ClassObject pointer.
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm doing it this way (rather than having a dedicated superclassIdx
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field) to save a few bytes of overhead per class.
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this is safe.
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sizeof(u4) == sizeof(ClassObject*));
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->super = (ClassObject*) pClassDef->superclassIdx;
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff class reference indices into the pointer fields.
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The elements of newClass->interfaces are not traversed or freed by
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmFreeClassInnards, so this is GC-safe.
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexTypeList* pInterfacesList;
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pInterfacesList != NULL) {
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaceCount = pInterfacesList->size;
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                newClass->interfaceCount * sizeof(ClassObject*));
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < newClass->interfaceCount; i++) {
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->interfaces);
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* load field definitions */
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: consider over-allocating the class object and appending the
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * static field info onto the end.  It's fixed-size and known at alloc
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * time.  This would save a couple of native heap allocations, but it
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * would also make heap compaction more difficult because we pass Field
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pointers around internally.
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->staticFieldsSize != 0) {
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* static fields stay on system heap; field data isn't "write once" */
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->staticFieldsSize;
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->sfieldCount = count;
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->sfields =
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (StaticField*) calloc(count, sizeof(StaticField));
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->instanceFieldsSize != 0) {
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->instanceFieldsSize;
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifieldCount = count;
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(InstField));
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->ifields);
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* load method definitions */
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->directMethodsSize != 0) {
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->directMethodsSize;
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethodCount = count;
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->directMethods);
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->virtualMethodsSize != 0) {
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->virtualMethodsSize;
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethodCount = count;
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->status = CLASS_LOADED;
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* caller must call dvmReleaseTrackedAlloc */
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newClass;
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to load the indicated class from the specified DEX file.
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is effectively loadClass()+defineClass() for a DexClassDef.  The
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loading was largely done when we crunched through the DEX.
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL on failure.  If we locate the class but encounter an error
1770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while processing it, an appropriate exception is thrown.
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, Object* classLoader)
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result;
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassDataHeader header;
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData;
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((pDvmDex != NULL) && (pClassDef != NULL));
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass) {
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: loading '%s'...\n",
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexGetClassDescriptor(pDexFile, pClassDef));
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEncodedData = dexGetClassData(pDexFile, pClassDef);
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pEncodedData != NULL) {
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexReadClassDataHeader(&pEncodedData, &header);
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Provide an all-zeroes header for the rest of the loading.
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memset(&header, 0, sizeof(header));
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            classLoader);
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass && (result != NULL)) {
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result->descriptor, pDvmDex, classLoader);
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a ClassObject that was allocated on the system heap.
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ClassObject itself is allocated on the GC heap, so we leave it for
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the garbage collector.
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this may be called with a partially-constructed object.
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: there is no particular ordering imposed, so don't go poking at
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclasses.
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeClassInnards(ClassObject* clazz)
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void *tp;
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->obj.clazz == gDvm.classJavaLangClass ||
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project           clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Guarantee that dvmFreeClassInnards can be called on a given
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class multiple times by clearing things out as we free them.
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't make any attempt at real atomicity here; higher
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * levels need to make sure that no two threads can free the
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * same ClassObject at the same time.
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: maybe just make it so the GC will never free the
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * innards of an already-freed class.
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_FREE(p) \
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(tp); \
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_LINEAR_FREE(p) \
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearFree(clazz->classLoader, tp); \
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* arrays just point at Object's vtable; don't free vtable in this case.
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmIsArrayClass() checks clazz->descriptor, so we have to do this check
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * before freeing the name.
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtableCount = -1;
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsArrayClass(clazz)) {
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = NULL;
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL_AND_LINEAR_FREE(clazz->vtable);
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->descriptor = NULL;
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_FREE(clazz->descriptorAlloc);
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->directMethods != NULL) {
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *directMethods = clazz->directMethods;
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int directMethodCount = clazz->directMethodCount;
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethods = NULL;
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethodCount = -1;
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < directMethodCount; i++) {
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&directMethods[i]);
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, directMethods);
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->virtualMethods != NULL) {
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *virtualMethods = clazz->virtualMethods;
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int virtualMethodCount = clazz->virtualMethodCount;
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount = -1;
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = NULL;
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < virtualMethodCount; i++) {
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&virtualMethods[i]);
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, virtualMethods);
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->initiatingLoaderCount = -1;
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_FREE(clazz->initiatingLoaders);
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->interfaceCount = -1;
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->interfaces);
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = -1;
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->iftable);
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = -1;
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifviPool);
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->sfieldCount = -1;
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_FREE(clazz->sfields);
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldCount = -1;
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifields);
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_FREE
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_LINEAR_FREE
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a Method that was allocated on the system heap.
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeMethodInnards(Method* meth)
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->exceptions);
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->lines);
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->locals);
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: call dvmFreeRegisterMap() if meth->registerMap was allocated
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //       on the system heap
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(meth);
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clone a Method, making new copies of anything that will be freed up
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by freeMethodInnards().
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void cloneMethod(Method* dst, const Method* src)
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(dst, src, sizeof(Method));
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* for current usage, these are never set, so no need to implement copy */
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dst->exceptions == NULL);
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dst->lines == NULL);
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dst->locals == NULL);
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pull the interesting pieces out of a DexMethod.
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The DEX file isn't going anywhere, so we don't need to make copies of
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the code area.
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth)
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexMethodId* pMethodId;
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pDexCode;
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->shorty = dexProtoGetShorty(&meth->prototype);
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->accessFlags = pDexMethod->accessFlags;
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->clazz = clazz;
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->jniArgInfo = 0;
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexCode = dexGetCode(pDexFile, pDexMethod);
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexCode != NULL) {
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* integer constants, copy over for faster access */
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = pDexCode->registersSize;
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insSize = pDexCode->insSize;
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->outsSize = pDexCode->outsSize;
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* pointer to code area */
1979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insns = pDexCode->insns;
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't have a DexCode block, but we still want to know how
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * much space is needed for the arguments (so we don't have to
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * compute it later).  We also take this opportunity to compute
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * JNI argument info.
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We do this for abstract methods as well, because we want to
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be able to substitute our exception-throwing "stub" in.
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int argsSize = dvmComputeMethodArgsSize(meth);
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsStaticMethod(meth))
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            argsSize++;
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = meth->insSize = argsSize;
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->outsSize == 0);
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->insns == NULL);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = dvmResolveNativeMethod;
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jniArgInfo (32-bit int) layout:
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   S - if set, do things the hard way (scan the signature)
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   R - return-type enumeration
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   H - target-specific hints
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This info is used at invocation time by dvmPlatformInvoke.  In most
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * having to fully parse the signature.
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The return-type bits are always set, even if target-specific hint bits
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are unavailable.
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeJniArgInfo(const DexProto* proto)
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = dexProtoGetShorty(proto);
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int returnType, padFlags, jniArgInfo;
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char sigByte;
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackOffset, padMask;
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hints;
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The first shorty character is the return type. */
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (*(sig++)) {
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_VOID;
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_FLOAT;
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_DOUBLE;
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S8;
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S4;
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hints = dvmPlatformInvokeHints(proto);
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (hints & DALVIK_JNI_NO_ARG_INFO) {
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= hints;
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return jniArgInfo;
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about a static field.
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This also "prepares" static fields by initializing them
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to their "standard default values".
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadSFieldFromDex(ClassObject* clazz,
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexSField, StaticField* sfield)
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.clazz = clazz;
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.accessFlags = pDexSField->accessFlags;
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Static object field values are set to "standard default values"
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (null or 0) until the class is initialized.  We delay loading
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant values from the class until that time.
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //sfield->value.j = 0;
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sfield->value.j == 0LL);     // cleared earlier with calloc
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
2087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.gets = sfield->field.puts = 0;
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about an instance field.
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadIFieldFromDex(ClassObject* clazz,
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexIField, InstField* ifield)
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.clazz = clazz;
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.accessFlags = pDexIField->accessFlags;
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(ifield->byteOffset == 0);    // cleared earlier with calloc
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->byteOffset = -1;    // make it obvious if we fail to set later
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.gets = ifield->field.puts = 0;
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache java.lang.ref.Reference fields and methods.
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool precacheReferenceOffsets(ClassObject *clazz)
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method *meth;
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* We trick the GC object scanner by not counting
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.ref.Reference.referent as an object
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field.  It will get explicitly scanned as part
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the reference-walking process.
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Find the object field named "referent" and put it
2130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just after the list of object reference fields.
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldRefCount; i++) {
2134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
2135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pField->field.name, "referent") == 0) {
2136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int targetIndex;
2137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Swap this field with the last object field.
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targetIndex = clazz->ifieldRefCount - 1;
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i != targetIndex) {
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField *swapField = &clazz->ifields[targetIndex];
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField tmpField;
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int tmpByteOffset;
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* It's not currently strictly necessary
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * for the fields to be in byteOffset order,
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * but it's more predictable that way.
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpByteOffset = swapField->byteOffset;
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                swapField->byteOffset = pField->byteOffset;
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pField->byteOffset = tmpByteOffset;
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpField = *swapField;
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *swapField = *pField;
2156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *pField = tmpField;
2157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* One fewer object field (wink wink).
2160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount--;
2162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i--;        /* don't trip "didn't find it" test if field was last */
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i == clazz->ifieldRefCount) {
2168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Cache pretty much everything about Reference so that
2173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we don't need to call interpreted code when clearing/enqueueing
2174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * references.  This is fragile, so we'll be paranoid.
2175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangRefReference = clazz;
2177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_referent =
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "referent", "Ljava/lang/Object;");
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_referent >= 0);
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_queue =
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "queue", "Ljava/lang/ref/ReferenceQueue;");
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_queue >= 0);
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_queueNext =
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "queueNext", "Ljava/lang/ref/Reference;");
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_vmData =
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "vmData", "I");
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_vmData >= 0);
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if FANCY_REFERENCE_SUBCLASS
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindVirtualMethodByDescriptor(clazz, "clear", "()V");
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(meth != NULL);
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.voffJavaLangRefReference_clear = meth->methodIndex;
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindVirtualMethodByDescriptor(clazz, "enqueue", "()Z");
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(meth != NULL);
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.voffJavaLangRefReference_enqueue = meth->methodIndex;
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* enqueueInternal() is private and thus a direct method. */
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(meth != NULL);
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.methJavaLangRefReference_enqueueInternal = meth;
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Link (prepare and resolve).  Verification is deferred until later.
2219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This converts symbolic references into pointers.  It's independent of
2221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the source file format.
2222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "classesResolved" is false, we assume that superclassIdx and
2224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interfaces[] are holding class reference indices rather than pointers.
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class references will be resolved during link.  (This is done when
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loading from DEX to avoid having to create additional storage to pass
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the indices around.)
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" with an exception pending on failure.
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLinkClass(ClassObject* clazz, bool classesResolved)
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 superclassIdx = 0;
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool okay = false;
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool resolve_okay;
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numInterfacesResolved = 0;
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "Resolve" the class.
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * At this point, clazz's reference fields contain Dex
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * file indices instead of direct object references.
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to translate those indices into real references,
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * while making sure that the GC doesn't sweep any of
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the referenced objects.
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The GC will avoid scanning this object as long as
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * clazz->obj.clazz is gDvm.unlinkedJavaLangClass.
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Once clazz is ready, we'll replace clazz->obj.clazz
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with gDvm.classJavaLangClass to let the GC know
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to look at it.
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* It's important that we take care of java.lang.Class
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * first.  If we were to do this after looking up the
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass (below), Class wouldn't be ready when
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.Object needed it.
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that we don't set clazz->obj.clazz yet.
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangClass == NULL) {
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->classLoader == NULL &&
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0)
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.classJavaLangClass = clazz;
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.classJavaLangClass =
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmFindSystemClassNoInit("Ljava/lang/Class;");
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.classJavaLangClass == NULL) {
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* should have thrown one */
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(dvmThreadSelf()));
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.classJavaLangClass != NULL);
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Resolve all Dex indices so we can hand the ClassObject
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * over to the GC.  If we fail at any point, we need to remove
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * any tracked references to avoid leaking memory.
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * All classes have a direct superclass, except for java/lang/Object.
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!classesResolved) {
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superclassIdx = (u4) clazz->super;          /* unpack temp store */
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->super = NULL;
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!classesResolved);
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (superclassIdx != kDexNoIndex) {
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* TODO: is this invariant true for all java/lang/Objects,
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * regardless of the class loader?  For now, assume it is.
2300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/ClassFormatError;",
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "java.lang.Object has a superclass");
2303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't finalize objects whose classes use the
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * default (empty) Object.finalize().
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!classesResolved) {
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (superclassIdx == kDexNoIndex) {
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/LinkageError;",
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "no superclass defined");
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->super = dvmResolveClass(clazz, superclassIdx, false);
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz->super == NULL) {
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(dvmThreadSelf()));
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (gDvm.optimizing) {
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* happens with "external" libs */
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGV("Unable to resolve superclass of %s (%d)\n",
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor, superclassIdx);
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Unable to resolve superclass of %s (%d)\n",
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor, superclassIdx);
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify */
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsFinalClass(clazz->super)) {
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' is final '%s'\n",
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass is final");
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (dvmIsInterfaceClass(clazz->super)) {
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' is interface '%s'\n",
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass is an interface");
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' (%s) is not accessible\n",
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalAccessError;",
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass not accessible");
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't let the GC reclaim the superclass.
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: shouldn't be needed; remove when things stabilize
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc((Object *)clazz->super, NULL);
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Inherit finalizability from the superclass.  If this
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class also overrides finalize(), its CLASS_ISFINALIZABLE
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * bit will already be set.
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* See if this class descends from java.lang.Reference
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and set the class flags appropriately.
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 superRefFlags;
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We've already determined the reference type of this
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * inheritance chain.  Inherit reference-ness from the superclass.
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE);
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, superRefFlags);
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (clazz->classLoader == NULL &&
2380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->super->classLoader == NULL &&
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                strcmp(clazz->super->descriptor,
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/Reference;") == 0)
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 refFlags;
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This class extends Reference, which means it should
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * be one of the magic Soft/Weak/PhantomReference classes.
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            refFlags = CLASS_ISREFERENCE;
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (strcmp(clazz->descriptor,
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/SoftReference;") == 0)
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Only CLASS_ISREFERENCE is set for soft references.
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/WeakReference;") == 0)
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISWEAKREFERENCE;
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/PhantomReference;") == 0)
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISPHANTOMREFERENCE;
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* No-one else is allowed to inherit directly
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * from Reference.
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//xxx is this the right exception?  better than an assertion.
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/LinkageError;",
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "illegal inheritance from Reference");
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* The class should not have any reference bits set yet.
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(GET_CLASS_FLAG_GROUP(clazz,
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE) == 0);
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, refFlags);
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!classesResolved && clazz->interfaceCount > 0) {
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Resolve the interfaces implemented directly by this class.  We
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * stuffed the class index into the interface pointer slot.
2428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->interfaceCount; i++) {
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 interfaceIdx;
2432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            interfaceIdx = (u4) clazz->interfaces[i];   /* unpack temp store */
2434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(interfaceIdx != kDexNoIndex);
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->interfaces[i] = dvmResolveClass(clazz, interfaceIdx, false);
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz->interfaces[i] == NULL) {
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(dvmThreadSelf()));
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const char* classDescriptor;
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                classDescriptor = dexStringByTypeIdx(pDexFile, interfaceIdx);
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (gDvm.optimizing) {
2446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* happens with "external" libs */
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGV("Failed resolving %s interface %d '%s'\n",
2448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor, interfaceIdx, classDescriptor);
2449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
2450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGI("Failed resolving %s interface %d '%s'\n",
2451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor, interfaceIdx, classDescriptor);
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail_during_resolve;
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* are we allowed to implement this interface? */
2457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Interface '%s' is not accessible to '%s'\n",
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->interfaces[i]->descriptor, clazz->descriptor);
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/IllegalAccessError;",
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "interface not accessible");
2463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail_during_resolve;
2464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Don't let the GC reclaim the interface class.
2467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: shouldn't be needed; remove when things stabilize
2468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAddTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            numInterfacesResolved++;
2471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  found interface '%s'\n",
2473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->interfaces[i]->descriptor);
2474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The ClassObject is now in a GC-able state.  We let the GC
2480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * realize this by punching in the real class type, which is
2481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * always java.lang.Class.
2482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * After this line, clazz will be fair game for the GC.
2484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Every field that the GC will look at must now be valid:
2485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * - clazz->super
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * - class->classLoader
2487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * - clazz->sfields
2488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * - clazz->interfaces
2489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->obj.clazz = gDvm.classJavaLangClass;
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
2493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_during_resolve:
2494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resolve_okay = false;
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resolve_okay = true;
2497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Now that the GC can scan the ClassObject, we can let
2501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * go of the explicit references we were holding onto.
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Either that or we failed, in which case we need to
2504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * release the references so we don't leak memory.
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object *)clazz->super, NULL);
2508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < numInterfacesResolved; i++) {
2510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!resolve_okay) {
2514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGW("resolve_okay is false\n");
2515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate vtable.
2520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz)) {
2522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no vtable; just set the method indices */
2523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in interface '%s'\n", count,
2527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++)
2534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!createVtable(clazz)) {
2539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("failed creating vtable\n");
2540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate interface method tables.  Can alter the vtable.
2546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!createIftable(clazz))
2548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Insert special-purpose "stub" method implementations.
2552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!insertMethodStubs(clazz))
2554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute instance field offsets and, hence, the size of the object.
2558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!computeFieldOffsets(clazz))
2560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Cache fields and methods from java/lang/ref/Reference and
2564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java/lang/Class.  This has to happen after computeFieldOffsets().
2565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->classLoader == NULL) {
2567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!precacheReferenceOffsets(clazz)) {
2569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("failed pre-caching Reference offsets\n");
2570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/InternalError;", NULL);
2571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (clazz == gDvm.classJavaLangClass) {
2574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Ljava/security/ProtectionDomain;");
2576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.offJavaLangClass_pd <= 0) {
2577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("ERROR: unable to find 'pd' field in Class\n");
2578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();     /* we're not going to get much farther */
2579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //goto bail;
2580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Done!
2586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
2590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_RESOLVED;
2591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    okay = true;
2592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
2593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We send CLASS_PREPARE events to the debugger from here.  The
2597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * definition of "preparation" is creating the static fields for a
2598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class and initializing them to the standard default values, but not
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * executing any code (that comes later, during "initialization").
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We did the static prep in loadSFieldFromDex() while loading the class.
2602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been prepared and resolved but possibly not yet verified
2604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at this point.
2605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.debuggerActive) {
2607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDbgPostClassPrepare(clazz);
2608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!okay) {
2612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
2613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckException(dvmThreadSelf())) {
2614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return okay;
2618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the virtual method table.
2622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the table is a copy of the table from our superclass,
2624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with our local methods overriding theirs.  The bottom part of the table
2625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has any new methods we defined.
2626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createVtable(ClassObject* clazz)
2628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int maxCount;
2631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->super->descriptor);
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* the virtual methods we define, plus the superclass vtable size */
2639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    maxCount = clazz->virtualMethodCount;
2640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        maxCount += clazz->super->vtableCount;
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* TODO: is this invariant true for all java/lang/Objects,
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * regardless of the class loader?  For now, assume it is.
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Over-allocate the table, then realloc it down if necessary.  So
2652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * long as we don't allocate anything in between we won't cause
2653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fragmentation, and reducing the size should be unlikely to cause
2654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a buffer copy.
2655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * maxCount);
2659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->vtable == NULL)
2660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int actualCount;
2664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->vtable, clazz->super->vtable,
2666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualCount = clazz->super->vtableCount;
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * See if any of our virtual methods override the superclass.
2671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* localMeth = &clazz->virtualMethods[i];
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int si;
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (si = 0; si < clazz->super->vtableCount; si++) {
2677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Method* superMeth = clazz->vtable[si];
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* verify */
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmIsFinalMethod(superMeth)) {
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        LOGW("Method %s.%s overrides final %s.%s\n",
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            localMeth->clazz->descriptor, localMeth->name,
2685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            superMeth->clazz->descriptor, superMeth->name);
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
2687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtable[si] = localMeth;
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    localMeth->methodIndex = (u2) si;
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //LOGV("+++   override %s.%s (slot %d)\n",
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    clazz->descriptor, localMeth->name, si);
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (si == clazz->super->vtableCount) {
2697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* not an override, add to end */
2698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[actualCount] = localMeth;
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                localMeth->methodIndex = (u2) actualCount;
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                actualCount++;
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //LOGV("+++   add method %s.%s\n",
2703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //    clazz->descriptor, localMeth->name);
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount != (u2) actualCount) {
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(actualCount <= maxCount);
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount < maxCount) {
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->vtable != NULL);
2717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(*(clazz->vtable)) * actualCount);
2720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz->vtable == NULL) {
2721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("vtable realloc failed\n");
2722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("+++  reduced vtable from %d to %d\n",
2725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    maxCount, actualCount);
2726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = actualCount;
2730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* java/lang/Object case */
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in base class '%s'\n", count,
2735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
2740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[i] = &clazz->virtualMethods[i];
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = clazz->virtualMethodCount;
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
2747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and populate "iftable".
2756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The set of interfaces we support is the combination of the interfaces
2758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we implement directly and those implemented by our superclass.  Each
2759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interface can have one or more "superinterfaces", which we must also
2760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * support.  For speed we flatten the tree out.
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to speed this up when there are lots of interfaces
2763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by merge-sorting the class pointers and binary-searching when removing
2764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * duplicates.  We could also drop the duplicate removal -- it's only
2765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there to reduce the memory footprint.
2766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
2770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createIftable(ClassObject* clazz)
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIftable = false;
2775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapVtable = false;
2776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIfvipool = false;
2777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ifCount, superIfCount, idx;
2778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = clazz->super->iftableCount;
2782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = 0;
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifCount = superIfCount;
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifCount += clazz->interfaceCount;
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->interfaceCount; i++)
2788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ifCount += clazz->interfaces[i]->iftableCount;
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ifCount == 0) {
2794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftableCount == 0);
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftable == NULL);
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
2797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a table with enough space for all interfaces, and copy the
2802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass' table in.
2803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(InterfaceEntry) * ifCount);
2806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIftable = true;
2807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (superIfCount != 0) {
2809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->iftable, clazz->super->iftable,
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(InterfaceEntry) * superIfCount);
2811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a flattened interface hierarchy of our immediate interfaces.
2815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = superIfCount;
2817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->interfaceCount; i++) {
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* interf;
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int j;
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        interf = clazz->interfaces[i];
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(interf != NULL);
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure this is still an interface class */
2826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsInterfaceClass(interf)) {
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Class '%s' implements non-interface '%s'\n",
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, interf->descriptor);
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowExceptionWithClassMessage(
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Ljava/lang/IncompatibleClassChangeError;",
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
2832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entry for this interface */
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[idx++].clazz = interf;
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entries for the interface's superinterfaces */
2839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = 0; j < interf->iftableCount; j++) {
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx == ifCount);
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
2847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Remove anything redundant from our recent additions.  Note we have
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to traverse the recent adds when looking for duplicates, because
2850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it's possible the recent additions are self-redundant.  This
2851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * reduces the memory footprint of classes with lots of inherited
2852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * interfaces.
2853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (I don't know if this will cause problems later on when we're trying
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to find a static field.  It looks like the proper search order is
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (1) current class, (2) interfaces implemented by current class,
2857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (3) repeat with superclass.  A field implemented by an interface
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and by a superclass might come out wrong if the superclass also
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * implements the interface.  The javac compiler will reject the
2860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * situation as ambiguous, so the concern is somewhat artificial.)
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because it wants to return just the interfaces declared to be
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * implemented directly by the class.  I'm excluding this code for now.
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = superIfCount; i < ifCount; i++) {
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = 0; j < ifCount; j++) {
2870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i == j)
2871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("INTF: redundant interface %s in %s\n",
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->iftable[i].clazz->descriptor,
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor);
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (i != ifCount-1)
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        memmove(&clazz->iftable[i], &clazz->iftable[i+1],
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (ifCount - i -1) * sizeof(InterfaceEntry));
2880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ifCount--;
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i--;        // adjust for i++ above
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } // if (false)
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = ifCount;
2890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we're an interface, we don't need the vtable pointers, so
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're done.  If this class doesn't implement an interface that our
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass doesn't have, then we again have nothing to do.
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //dvmDumpClass(clazz, kDumpClassFullDetail);
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
2899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * When we're handling invokeinterface, we probably have an object
2904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * whose type is an interface class rather than a concrete class.  We
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * need to convert the method reference into a vtable index.  So, for
2906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * every entry in "iftable", we create a list of vtable indices.
2907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Because our vtable encompasses the superclass vtable, we can use
2909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the vtable indices from our superclass for all of the interfaces
2910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that weren't directly implemented by us.
2911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Each entry in "iftable" has a pointer to the start of its set of
2913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * vtable offsets.  The iftable entries in the superclass point to
2914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * storage allocated in the superclass, and the iftable entries added
2915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for this class point to storage allocated in this class.  "iftable"
2916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is flat for fast access in a class and all of its subclasses, but
2917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "ifviPool" is only created for the topmost implementor.
2918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int poolSize = 0;
2920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = superIfCount; i < ifCount; i++) {
2921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note it's valid for an interface to have no methods (e.g.
2923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * java/io/Serializable).
2924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: pool: %d from %s\n",
2926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->virtualMethodCount,
2927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->descriptor);
2928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolSize += clazz->iftable[i].clazz->virtualMethodCount;
2929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (poolSize == 0) {
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: didn't find any new interfaces with methods\n");
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = poolSize;
2938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
2939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        poolSize * sizeof(int*));
2940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIfvipool = true;
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Fill in the vtable offsets for the interfaces that weren't part of
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our superclass.
2945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int poolOffset = 0;
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method** mirandaList = NULL;
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int mirandaCount = 0, mirandaAlloc = 0;
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = superIfCount; i < ifCount; i++) {
2951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* interface;
2952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int methIdx;
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
2955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        interface = clazz->iftable[i].clazz;
2956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolOffset += interface->virtualMethodCount;    // end here
2957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * For each method listed in the interface's method list, find the
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matching method in our class's method list.  We want to favor the
2961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass over the superclass, which just requires walking
2962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * back from the end of the vtable.  (This only matters if the
2963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass defines a private method and this class redefines
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it -- otherwise it would use the same vtable slot.  In Dalvik
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * those don't end up in the virtual method table, so it shouldn't
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matter which direction we go.  We walk it backward anyway.)
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Suppose we have the following arrangement:
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public interface MyInterface
2971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface();
2972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public abstract class MirandaAbstract implements MirandaInterface
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     //public abstract boolean inInterface(); // not declared!
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public class MirandClass extends MirandaAbstract
2976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface() { stuff }
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The javac compiler happily compiles MirandaAbstract even though
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it doesn't declare all methods from its interface.  When we try
2981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to set up a vtable for MirandaAbstract, we find that we don't
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have an slot for inInterface.  To prevent this, we synthesize
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * abstract method declarations in MirandaAbstract.
2984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We have to expand vtable and update some things that point at it,
2986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so we accumulate the method list and do it all at once below.
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* imeth = &interface->virtualMethods[methIdx];
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            IF_LOGVV() {
2993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
2994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("INTF:  matching '%s' '%s'\n", imeth->name, desc);
2995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(desc);
2996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = clazz->vtableCount-1; j >= 0; j--) {
2999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    == 0)
3001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("INTF:   matched at %d\n", j);
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsPublicMethod(clazz->vtable[j])) {
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        LOGW("Implementation of %s.%s is not public\n",
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            clazz->descriptor, clazz->vtable[j]->name);
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmThrowException("Ljava/lang/IllegalAccessError;",
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "interface implementation not public");
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->iftable[i].methodIndexArray[methIdx] = j;
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (j < 0) {
3015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                IF_LOGV() {
3016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    char* desc =
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dexProtoCopyMethodDescriptor(&imeth->prototype);
3018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            imeth->name, desc, clazz->descriptor);
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(desc);
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //return false;
3024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mirandaCount == mirandaAlloc) {
3026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaAlloc += 8;
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (mirandaList == NULL) {
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        mirandaList = dvmLinearAlloc(clazz->classLoader,
3029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        mirandaAlloc * sizeof(Method*));
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        mirandaList = dvmLinearRealloc(clazz->classLoader,
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList, mirandaAlloc * sizeof(Method*));
3034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(mirandaList != NULL);    // mem failed + we leaked
3036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * These may be redundant (e.g. method with same name and
3040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * signature declared in two interfaces implemented by the
3041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * same abstract class).  We can squeeze the duplicates
3042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * out here.
3043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int mir;
3045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (mir = 0; mir < mirandaCount; mir++) {
3046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmCompareMethodNamesAndProtos(
3047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            mirandaList[mir], imeth) == 0)
3048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    {
3049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        IF_LOGVV() {
3050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            char* desc = dexProtoCopyMethodDescriptor(
3051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    &imeth->prototype);
3052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList[mir]->clazz->descriptor,
3054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->clazz->descriptor,
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->name, desc);
3056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            free(desc);
3057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* point the iftable at a phantom slot index */
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->iftable[i].methodIndexArray[methIdx] =
3064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtableCount + mir;
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("MIRANDA: %s points at slot %d\n",
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    imeth->name, clazz->vtableCount + mir);
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if non-duplicate among Mirandas, add to Miranda list */
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mir == mirandaCount) {
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //LOGV("MIRANDA: holding '%s' in slot %d\n",
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    imeth->name, mir);
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaList[mirandaCount++] = imeth;
3073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mirandaCount != 0) {
3079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* newVirtualMethods;
3080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
3081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int oldMethodCount, oldVtableCount;
3082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < mirandaCount; i++) {
3084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("MIRANDA %d: %s.%s\n", i,
3085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We found methods in one or more interfaces for which we do not
3090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have vtable entries.  We have to expand our virtualMethods
3091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * table (which might be empty) to hold some new entries.
3092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->virtualMethods == NULL) {
3094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods,
3100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newVirtualMethods != clazz->virtualMethods) {
3103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Table was moved in memory.  We have to run through the
3105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * vtable and fix the pointers.  The vtable entries might be
3106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * pointing at superclasses, so we flip it around: run through
3107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * all locally-defined virtual methods, and fix their entries
3108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in the vtable.  (This would get really messy if sub-classes
3109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * had already been loaded.)
3110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * hold the virtual methods declared by this class.  The
3113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method's methodIndex is the vtable index, and is the same
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * for all sub-classes (and all super classes in which it is
3115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * defined).  We're messing with these because the Miranda
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * stuff makes it look like the class actually has an abstract
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method declaration in it.
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("MIRANDA fixing vtable pointers\n");
3120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* meth = newVirtualMethods;
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[meth->methodIndex] = meth;
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldMethodCount = clazz->virtualMethodCount;
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = newVirtualMethods;
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount += mirandaCount;
3130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We also have to expand the vtable.
3135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtable != NULL);
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable,
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->vtable == NULL) {
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zapVtable = true;
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldVtableCount = clazz->vtableCount;
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount += mirandaCount;
3148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Now we need to create the fake methods.  We clone the abstract
3151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method definition from the interface and then replace a few
3152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * things.
3153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = clazz->virtualMethods + oldMethodCount;
3155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < mirandaCount; i++, meth++) {
3156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cloneMethod(meth, mirandaList[i]);
3158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->clazz = clazz;
3159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_MIRANDA;
3160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->methodIndex = (u2) (oldVtableCount + i);
3161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* point the new vtable entry at the new method */
3164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[oldVtableCount + i] = meth;
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, mirandaList);
3169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO?
3174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sort the interfaces by number of declared methods.  All we really
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want is to get the interfaces with zero methods at the end of the
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * list, so that when we walk through the list during invoke-interface
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we don't examine interfaces that can't possibly be useful.
3178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The set will usually be small, so a simple insertion sort works.
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to be careful not to change the order of two interfaces
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that define the same method.  (Not a problem if we only move the
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * zero-method interfaces to the end.)
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * PROBLEM:
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we do this, we will no longer be able to identify super vs.
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * current class interfaces by comparing clazz->super->iftableCount.  This
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * breaks anything that only wants to find interfaces declared directly
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmDbgOutputAllInterfaces, etc).  Need to provide a workaround.
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can sort just the interfaces implemented directly by this class,
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but that doesn't seem like it would provide much of an advantage.  I'm
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not sure this is worthwhile.
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This has been made largely obsolete by the interface cache mechanism.)
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpClass(clazz);
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIftable)
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapVtable)
3207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIfvipool)
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
3211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Provide "stub" implementations for methods without them.
3216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently we provide an implementation for all abstract methods that
3218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throws an AbstractMethodError exception.  This allows us to avoid an
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * explicit check for abstract methods in every virtual call.
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: for Miranda methods, the method declaration is a clone of what
3222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * was found in the interface class.  That copy may already have had the
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * function pointer filled in, so don't be surprised if it's not NULL.
3224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which is nonsensical.  Need to make sure that this doesn't escape the
3227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM.  We can either mask it out in reflection calls, or copy "native"
3228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the high 16 bits of accessFlags and check that internally.
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool insertMethodStubs(ClassObject* clazz)
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth;
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = clazz->virtualMethods;
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(meth)) {
3240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->insns == NULL);
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->nativeFunc == NULL ||
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_NATIVE;
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Swap two instance fields.
3256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void swapField(InstField* pOne, InstField* pTwo)
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    InstField swap;
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("  --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    swap = *pOne;
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pOne = *pTwo;
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pTwo = swap;
3265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assign instance fields to u4 slots.
3269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top portion of the instance field area is occupied by the superclass
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields, the bottom by the fields for this class.
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "long" and "double" fields occupy two adjacent slots.  On some
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * arrange fields (or introduce padding) to ensure this.  We assume the
3276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can just ensure that the offset is "even".  To avoid wasting space,
3278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we want to move non-reference 32-bit fields into gaps rather than
3279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creating pad words.
3280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the worst case we will waste 4 bytes, but because objects are
3282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (assuming this is the most-derived class).
3284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pad words are not represented in the field table, so the field table
3286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * itself does not change size.
3287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The number of field slots determines the size of the object, so we
3289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set that here too.
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This function feels a little more complicated than I'd like, but it
3292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has the property of moving the smallest possible set of fields, which
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should reduce the time required to load a class.
3294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will break.
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool computeFieldOffsets(ClassObject* clazz)
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int fieldOffset;
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
3302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset = clazz->super->objectSize;
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
3308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset = offsetof(DataObject, instanceData);
3309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start by moving all reference fields to the front.
3319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldRefCount = 0;
3321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a reference field; see if any reference fields
3328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* refField = &clazz->ifields[j--];
3333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = refField->field.signature[0];
3334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == '[' || rc == 'L') {
3336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a reference field that follows at least one
3337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-reference field.  Swap it with the current field.
3338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "refField" points to the non-ref field.)
3340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, refField);
3342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Fix the signature.
3344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->ifieldRefCount++;
3348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a reference field.
3355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount++;
3357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we've hit the end of the reference fields, break.
3361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L')
3363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
3366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
3367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Now we want to pack all of the double-wide fields together.  If we're
3372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not aligned, though, we want to shuffle one 32-bit field into place.
3373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we can't find one, we'll have to pad it.
3374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  +++ not aligned\n");
3377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'J' && c != 'D') {
3382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The field that comes next is 32-bit, so just advance past it.
3384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(c != '[' && c != 'L');
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pField->byteOffset = fieldOffset;
3387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i++;
3389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("  --- offset2 '%s'=%d\n",
3390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pField->field.name, pField->byteOffset);
3391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Next field is 64-bit, so search for a 32-bit field we can
3394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swap into it.
3395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool found = false;
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            j = clazz->ifieldCount - 1;
3398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* singleField = &clazz->ifields[j--];
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = singleField->field.signature[0];
3401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc != 'J' && rc != 'D') {
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, singleField);
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //c = rc;
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("  +++ swapped '%s' for alignment\n",
3406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pField->field.name);
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pField->byteOffset = fieldOffset;
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fieldOffset += sizeof(u4);
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("  --- offset3 '%s'=%d\n",
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pField->field.name, pField->byteOffset);
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
3412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i++;
3413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!found) {
3417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("  +++ inserting pad field in '%s'\n", clazz->descriptor);
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fieldOffset += sizeof(u4);
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Alignment is good, shuffle any double-wide fields forward, and
3425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finish assigning field offsets to all fields.
3426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for ( ; i < clazz->ifieldCount; i++) {
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'D' && c != 'J') {
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a double-wide field; see if any double fields
3435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* doubleField = &clazz->ifields[j--];
3440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = doubleField->field.signature[0];
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == 'D' || rc == 'J') {
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a double-wide field that follows at least one
3444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-double field.  Swap it with the current field.
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "doubleField" points to the non-double field.)
3447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, doubleField);
3449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a double-wide field, leave it be.
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'J' || c == 'D')
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure that all reference fields appear before
3470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * non-reference fields, and all double-wide fields are aligned.
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = 0;  // seen non-ref
3473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'D' || c == 'J') {
3478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((pField->byteOffset & 0x07) == 0);
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!j) {
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(i == clazz->ifieldRefCount);
3484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                j = 1;
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (j) {
3487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!j) {
3491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->ifieldRefCount == clazz->ifieldCount);
3492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We map a C struct directly on top of java/lang/Class objects.  Make
3497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sure we left enough room for the instance fields.
3498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->objectSize = fieldOffset;
3503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throw the VM-spec-mandated error when an exception is thrown during
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class initialization.
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The safest way to do this is to call the ExceptionInInitializerError
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constructor that takes a Throwable.
3514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [Do we want to wrap it if the original is an Error rather than
3516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an Exception?]
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwClinitError(void)
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
3521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
3522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* eiie;
3523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = dvmGetException(self);
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddTrackedAlloc(exception, self);
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmClearException(self);
3527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Always resolves to same thing -- no race condition.
3531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangExceptionInInitializerError =
3533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClass(
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Ljava/lang/ExceptionInInitializerError;");
3535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
3538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.methJavaLangExceptionInInitializerError_init =
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "<init>", "(Ljava/lang/Throwable;)V");
3543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
3546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ALLOC_DEFAULT);
3551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (eiie == NULL)
3552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
3553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Construct the new object, and replace the exception with it.
3556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
3558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        eiie, &unused, exception);
3560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetException(self, eiie);
3561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(eiie, NULL);
3562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
3563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return;
3564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:       /* restore original exception */
3566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetException(self, exception);
3567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
3568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return;
3569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class failed to initialize on a previous attempt, so we want to throw
3573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
3574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * failed in verification, in which case v2 5.4.1 says we need to re-throw
3575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the previous error.
3576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwEarlierClassFailure(ClassObject* clazz)
3578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->verifyErrorClass);
3581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->verifyErrorClass == NULL) {
3583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor);
3585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor);
3588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize any static fields whose values are stored in
3593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the DEX file.  This must be done during class initialization.
3594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void initSFields(ClassObject* clazz)
3596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile;
3599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef;
3600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexEncodedArray* pValueList;
3601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EncodedArrayIterator iterator;
3602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount == 0) {
3605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->pDvmDex == NULL) {
3608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* generated class; any static fields should already be set up */
3609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = clazz->pDvmDex->pDexFile;
3613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pClassDef != NULL);
3616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pValueList == NULL) {
3619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Iterate over the initial values array, setting the corresponding
3626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * static field for each array element.
3627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AnnotationValue value;
3631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StaticField* sfield = &clazz->sfields[i];
3633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* descriptor = sfield->field.signature;
3634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool needRelease = false;
3635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! parsed) {
3637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: Eventually verification should attempt to ensure
3639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that this can't happen at least due to a data integrity
3640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * problem.
3641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Static initializer parse failed for %s at index %d",
3643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->descriptor, i);
3644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Verify that the value we got was of a valid type. */
3648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (descriptor[0]) {
3650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'B': parsed = (value.type == kDexAnnotationByte);    break;
3652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'C': parsed = (value.type == kDexAnnotationChar);    break;
3653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'S': parsed = (value.type == kDexAnnotationShort);   break;
3654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'I': parsed = (value.type == kDexAnnotationInt);     break;
3655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J': parsed = (value.type == kDexAnnotationLong);    break;
3656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': parsed = (value.type == kDexAnnotationFloat);   break;
3657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': parsed = (value.type == kDexAnnotationDouble);  break;
3658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '[': parsed = (value.type == kDexAnnotationNull);    break;
3659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'L': {
3660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                switch (value.type) {
3661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationNull: {
3662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /* No need for further tests. */
3663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationString: {
3666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/String;") == 0);
3668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        needRelease = true;
3669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationType: {
3672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        needRelease = true;
3675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    default: {
3678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed = false;
3679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
3685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                parsed = false;
3686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parsed) {
3691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * All's well, so store the value. Note: This always
3693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * stores the full width of a JValue, even though most of
3694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the time only the first word is needed.
3695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sfield->value = value.value;
3697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (needRelease) {
3698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmReleaseTrackedAlloc(value.value.l, self);
3699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Something up above had a problem. TODO: See comment
3703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * above the switch about verfication.
3704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bogus static initialization: value type %d in field type "
3706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "%s for %s at index %d",
3707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value.type, descriptor, clazz->descriptor, i);
3708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "descriptor" yields the same class object in the
3716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of clazz1 and clazz2.
3717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must hold gDvm.loadedClasses.
3719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if they match.
3721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool compareDescriptorClasses(const char* descriptor,
3723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
3724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result1;
3726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result2;
3727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do the first lookup by name.
3730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can skip a second lookup by name if the second class loader is
3735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the initiating loader list of the class object we retrieved.
3736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This means that somebody already did a lookup of this class through
3737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the second loader, and it resolved to the same class.)  If it's not
3738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * there, we may simply not have had an opportunity to add it yet, so
3739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we do the full lookup.
3740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The initiating loader test should catch the majority of cases
3742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (in particular, the zillions of references to String/Object).
3743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For this to work, the superclass/interface should be the first
3747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * argument, so that way if it's from the bootstrap loader this test
3748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will work.  (The bootstrap loader, by definition, never shows up
3749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * as the initiating loader of a class defined by some other loader.)
3750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
3752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
3754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isInit) {
3756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
3760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result1 == NULL || result2 == NULL) {
3768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(dvmThreadSelf());
3769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result1 == result2) {
3770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Neither class loader could find this class.  Apparently it
3772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * doesn't exist.
3773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can either throw some sort of exception now, or just
3775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * assume that it'll fail later when something actually tries
3776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to use the class.  For strict handling we should throw now,
3777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * because a "tricky" class loader could start returning
3778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * something later, and a pair of "tricky" loaders could set
3779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * us up for confusion.
3780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * I'm not sure if we're allowed to complain about nonexistent
3782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes in method signatures during class init, so for now
3783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * this will just return "true" and let nature take its course.
3784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
3786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* only one was found, so clearly they're not the same */
3788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
3789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result1 == result2;
3793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For every component in the method descriptor, resolve the class in the
3797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of the two classes and compare the results.
3798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For best results, the "superclass" class should be first.
3800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the classes match, "false" otherwise.
3802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkMethodDescriptorClasses(const Method* meth,
3804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
3805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexParameterIterator iterator;
3807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
3808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* walk through the list of parameters */
3810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexParameterIteratorInit(&iterator, &meth->prototype);
3811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
3812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor = dexParameterIteratorNextDescriptor(&iterator);
3813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor == NULL)
3815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor[0] == 'L' || descriptor[0] == '[') {
3818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* non-primitive type */
3819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
3820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
3821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check the return type */
3825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexProtoGetReturnType(&meth->prototype);
3826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (descriptor[0] == 'L' || descriptor[0] == '[') {
3827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
3828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
3829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validate the descriptors in the superclass and interfaces.
3835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * What we need to do is ensure that the classes named in the method
3837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptors in our ancestors and ourselves resolve to the same class
3838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects.  The only time this matters is when the classes come from
3839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * different class loaders, and the resolver might come up with a
3840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * different answer for the same class name depending on context.
3841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to check to see if an interface's methods match with
3843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * its superinterface's methods, because you can't instantiate an
3844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interface and do something inappropriate with it.  If interface I1
3845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * extends I2 and is implemented by C, and I1 and I2 are in separate
3846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loaders and have conflicting views of other classes, we will
3847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * catch the conflict when we process C.  Anything that implements I1 is
3848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * doomed to failure, but we don't need to catch that while processing I1.
3849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
3851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool validateSuperDescriptors(const ClassObject* clazz)
3853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz))
3857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
3858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start with the superclass-declared methods.
3861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL &&
3863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->classLoader != clazz->super->classLoader)
3864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
3865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Walk through every method declared in the superclass, and
3867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * compare resolved descriptor components.  We pull the Method
3868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * structs out of the vtable.  It doesn't matter whether we get
3869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the struct from the parent or child, since we just need the
3870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * UTF-8 descriptor, which must match.
3871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to do this even for the stuff inherited from Object,
3873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because it's possible that the new class loader has redefined
3874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a basic class like String.
3875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;
3877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("Checking %s %p vs %s %p\n",
3879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->classLoader,
3880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->super->descriptor, clazz->super->classLoader);
3881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
3882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth = clazz->vtable[i];
3883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!checkMethodDescriptorClasses(meth, clazz->super, clazz)) {
3884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
3885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->name, clazz->descriptor, clazz->classLoader,
3886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->super->descriptor, clazz->super->classLoader);
3887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/LinkageError;",
3888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Classes resolve differently in superclass");
3889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
3890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Check all interfaces we implement.
3896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->iftableCount; i++) {
3898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const InterfaceEntry* iftable = &clazz->iftable[i];
3899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->classLoader != iftable->clazz->classLoader) {
3901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ClassObject* iface = iftable->clazz;
3902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
3903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = 0; j < iface->virtualMethodCount; j++) {
3905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const Method* meth;
3906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int vtableIndex;
3907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vtableIndex = iftable->methodIndexArray[j];
3909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth = clazz->vtable[vtableIndex];
3910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!checkMethodDescriptorClasses(meth, iface, clazz)) {
3912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Method mismatch: %s in %s (cl=%p) and "
3913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "iface %s (cl=%p)\n",
3914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->name, clazz->descriptor, clazz->classLoader,
3915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        iface->descriptor, iface->classLoader);
3916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmThrowException("Ljava/lang/LinkageError;",
3917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Classes resolve differently in interface");
3918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
3919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the class is being initialized by us (which means that
3929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calling dvmInitClass will return immediately after fiddling with locks).
3930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There isn't a race here, because either clazz->initThreadId won't match
3932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * us, or it will and it was set in the same thread.
3933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsClassInitializing(const ClassObject* clazz)
3935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (clazz->status == CLASS_INITIALIZING &&
3937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId == dvmThreadSelf()->threadId);
3938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If a class has not been initialized, do so by executing the code in
3942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <clinit>.  The sequence is described in the VM spec v2 2.17.5.
3943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible for multiple threads to arrive here simultaneously, so
3945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to lock the class while we check stuff.  We know that no
3946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code has access to the class yet, so we can use the class's
3947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor lock.
3948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We will often be called recursively, e.g. when the <clinit> code resolves
3950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of its fields, the field resolution will try to initialize the class.
3951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can get very interesting if a class has a static field initialized
3953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to a new instance of itself.  <clinit> will end up calling <init> on
3954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the members it is initializing, which is fine unless it uses the contents
3955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of static fields to initialize instance fields.  This will leave the
3956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * static-referenced objects in a partially initialized state.  This is
3957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reasonably rare and can sometimes be cured with proper field ordering.
3958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, returns "false" with an exception raised.
3960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -----
3962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible to cause a deadlock by having a situation like this:
3964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class A { static { sleep(10000); new B(); } }
3965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class B { static { sleep(10000); new A(); } }
3966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new A(); } }.start();
3967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new B(); } }.start();
3968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This appears to be expected under the spec.
3969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The interesting question is what to do if somebody calls Thread.interrupt()
3971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on one of the deadlocked threads.  According to the VM spec, they're both
3972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sitting in "wait".  Should the interrupt code quietly raise the
3973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "interrupted" flag, or should the "wait" return immediately with an
3974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception raised?
3975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This gets a little murky.  The VM spec says we call "wait", and the
3977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec for Thread.interrupt says Object.wait is interruptible.  So it
3978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * seems that, if we get unlucky and interrupt class initialization, we
3979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are expected to throw (which gets converted to ExceptionInInitializerError
3980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * since InterruptedException is checked).
3981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are a couple of problems here.  First, all threads are expected to
3983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * present a consistent view of class initialization, so we can't have it
3984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fail in one thread and succeed in another.  Second, once a class fails
3985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to initialize, it must *always* fail.  This means that a stray interrupt()
3986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call could render a class unusable for the lifetime of the VM.
3987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In most cases -- the deadlock example above being a counter-example --
3989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interrupting thread can't tell whether the target thread handled
3990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization itself or had to wait while another thread did the
3991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work.  Refusing to interrupt class initialization is, in most cases,
3992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not something that a program can reliably detect.
3993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On the assumption that interrupting class initialization is highly
3995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * undesirable in most circumstances, and that failing to do so does not
3996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deviate from the spec in a meaningful way, we don't allow class init
3997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to be interrupted by Thread.interrupt().
3998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitClass(ClassObject* clazz)
4000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool initializedByUs = false;
4003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
4006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* method;
4007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockObject(self, (Object*) clazz);
4009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the class hasn't been verified yet, do so now.
4013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status < CLASS_VERIFIED) {
4015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we're in an "erroneous" state, throw an exception and bail.
4017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
4020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_RESOLVED);
4024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             clazz->classLoader == NULL))
4029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("+++ not verifying class %s (cl=%p)\n",
4031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->classLoader);
4032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto noverify;
4033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!gDvm.optimizing)
4036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("+++ late verify on %s\n", clazz->descriptor);
4037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're not supposed to optimize an unverified class, but during
4040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * development this mode was useful.  We can't verify an optimized
4041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class because the optimization process discards information.
4042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Class '%s' was optimized without verification; "
4045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 "not verifying now\n",
4046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("  ('rm /data/dalvik-cache/*' and restart to fix this)");
4048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto verify_failed;
4049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFYING;
4052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmVerifyClass(clazz, VERIFY_DEFAULT)) {
4053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverify_failed:
4054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->verifyErrorClass = dvmGetException(self)->clazz;
4057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
4062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnoverify:
4064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_INITIALIZED)
4066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (clazz->status == CLASS_INITIALIZING) {
4069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* we caught somebody else in the act; was it us? */
4070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->initThreadId == self->threadId) {
4071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGV("HEY: found a recursive <clinit>\n");
4072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
4076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("GLITCH: exception pending at start of class init\n");
4077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
4078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Wait for the other thread to finish initialization.  We pass
4082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "false" for the "interruptShouldThrow" arg so it doesn't throw
4083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception on interrupt.
4084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * When we wake up, repeat the test for init-in-progress.  If there's
4089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception pending (only possible if "interruptShouldThrow"
4090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * was set), bail out.
4091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
4093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Class init of '%s' failing with wait() exception\n",
4094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: this is bogus, because it means the two threads have a
4097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different idea of the class status.  We need to flag the
4098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class as bad and ensure that the initializer thread respects
4099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * our notice.  If we get lucky and wake up after the class has
4100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * finished initialization but before being woken, we have to
4101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swallow the exception, perhaps raising thread->interrupted
4102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to preserve semantics.
4103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
4104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Since we're not currently allowing interrupts, this should
4105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never happen and we don't need to fix this.
4106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
4108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwClinitError();
4109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_INITIALIZING) {
4113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Waiting again for class init\n");
4114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
4115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_INITIALIZED ||
4117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               clazz->status == CLASS_ERROR);
4118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The caller wants an exception, but it was thrown in a
4121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different thread.  Synthesize one here.
4122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "(<clinit> failed, see exception in other thread)");
4125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* see if we failed previously */
4130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_ERROR) {
4131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // might be wise to unlock before throwing; depends on which class
4132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // it is that we have locked
4133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
4134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwEarlierClassFailure(clazz);
4135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
4136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're ready to go, and have exclusive access to the class.
4140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Before we start initialization, we need to do one extra bit of
4142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * validation: make sure that the methods declared here match up
4143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with our superclass and interfaces.  We know that the UTF-8
4144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * descriptors match, but classes from different class loaders can
4145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have the same name.
4146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We do this now, rather than at load/link time, for the same reason
4148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we defer verification.
4149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's unfortunate that we need to do this at all, but we risk
4151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mixing reference types with identical names (see Dalvik test 068).
4152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateSuperDescriptors(clazz)) {
4154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
4155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Let's initialize this thing.
4161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We unlock the object so that other threads can politely sleep on
4163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our mutex with Object.wait(), instead of hanging or spinning trying
4164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to grab our mutex.
4165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->status < CLASS_INITIALIZING);
4167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // We started initializing.
4170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    logClassLoad('+', clazz);
4171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initializedByUs = true;
4172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->status = CLASS_INITIALIZING;
4175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->initThreadId = self->threadId;
4176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init our superclass */
4179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsInterfaceClass(clazz));
4181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz->super)) {
4182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
4183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* wake up anybody who started waiting while we were unlocked */
4185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
4186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_notify;
4187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize any static fields whose values are
4191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stored in the Dex file.  This should include all of the
4192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * simple "final static" fields, which are required to
4193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * More-complicated final static fields should be set
4195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the beginning of <clinit>;  all we can do is trust
4196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the compiler did the right thing.
4197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initSFields(clazz);
4199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Execute any static initialization code.
4201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method == NULL) {
4204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
4208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, method, NULL, &unused);
4209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
4212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We've had an exception thrown during static initialization.  We
4214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * need to throw an ExceptionInInitializerError, but we want to
4215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * tuck the original exception into the "cause" field.
4216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Exception %s thrown during %s.<clinit>\n",
4218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwClinitError();
4220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGW("+++ replaced\n");
4221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* success! */
4226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_INITIALIZED;
4228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Initialized class: %s\n", clazz->descriptor);
4229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_notify:
4232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Notify anybody waiting on the object.
4234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmObjectNotifyAll(self, (Object*) clazz);
4236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
4238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initializedByUs) {
4241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // We finished initializing.
4242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('-', clazz);
4243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (clazz->status != CLASS_ERROR);
4249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Replace method->nativeFunc and method->insns with new values.  This is
4253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * performed on resolution of a native method.
4254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetNativeFunc(const Method* method, DalvikBridgeFunc func,
4256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns)
4257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* just open up both; easier that way */
4261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ((Method*)method)->nativeFunc = func;
4265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ((Method*)method)->insns = insns;
4266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a RegisterMap to a Method.  This is done when we verify the class
4273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and compute the register maps at class initialization time, which means
4274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that "pMap" is on the heap and should be freed when the Method is
4275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * discarded.
4276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method->registerMap != NULL) {
4282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: registerMap already set for %s.%s\n",
4283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
4284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* keep going */
4285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* might be virtual or direct */
4288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->registerMap = pMap;
4292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmHashForeach callback.  A nonzero return value causes foreach to
4299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bail out.
4300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findClassCallback(void* vclazz, void* arg)
4302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = vclazz;
4304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor = (const char*) arg;
4305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, descriptor) == 0)
4307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (int) clazz;
4308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a loaded class by descriptor. Returns the first one found.
4313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because there can be more than one if class loaders are involved,
4314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this is not an especially good API. (Currently only used by the
4315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * debugger and "checking" JNI.)
4316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" should have the form "Ljava/lang/Class;" or
4318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class name.
4320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindLoadedClass(const char* descriptor)
4322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
4324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (void*) descriptor);
4328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) result;
4331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Retrieve the system (a/k/a application) class loader.
4335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetSystemClassLoader(void)
4337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
4339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* getSysMeth;
4340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader;
4341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
4344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
4345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        "()Ljava/lang/ClassLoader;");
4348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getSysMeth == NULL)
4349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
4350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
4352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    loader = (Object*)result.l;
4354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return loader;
4355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a dvmHashForeach callback.
4360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpClass(void* vclazz, void* varg)
4362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
4364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* super;
4365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int flags = (int) varg;
4366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* desc;
4367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
4370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("dumpClass: ignoring request to dump null class\n");
4371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & kDumpClassFullDetail) == 0) {
4375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showInit = (flags & kDumpClassInitialized) != 0;
4376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showLoader = (flags & kDumpClassClassLoader) != 0;
4377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* initStr;
4378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (showInit && showLoader)
4382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showInit)
4384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %s\n", clazz->descriptor, initStr);
4385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showLoader)
4386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
4388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s\n", clazz->descriptor);
4389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* clazz->super briefly holds the superclass index during class prep */
4394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = clazz->super;
4396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
4397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = NULL;
4398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmIsInterfaceClass(clazz) ? "interface" : "class",
4401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("  objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super != NULL ? (int) super->objectSize : -1);
4404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("  access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->accessFlags & JAVA_FLAGS_MASK);
4406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (super != NULL)
4407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsArrayClass(clazz)) {
4409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  dimensions=%d elementClass=%s\n",
4410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->arrayDim, clazz->elementClass->descriptor);
4411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->iftableCount > 0) {
4413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  interfaces (%d):\n", clazz->iftableCount);
4414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->iftableCount; i++) {
4415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InterfaceEntry* ent = &clazz->iftable[i];
4416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
4417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %s (cl=%p)\n",
4419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                i, ent->clazz->descriptor, ent->clazz->classLoader);
4420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* enable when needed */
4422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (false && ent->methodIndexArray != NULL) {
4423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGI("      %2d: %d %s %s\n",
4425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        j, ent->methodIndexArray[j],
4426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        ent->clazz->virtualMethods[j].name,
4427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable[ent->methodIndexArray[j]]->name);
4428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
4432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  vtable (%d entries, %d in super):\n", clazz->vtableCount,
4433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super != NULL ? super->vtableCount : 0);
4434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->vtableCount; i++) {
4435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %s%2d: %p %20s %s\n",
4437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[i]->name, desc);
4440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  direct methods (%d entries):\n", clazz->directMethodCount);
4443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->directMethodCount; i++) {
4444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->directMethods[i].prototype);
4446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->directMethods[i].name,
4447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  interface methods (%d):\n", clazz->virtualMethodCount);
4452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
4453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->virtualMethods[i].prototype);
4455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %2d %20s %s\n", i,
4456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->virtualMethods[i].methodIndex,
4457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods[i].name,
4458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount > 0) {
4463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  static fields (%d entries):\n", clazz->sfieldCount);
4464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->sfieldCount; i++) {
4465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->sfields[i].field.signature);
4467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->ifieldCount > 0) {
4470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  instance fields (%d entries):\n", clazz->ifieldCount);
4471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->ifieldCount; i++) {
4472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->ifields[i].field.signature);
4474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a single class.
4481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpClass(const ClassObject* clazz, int flags)
4485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClass((void*) clazz, (void*) flags);
4487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of all classes.
4491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpAllClasses(int flags)
4493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of loaded classes
4501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetNumLoadedClasses()
4503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count;
4505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = dvmHashTableNumEntries(gDvm.loadedClasses);
4507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
4509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write some statistics to the log file.
4513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpLoaderStats(const char* msg)
4515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef COUNT_PRECISE_METHODS
4521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("GC precise methods: %d\n",
4522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPointerSetGetCount(gDvm.preciseMethods));
4523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
4527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the field access counts for all fields in this method.
4529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpAccessCounts(void* vclazz, void* varg)
4531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
4533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
4536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Field* field = &clazz->ifields[i].field;
4537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->gets != 0)
4539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("GI %d %s.%s\n", field->gets,
4540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->puts != 0)
4542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("PI %d %s.%s\n", field->puts,
4543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->sfieldCount; i++) {
4546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Field* field = &clazz->sfields[i].field;
4547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->gets != 0)
4549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("GS %d %s.%s\n", field->gets,
4550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->puts != 0)
4552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("PS %d %s.%s\n", field->puts,
4553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the field access counts for all loaded classes.
4561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpFieldAccessCounts(void)
4563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Mark all classes associated with the built-in loader.
4573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int markClassObject(void *clazz, void *arg)
4575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(arg);
4577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMarkObjectNonNull((Object *)clazz);
4579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The garbage collector calls this to mark the class objects for all
4584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loaded classes.
4585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmGcScanRootClassLoader()
4587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* dvmClassStartup() may not have been called before the first GC.
4589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.loadedClasses != NULL) {
4591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.loadedClasses);
4592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.loadedClasses);
4594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Method Prototypes and Descriptors
4601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(). The
4606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name is considered the "major" order and the prototype the "minor"
4607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * order. The prototypes are compared as if by dvmCompareMethodProtos().
4608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndProtos(const Method* method1,
4610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodProtos(method1, method2);
4619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(), ignoring
4623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the return value. The name is considered the "major" order and the
4624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * prototype the "minor" order. The prototypes are compared as if by
4625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmCompareMethodArgProtos().
4626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodParameterProtos(method1, method2);
4637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, prototype) pair with the (name, prototype) of
4641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameProtoAndMethod(const char* name,
4646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexProto* proto, const Method* method)
4647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dexProtoCompare(proto, &method->prototype);
4655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, method descriptor) pair with the (name, prototype) of
4659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameDescriptorAndMethod(const char* name,
4664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor, const Method* method)
4665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareDescriptorAndMethodProto(descriptor, method);
4673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4674