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"
26fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden#include "analysis/Optimize.h"
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stddef.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/stat.h>
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <pthread.h>
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <cutils/process_name.h>
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/types.h>
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on Linking and Verification
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe basic way to retrieve a class is to load it, make sure its superclass
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand interfaces are available, prepare its fields, and return it.  This gets
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta little more complicated when multiple threads can be trying to retrieve
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe class simultaneously, requiring that we use the class object's monitor
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectto keep things orderly.
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe linking (preparing, resolving) of a class can cause us to recursively
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectload superclasses and interfaces.  Barring circular references (e.g. two
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses that are superclasses of each other), this will complete without
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe loader attempting to access the partially-linked class.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWith verification, the situation is different.  If we try to verify
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectevery class as we load it, we quickly run into trouble.  Even the lowly
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.Object requires CloneNotSupportedException; follow the list
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectof referenced classes and you can head down quite a trail.  The trail
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecteventually leads back to Object, which is officially not fully-formed yet.
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe VM spec (specifically, v2 5.4.1) notes that classes pulled in during
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification do not need to be prepared or verified.  This means that we
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectare allowed to have loaded but unverified classes.  It further notes that
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe class must be verified before it is initialized, which allows us to
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdefer verification for all classes until class init.  You can't execute
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcode or access fields in an uninitialized class, so this is safe.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIt also allows a more peaceful coexistence between verified and
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectunverifiable code.  If class A refers to B, and B has a method that
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectrefers to a bogus class C, should we allow class A to be verified?
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf A only exercises parts of B that don't use class C, then there is
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnothing wrong with running code in A.  We can fully verify both A and B,
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand allow execution to continue until B causes initialization of C.  The
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectVerifyError is thrown close to the point of use.
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis gets a little weird with java.lang.Class, which is the only class
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthat can be instantiated before it is initialized.  We have to force
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectinitialization right after the class is created, because by definition we
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthave instances of it on the heap, and somebody might get a class object and
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstart making virtual calls on it.  We can end up going recursive during
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification of java.lang.Class, but we avoid that by checking to see if
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification is already in progress before we try to initialize it.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on class loaders and interaction with optimization / verification
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIn what follows, "pre-verification" and "optimization" are the steps
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectperformed by the dexopt command, which attempts to verify and optimize
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses as part of unpacking jar files and storing the DEX data in the
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectdalvik-cache directory.  These steps are performed by loading the DEX
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfiles directly, without any assistance from ClassLoader instances.
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWhen we pre-verify and optimize a class in a DEX file, we make some
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectassumptions about where the class loader will go to look for classes.
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIf we can't guarantee those assumptions, e.g. because a class ("AppClass")
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectreferences something not defined in the bootstrap jars or the AppClass jar,
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwe can't pre-verify or optimize the class.
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe VM doesn't define the behavior of user-defined class loaders.
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor example, suppose application class AppClass, loaded by UserLoader,
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecthas a method that creates a java.lang.String.  The first time
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAppClass.stringyMethod tries to do something with java.lang.String, it
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectasks UserLoader to find it.  UserLoader is expected to defer to its parent
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectloader, but isn't required to.  UserLoader might provide a replacement
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfor String.
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe can run into trouble if we pre-verify AppClass with the assumption that
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.String will come from core.jar, and don't verify this assumption
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectat runtime.  There are two places that an alternate implementation of
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjava.lang.String can come from: the AppClass jar, or from some other jar
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthat UserLoader knows about.  (Someday UserLoader will be able to generate
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsome bytecode and call DefineClass, but not yet.)
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectTo handle the first situation, the pre-verifier will explicitly check for
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconflicts between the class being optimized/verified and the bootstrap
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses.  If an app jar contains a class that has the same package and
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclass name as a class in a bootstrap jar, the verification resolver refuses
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectto find either, which will block pre-verification and optimization on
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclasses that reference ambiguity.  The VM will postpone verification of
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe app class until first load.
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFor the second situation, we need to ensure that all references from a
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpre-verified class are satisified by the class' jar or earlier bootstrap
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectjars.  In concrete terms: when resolving a reference to NewClass,
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwhich was caused by a reference in class AppClass, we check to see if
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectAppClass was pre-verified.  If so, we require that NewClass comes out
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectof either the AppClass jar or one of the jars in the bootstrap path.
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(We may not control the class loaders, but we do manage the DEX files.
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe can verify that it's either (loader==null && dexFile==a_boot_dex)
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projector (loader==UserLoader && dexFile==AppClass.dexFile).  Classes from
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDefineClass can't be pre-verified, so this doesn't apply.)
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis should ensure that you can't "fake out" the pre-verifier by creating
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta user-defined class loader that replaces system classes.  It should
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectalso ensure that you can write such a loader and have it work in the
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexpected fashion; all you lose is some performance due to "just-in-time
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverification" and the lack of DEX optimizations.
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThere is a "back door" of sorts in the class resolution check, due to
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe fact that the "class ref" entries are shared between the bytecode
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand meta-data references (e.g. annotations and exception handler lists).
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe class references in annotations have no bearing on class verification,
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectso when a class does an annotation query that causes a class reference
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectindex to be resolved, we don't want to fail just because the calling
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectclass was pre-verified and the resolved class is in some random DEX file.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe successful resolution adds the class to the "resolved classes" table,
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectso when optimized bytecode references it we don't repeat the resolve-time
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcheck.  We can avoid this by not updating the "resolved classes" table
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwhen the class reference doesn't come out of something that has been
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchecked by the verifier, but that has a nonzero performance impact.
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSince the ultimate goal of this test is to catch an unusual situation
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(user-defined class loaders redefining core classes), the added caution
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmay not be worth the performance hit.
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1557ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden/*
1567ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden * Class serial numbers start at this value.  We use a nonzero initial
1577ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden * value so they stand out in binary dumps (e.g. hprof output).
1587ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden */
1592c98747b403970ef4b3352e271633f93935b9825Barry Hayes#define INITIAL_CLASS_SERIAL_NUMBER 0x50000000
1607ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden
1617ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden/*
1627ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden * Constant used to size an auxillary class object data structure.
1637ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden * For optimum memory use this should be equal to or slightly larger than
1647ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden * the number of classes loaded when the zygote finishes initializing.
1657ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden */
1667ccb7a6a563396e4b64069dd4e57977d1b5b6180Andy McFadden#define ZYGOTE_CLASS_CUTOFF 2304
1672c98747b403970ef4b3352e271633f93935b9825Barry Hayes
168c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes#define CLASS_SFIELD_SLOTS 1
169c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeCpeArray(ClassPathEntry* cpe);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassFromLoaderNoInit(
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor, Object* loader);
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassNoInit(const char* descriptor, Object* loader,\
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex);
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex(DvmDex* pDvmDex,
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, Object* loader);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,\
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth);
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeJniArgInfo(const DexProto* proto);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadSFieldFromDex(ClassObject* clazz,
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexSField, StaticField* sfield);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadIFieldFromDex(ClassObject* clazz,
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexIField, InstField* field);
1866daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic bool precacheReferenceOffsets(ClassObject* clazz);
1876daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic void computeRefOffsets(ClassObject* clazz);
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeMethodInnards(Method* meth);
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createVtable(ClassObject* clazz);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createIftable(ClassObject* clazz);
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool insertMethodStubs(ClassObject* clazz);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool computeFieldOffsets(ClassObject* clazz);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwEarlierClassFailure(ClassObject* clazz);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Logs information about a class loading with given timestamp.
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: In the case where we fail in dvmLinkClass() and log the class as closing (type='<'),
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it would probably be better to use a new type code to indicate the failure.  This change would
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * require a matching change in the parser and analysis code in frameworks/base/tools/preload.
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logClassLoadWithTime(char type, ClassObject* clazz, u8 time) {
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pid_t ppid = getppid();
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pid_t pid = getpid();
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int tid = (unsigned int) pthread_self();
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2081663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block    ALOG(LOG_INFO, "PRELOAD", "%c%d:%d:%d:%s:%d:%s:%lld", type, ppid, pid, tid,
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        get_process_name(), (int) clazz->classLoader, clazz->descriptor,
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        time);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Logs information about a class loading.
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logClassLoad(char type, ClassObject* clazz) {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    logClassLoadWithTime(type, clazz, dvmGetThreadCpuTimeNsec());
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Some LinearAlloc unit tests.
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void linearAllocTests()
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* fiddle;
227fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    int test = 1;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    switch (test) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 0:
231fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fiddle = (char*)dvmLinearAlloc(NULL, 3200-28);
232fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmLinearReadOnly(NULL, (char*)fiddle);
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 1:
235fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fiddle = (char*)dvmLinearAlloc(NULL, 3200-24);
236fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmLinearReadOnly(NULL, (char*)fiddle);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 2:
239fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fiddle = (char*)dvmLinearAlloc(NULL, 3200-20);
240fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmLinearReadOnly(NULL, (char*)fiddle);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 3:
243fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fiddle = (char*)dvmLinearAlloc(NULL, 3200-16);
244fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmLinearReadOnly(NULL, (char*)fiddle);
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 4:
247fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        fiddle = (char*)dvmLinearAlloc(NULL, 3200-12);
248fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmLinearReadOnly(NULL, (char*)fiddle);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
251fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 896);
252fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    dvmLinearReadOnly(NULL, (char*)fiddle);
253fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 20);      // watch addr of this alloc
254fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    dvmLinearReadOnly(NULL, (char*)fiddle);
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
256fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 1);
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'q';
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
259fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 4096);
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'x';
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[4095] = 'y';
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearFree(NULL, fiddle);
264fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 0);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
266fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearRealloc(NULL, fiddle, 12);
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[11] = 'z';
268fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    dvmLinearReadOnly(NULL, (char*)fiddle);
269fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearRealloc(NULL, fiddle, 5);
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(NULL, fiddle);
271fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 17001);
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[0] = 'x';
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fiddle[17000] = 'y';
274fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    dvmLinearReadOnly(NULL, (char*)fiddle);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    char* str = (char*)dvmLinearStrdup(NULL, "This is a test!");
2774308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("GOT: '%s'", str);
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2797605a84a9a0a1764c1fb290d9c93e8114eaf620aAndy McFadden    /* try to check the bounds; allocator may round allocation size up */
280fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    fiddle = (char*)dvmLinearAlloc(NULL, 12);
2814308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("Should be 1: %d", dvmLinearAllocContains(fiddle, 12));
2824308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("Should be 0: %d", dvmLinearAllocContains(fiddle, 13));
2834308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("Should be 0: %d", dvmLinearAllocContains(fiddle - 128*1024, 1));
2847605a84a9a0a1764c1fb290d9c93e8114eaf620aAndy McFadden
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearAllocDump(NULL);
286fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    dvmLinearFree(NULL, (char*)str);
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayesstatic size_t classObjectSize(size_t sfieldCount)
290c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes{
291dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    size_t offset = OFFSETOF_MEMBER(ClassObject, sfields);
292dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    return offset + sizeof(StaticField) * sfieldCount;
293c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes}
294c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
295c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayessize_t dvmClassObjectSize(const ClassObject *clazz)
296c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes{
297c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz != NULL);
298c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    return classObjectSize(clazz->sfieldCount);
299c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes}
300c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
301a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein/* (documented in header) */
302a9c49df6714b3a37b7a7d0522932e622be2b35acDan BornsteinClassObject* dvmFindPrimitiveClass(char type)
303a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein{
304a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    PrimitiveType primitiveType = dexGetPrimitiveTypeFromDescriptorChar(type);
305a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
306a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    switch (primitiveType) {
307a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_VOID:    return gDvm.typeVoid;
308a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_BOOLEAN: return gDvm.typeBoolean;
309a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_BYTE:    return gDvm.typeByte;
310a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_SHORT:   return gDvm.typeShort;
311a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_CHAR:    return gDvm.typeChar;
312a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_INT:     return gDvm.typeInt;
313a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_LONG:    return gDvm.typeLong;
314a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_FLOAT:   return gDvm.typeFloat;
315a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        case PRIM_DOUBLE:  return gDvm.typeDouble;
316a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        default: {
317e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Unknown primitive type '%c'", type);
318a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein            return NULL;
319a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        }
320a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    }
321a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein}
322a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
323a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein/*
324a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein * Synthesize a primitive class.
325a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein *
326a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein * Just creates the class and returns it (does not add it to the class list).
327a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein */
328a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornsteinstatic bool createPrimitiveType(PrimitiveType primitiveType, ClassObject** pClass)
329a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein{
330a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    /*
331a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     * Fill out a few fields in the ClassObject.
332a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     *
333a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     * Note that primitive classes do not sub-class the class Object.
334a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     * This matters for "instanceof" checks. Also, we assume that the
335a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     * primitive class does not override finalize().
336a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     */
337a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
338a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    const char* descriptor = dexGetPrimitiveTypeDescriptor(primitiveType);
339a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    assert(descriptor != NULL);
340a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
34152e2626eb3bf620c53459a90d912733de2ce0369Carl Shapiro    ClassObject* newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_NON_MOVING);
342a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    if (newClass == NULL) {
343a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        return false;
344a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    }
345a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
346dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    DVM_OBJECT_INIT(newClass, gDvm.classJavaLangClass);
347a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmSetClassSerialNumber(newClass);
348c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    SET_CLASS_FLAG(newClass, ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT);
349a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    newClass->primitiveType = primitiveType;
350a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    newClass->descriptorAlloc = NULL;
351a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    newClass->descriptor = descriptor;
352a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    newClass->super = NULL;
353a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    newClass->status = CLASS_INITIALIZED;
354a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
355a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    /* don't need to set newClass->objectSize */
356a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
35760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("Constructed class for primitive type '%s'", newClass->descriptor);
358a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
359a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    *pClass = newClass;
360a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmReleaseTrackedAlloc((Object*) newClass, NULL);
361a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
362a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    return true;
363a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein}
364a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
365a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein/*
366318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein * Create the initial class instances. These consist of the class
367318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein * Class and all of the classes representing primitive types.
368a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein */
3691e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic bool createInitialClasses() {
370318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    /*
371318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * Initialize the class Class. This has to be done specially, particularly
372318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * because it is an instance of itself.
373318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     */
374318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    ClassObject* clazz = (ClassObject*)
37552e2626eb3bf620c53459a90d912733de2ce0369Carl Shapiro        dvmMalloc(classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_NON_MOVING);
376318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    if (clazz == NULL) {
377318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein        return false;
378318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    }
379dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    DVM_OBJECT_INIT(clazz, clazz);
380c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    SET_CLASS_FLAG(clazz, ACC_PUBLIC | ACC_FINAL | CLASS_ISCLASS);
381318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    clazz->descriptor = "Ljava/lang/Class;";
382318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    gDvm.classJavaLangClass = clazz;
38360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("Constructed the class Class.");
384a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
385318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    /*
386318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * Initialize the classes representing primitive types. These are
387318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * instances of the class Class, but other than that they're fairly
388318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * different from regular classes.
389318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     */
390318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    bool ok = true;
391a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_VOID,    &gDvm.typeVoid);
392a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_BOOLEAN, &gDvm.typeBoolean);
393a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_BYTE,    &gDvm.typeByte);
394a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_SHORT,   &gDvm.typeShort);
395a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_CHAR,    &gDvm.typeChar);
396a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_INT,     &gDvm.typeInt);
397a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_LONG,    &gDvm.typeLong);
398a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_FLOAT,   &gDvm.typeFloat);
399a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    ok &= createPrimitiveType(PRIM_DOUBLE,  &gDvm.typeDouble);
400a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
401a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    return ok;
402a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein}
403a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the bootstrap class loader.
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call this after the bootclasspath string has been finalized.
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4091e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmClassStartup()
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make this a requirement -- don't currently support dirs in path */
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(gDvm.bootClassPathStr, ".") == 0) {
413c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("ERROR: must specify non-'.' bootclasspath");
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses =
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.pBootLoaderAlloc = dvmLinearAllocCreate(NULL);
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.pBootLoaderAlloc == NULL)
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        linearAllocTests();
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(0);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Class serial number.  We start with a high value to make it distinct
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in binary dumps (e.g. hprof).
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4332c98747b403970ef4b3352e271633f93935b9825Barry Hayes    gDvm.classSerialNumber = INITIAL_CLASS_SERIAL_NUMBER;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
435318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    /*
436318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * Set up the table we'll use for tracking initiating loaders for
4372c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * early classes.
4382c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * If it's NULL, we just fall back to the InitiatingLoaderList in the
4392c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * ClassObject, so it's not fatal to fail this allocation.
4402c98747b403970ef4b3352e271633f93935b9825Barry Hayes     */
441fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    gDvm.initiatingLoaderList = (InitiatingLoaderList*)
4422c98747b403970ef4b3352e271633f93935b9825Barry Hayes        calloc(ZYGOTE_CLASS_CUTOFF, sizeof(InitiatingLoaderList));
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4448521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein    /*
445318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * Create the initial classes. These are the first objects constructed
446318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein     * within the nascent VM.
447a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein     */
448318839c0b3f912790b61c876fbe75917e1ca0378Dan Bornstein    if (!createInitialClasses()) {
449a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein        return false;
450a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    }
451a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein
452a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    /*
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Process the bootstrap class path.  This means opening the specified
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DEX or Jar files and possibly running them through the optimizer.
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.bootClassPath == NULL);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    processClassPath(gDvm.bootClassPathStr, true);
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPath == NULL)
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
462a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden    return true;
463a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden}
464a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden
465a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden/*
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up.
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4681e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmClassShutdown()
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard all system-loaded classes */
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableFree(gDvm.loadedClasses);
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses = NULL;
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard primitive classes created for arrays */
475a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeVoid);
476a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeBoolean);
477a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeByte);
478a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeShort);
479a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeChar);
480a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeInt);
481a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeLong);
482a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeFloat);
483a9c49df6714b3a37b7a7d0522932e622be2b35acDan Bornstein    dvmFreeClassInnards(gDvm.typeDouble);
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* this closes DEX files, JAR files, etc. */
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeCpeArray(gDvm.bootClassPath);
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = NULL;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearAllocDestroy(NULL);
4902c98747b403970ef4b3352e271633f93935b9825Barry Hayes
4912c98747b403970ef4b3352e271633f93935b9825Barry Hayes    free(gDvm.initiatingLoaderList);
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Bootstrap class loader
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a ClassPathEntry array.
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpClassPath(const ClassPathEntry* cpe)
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx = 0;
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* kindStr;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:       kindStr = "jar";    break;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:       kindStr = "dex";    break;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:            kindStr = "???";    break;
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5174308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  %2d: type=%s %s %p", idx, kindStr, cpe->fileName, cpe->ptr);
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (CALC_CACHE_STATS && cpe->kind == kCpeJar) {
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DvmDex* pDvmDex = dvmGetJarFileDex(pJarFile);
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpAtomicCacheStats(pDvmDex->pInterfaceCache);
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        idx++;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of the bootstrap class path.
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
5321e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmDumpBootClassPath()
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClassPath(gDvm.bootClassPath);
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the class path contains the specified path.
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmClassPathContains(const ClassPathEntry* cpe, const char* path)
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(cpe->fileName, path) == 0)
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free an array of ClassPathEntry structs.
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We release the contents of each entry, then free the array itself.
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeCpeArray(ClassPathEntry* cpe)
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpeStart = cpe;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe == NULL)
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free JarFile */
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmJarFileFree((JarFile*) cpe->ptr);
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free RawDexFile */
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmRawDexFileFree((RawDexFile*) cpe->ptr);
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
5746f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            assert(false);
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cpe->fileName);
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(cpeStart);
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
5866f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * Get the filename suffix of the given file (everything after the
5876f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * last "." if any, or "<none>" if there's no apparent suffix). The
5886f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * passed-in buffer will always be '\0' terminated.
5896f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein */
5906f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornsteinstatic void getFileNameSuffix(const char* fileName, char* suffixBuf, size_t suffixBufLen)
5916f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein{
5926f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    const char* lastDot = strrchr(fileName, '.');
5936f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein
5946f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    strlcpy(suffixBuf, (lastDot == NULL) ? "<none>" : (lastDot + 1), suffixBufLen);
5956f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein}
5966f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein
5976f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein/*
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Prepare a ClassPathEntry struct, which at this point only has a valid
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filename.  We need to figure out what kind of file it is, and for
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * everything other than directories we need to open it up and see
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * what's inside.
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap)
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct stat sb;
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6076f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    if (stat(cpe->fileName, &sb) < 0) {
608062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Unable to stat classpath element '%s'", cpe->fileName);
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (S_ISDIR(sb.st_mode)) {
612c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Directory classpath elements are not supported: %s", cpe->fileName);
6136f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        return false;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6166f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    char suffix[10];
6176f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    getFileNameSuffix(cpe->fileName, suffix, sizeof(suffix));
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6196f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    if ((strcmp(suffix, "jar") == 0) || (strcmp(suffix, "zip") == 0) ||
6206f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            (strcmp(suffix, "apk") == 0)) {
6216f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        JarFile* pJarFile = NULL;
6226f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) {
6236f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            cpe->kind = kCpeJar;
6246f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            cpe->ptr = pJarFile;
6256f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            return true;
6266f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        }
6276f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    } else if (strcmp(suffix, "dex") == 0) {
6286f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        RawDexFile* pRawDexFile = NULL;
6296f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0) {
6306f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            cpe->kind = kCpeDex;
6316f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            cpe->ptr = pRawDexFile;
6326f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein            return true;
6336f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        }
6346f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein    } else {
635c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unknown type suffix '%s'", suffix);
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
638062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    ALOGD("Unable to process classpath element '%s'", cpe->fileName);
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a colon-separated list of directories, Zip files, and DEX files
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into an array of ClassPathEntry structs.
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * During normal startup we fail if there are no entries, because we won't
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * get very far without the basic language support classes, but if we're
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * optimizing a DEX file we allow it.
6491b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden *
6501b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * If entries are added or removed from the bootstrap class path, the
6511b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * dependencies in the DEX files will break, and everything except the
6521b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * very first entry will need to be regenerated.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpe = NULL;
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangle;
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* end;
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx, count;
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pathStr != NULL);
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mangle = strdup(pathStr);
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through and essentially strtok() the string.  Get a count of
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the #of elements while we're at it.
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the path was constructed strangely (e.g. ":foo::bar:") this will
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * over-allocate, which isn't ideal but is mostly harmless.
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = 1;
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (cp = mangle; *cp != '\0'; cp++) {
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == ':') {   /* separates two entries */
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    end = cp;
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage.  We over-alloc by one so we can set an "end" marker.
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe = (ClassPathEntry*) calloc(count+1, sizeof(ClassPathEntry));
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set the global pointer so the DEX file dependency stuff can find it.
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Go through a second time, pulling stuff out.
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cp = mangle;
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = 0;
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cp < end) {
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '\0') {
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leading, trailing, or doubled ':'; ignore it */
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
70132bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            if (isBootstrap &&
70232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                    dvmPathToAbsolutePortion(cp) == NULL) {
703c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("Non-absolute bootclasspath entry '%s'", cp);
70432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                free(cpe);
70532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                cpe = NULL;
70632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                goto bail;
70732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            }
70832bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassPathEntry tmp;
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.kind = kCpeUnknown;
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.fileName = strdup(cp);
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.ptr = NULL;
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            /*
71532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             * Drop an end marker here so DEX loader can walk unfinished
71632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             * list.
71732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             */
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].kind = kCpeLastEntry;
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].fileName = NULL;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].ptr = NULL;
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!prepareCpe(&tmp, isBootstrap)) {
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* drop from list and continue on */
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(tmp.fileName);
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* copy over, pointers and all */
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cpe[idx] = tmp;
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                idx++;
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp += strlen(cp) +1;
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx <= count);
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (idx == 0 && !gDvm.optimizing) {
7366f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        /*
7376f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein         * There's no way the vm will be doing anything if this is the
7386f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein         * case, so just bail out (reasonably) gracefully.
7396f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein         */
740c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("No valid entries found in bootclasspath '%s'", pathStr);
741f7c18055de6e7ffb3ee16a45680ea0ffd6158fbdBen Cheng        gDvm.lastMessage = pathStr;
7426f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein        dvmAbort();
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("  (filled %d of %d slots)", idx, count);
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put end marker in over-alloc slot */
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].kind = kCpeLastEntry;
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].fileName = NULL;
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].ptr = NULL;
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dumpClassPath(cpe);
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangle);
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe;
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the DEX files we loaded from the bootstrap class path for a DEX
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file that has the class with the matching descriptor.
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the matching DEX file and DexClassDef entry if found, otherwise
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns NULL.
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic DvmDex* searchBootPathForClass(const char* descriptor,
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef** ppClassDef)
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pFoundDef = NULL;
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pFoundFile = NULL;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...",
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor);
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
77892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        //ALOGV("+++  checking '%s' (%d)", cpe->fileName, cpe->kind);
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JarFile* pJarFile = (JarFile*) cpe->ptr;
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetJarFileDex(pJarFile);
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetRawDexFileDex(pRawDexFile);
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
814c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Unknown kind %d", cpe->kind);
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Special handling during verification + optimization.
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The DEX optimizer needs to load classes from the DEX file it's working
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * on.  Rather than trying to insert it into the bootstrap class path
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * or synthesizing a class loader to manage it, we just make it available
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here.  It logically comes after all existing entries in the bootstrap
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class path.
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPathOptExtra != NULL) {
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef =
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor);
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pClassDef != NULL) {
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* found */
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundDef = pClassDef;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundFile = gDvm.bootClassPathOptExtra;
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfound:
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ppClassDef = pFoundDef;
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pFoundFile;
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the "extra" DEX, which becomes a de facto member of the bootstrap
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class set.
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetBootPathExtraDex(DvmDex* pDvmDex)
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPathOptExtra = pDvmDex;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the #of entries in the bootstrap class path.
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Used for ClassLoader.getResources().)
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
8631e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapiroint dvmGetBootPathSize()
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry)
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe - gDvm.bootClassPath;
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a resource with the specified name in entry N of the boot class path.
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We return a newly-allocated String of one of these forms:
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   file://path/name
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   jar:file://path!/name
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Where "path" is the bootstrap class path entry and "name" is the string
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * passed into this method.  "path" needs to be an absolute path (starting
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with '/'); if it's not we'd need to "absolutify" it as part of forming
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the URL string.
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectStringObject* dvmGetBootPathResource(const char* name, int idx)
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int kUrlOverhead = 13;        // worst case for Jar URL
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* urlObj = NULL;
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("+++ searching for resource '%s' in %d(%s)",
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        name, idx, cpe[idx].fileName);
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we could use direct array index, but I don't entirely trust "idx" */
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (idx-- && cpe->kind != kCpeLastEntry)
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe->kind == kCpeLastEntry) {
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1];
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (cpe->kind) {
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeJar:
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dexZipFindEntry(&pJarFile->archive, name) == NULL)
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name);
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeDex:
91392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("No resources in DEX files");
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("+++ using URL='%s'", urlBuf);
92181f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes    urlObj = dvmCreateStringFromCstr(urlBuf);
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return urlObj;
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class list management
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* search for these criteria in the Class hash table */
935d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct ClassMatchCriteria {
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     loader;
938d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kInitLoaderInc  4       /* must be power of 2 */
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9422c98747b403970ef4b3352e271633f93935b9825Barry Hayesstatic InitiatingLoaderList *dvmGetInitiatingLoaderList(ClassObject* clazz)
9432c98747b403970ef4b3352e271633f93935b9825Barry Hayes{
944c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->serialNumber >= INITIAL_CLASS_SERIAL_NUMBER);
9452c98747b403970ef4b3352e271633f93935b9825Barry Hayes    int classIndex = clazz->serialNumber-INITIAL_CLASS_SERIAL_NUMBER;
9462c98747b403970ef4b3352e271633f93935b9825Barry Hayes    if (gDvm.initiatingLoaderList != NULL &&
9472c98747b403970ef4b3352e271633f93935b9825Barry Hayes        classIndex < ZYGOTE_CLASS_CUTOFF) {
9482c98747b403970ef4b3352e271633f93935b9825Barry Hayes        return &(gDvm.initiatingLoaderList[classIndex]);
9492c98747b403970ef4b3352e271633f93935b9825Barry Hayes    } else {
9502c98747b403970ef4b3352e271633f93935b9825Barry Hayes        return &(clazz->initiatingLoaderList);
9512c98747b403970ef4b3352e271633f93935b9825Barry Hayes    }
9522c98747b403970ef4b3352e271633f93935b9825Barry Hayes}
9532c98747b403970ef4b3352e271633f93935b9825Barry Hayes
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine if "loader" appears in clazz' initiating loader list.
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class hash table lock must be held when calling here, since
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it's also used when updating a class' initiating loader list.
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: switch to some sort of lock-free data structure so we don't have
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to grab the lock to do a lookup.  Among other things, this would improve
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the speed of compareDescriptorClasses().
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader)
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The bootstrap class loader can't be just an initiating loader for
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anything (it's always the defining loader if the class is visible
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to it).  We don't put defining loaders in the initiating list.
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader == NULL)
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Scan the list for a match.  The list is expected to be short.
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
9772c98747b403970ef4b3352e271633f93935b9825Barry Hayes    /* Cast to remove the const from clazz, but use const loaderList */
9782c98747b403970ef4b3352e271633f93935b9825Barry Hayes    ClassObject* nonConstClazz = (ClassObject*) clazz;
9792c98747b403970ef4b3352e271633f93935b9825Barry Hayes    const InitiatingLoaderList *loaderList =
9802c98747b403970ef4b3352e271633f93935b9825Barry Hayes        dvmGetInitiatingLoaderList(nonConstClazz);
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
9822c98747b403970ef4b3352e271633f93935b9825Barry Hayes    for (i = loaderList->initiatingLoaderCount-1; i >= 0; --i) {
9832c98747b403970ef4b3352e271633f93935b9825Barry Hayes        if (loaderList->initiatingLoaders[i] == loader) {
9844308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            //ALOGI("+++ found initiating match %p in %s",
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    loader, clazz->descriptor);
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "loader" to clazz's initiating loader set, unless it's the defining
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader.
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the common case this will be a short list, so we don't need to do
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything too fancy here.
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This locks gDvm.loadedClasses for synchronization, so don't hold it
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * when calling here.
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddInitiatingLoader(ClassObject* clazz, Object* loader)
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != clazz->classLoader) {
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(loader != NULL);
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Adding %p to '%s' init list", loader, clazz->descriptor);
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.loadedClasses);
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Make sure nobody snuck in.  The penalty for adding twice is
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pretty minor, and probably outweighs the O(n^2) hit for
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * checking before every add, so we may not want to do this.
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
10152c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //if (dvmLoaderInInitiatingList(clazz, loader)) {
1016e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        //    ALOGW("WOW: simultaneous add of initiating class loader");
10172c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //    goto bail_unlock;
10182c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //}
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The list never shrinks, so we just keep a count of the
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * number of elements in it, and reallocate the buffer when
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we run off the end.
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The pointer is initially NULL, so we *do* want to call realloc
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when count==0.
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
10282c98747b403970ef4b3352e271633f93935b9825Barry Hayes        InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
10292c98747b403970ef4b3352e271633f93935b9825Barry Hayes        if ((loaderList->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) {
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object** newList;
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10322c98747b403970ef4b3352e271633f93935b9825Barry Hayes            newList = (Object**) realloc(loaderList->initiatingLoaders,
10332c98747b403970ef4b3352e271633f93935b9825Barry Hayes                        (loaderList->initiatingLoaderCount + kInitLoaderInc)
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * sizeof(Object*));
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (newList == NULL) {
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* this is mainly a cache, so it's not the EotW */
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail_unlock;
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
10402c98747b403970ef4b3352e271633f93935b9825Barry Hayes            loaderList->initiatingLoaders = newList;
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10424308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            //ALOGI("Expanded init list to %d (%s)",
10432c98747b403970ef4b3352e271633f93935b9825Barry Hayes            //    loaderList->initiatingLoaderCount+kInitLoaderInc,
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor);
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
10462c98747b403970ef4b3352e271633f93935b9825Barry Hayes        loaderList->initiatingLoaders[loaderList->initiatingLoaderCount++] =
10472c98747b403970ef4b3352e271633f93935b9825Barry Hayes            loader;
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.loadedClasses);
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.)
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entries in the class hash table are stored as { descriptor, d-loader }
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * tuples.  If the hashed class descriptor matches the requested descriptor,
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the hashed defining class loader matches the requested class
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader, we're good.  If only the descriptor matches, we check to see if the
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader is in the hashed class' initiating loader list.  If so, we
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can return "true" immediately and skip some of the loadClass melodrama.
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must lock the hash table before calling here.
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns 0 if a matching entry is found, nonzero otherwise.
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByCrit(const void* vclazz, const void* vcrit)
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit;
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 &&
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == pCrit->loader ||
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (pCrit->loader != NULL &&
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, pCrit->loader)) ));
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //if (match)
10794308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //    ALOGI("+++ %s %p matches existing %s %p",
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        pCrit->descriptor, pCrit->loader,
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        clazz->descriptor, clazz->classLoader);
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instead of a ClassMatchCriteria.
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByClass(const void* vclazz, const void* vaddclazz)
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* addClazz = (const ClassObject*) vaddclazz;
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 &&
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == addClazz->classLoader ||
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (addClazz->classLoader != NULL &&
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) ));
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search through the hash table to find an entry with a matching descriptor
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and an initiating class loader that matches "loader".
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The table entries are hashed on descriptor only, because they're unique
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on *defining* class loader, not *initiating* class loader.  This isn't
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * great, because it guarantees we will have to probe when multiple
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loaders are used.
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note this does NOT try to load a class; it just finds a class that
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has already been loaded.
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "unprepOkay" is set, this will return classes that have been added
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the hash table but are not yet fully loaded and linked.  Otherwise,
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * such classes are ignored.  (The only place that should set "unprepOkay"
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is findClassNoInit(), which will wait for the prep to finish.)
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if not found.
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmLookupClass(const char* descriptor, Object* loader,
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool unprepOkay)
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassMatchCriteria crit;
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.descriptor = descriptor;
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.loader = loader;
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(descriptor);
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p",
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThreadSelf()->threadId, descriptor, loader);
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit,
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByCrit, false);
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been added to the hash table but isn't ready for use.
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're going to act like we didn't see it, so that the caller will
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * go through the full "find class" path, which includes locking the
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * object and waiting until it's ready.  We could do that lock/wait
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here, but this is an extremely rare case, and it's simpler to have
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the wait-for-class code centralized.
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1148fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    if (found && !unprepOkay && !dvmIsClassLinked((ClassObject*)found)) {
114992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Ignoring not-yet-ready %s, using slow path",
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((ClassObject*)found)->descriptor);
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        found = NULL;
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) found;
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new class to the hash table.
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class is considered "new" if it doesn't match on both the class
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor and the defining class loader.
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we should probably have separate hash tables for each
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader. This could speed up dvmLookupClass and
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * other common operations. It does imply a VM-visible data structure
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for each ClassLoader object with loaded classes, which we don't
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have yet.
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmAddClassToHash(ClassObject* clazz)
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(clazz->descriptor);
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz,
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByClass, true);
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p",
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader,
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (found == (void*) clazz), clazz);
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmCheckClassTablePerf();
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* can happen if two threads load the same class simultaneously */
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (found == (void*) clazz);
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute hash value for a class.
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 hashcalcClass(const void* item)
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor);
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check the performance of the "loadedClasses" hash table.
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
12031e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmCheckClassTablePerf()
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hashcmpClassByClass);
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove a class object from the hash table.
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeClassFromHash(ClassObject* clazz)
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
121792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("+++ removeClassFromHash '%s'", clazz->descriptor);
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash = dvmComputeUtf8Hash(clazz->descriptor);
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz))
1223e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Hash table remove failed on class '%s'", clazz->descriptor);
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class creation
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set clazz->serialNumber to the next available value.
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This usually happens *very* early in class creation, so don't expect
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything else in the class to be ready.
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetClassSerialNumber(ClassObject* clazz)
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->serialNumber == 0);
1243fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden    clazz->serialNumber = android_atomic_inc(&gDvm.classSerialNumber);
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded and initialized if it has not already been.
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If necessary, the superclass will be loaded.
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClass(const char* descriptor, Object* loader)
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindClassNoInit(descriptor, loader);
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded if it has not already been, as will its
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass.  It will not be initialized.
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClassNoInit(const char* descriptor,
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* loader)
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(descriptor != NULL);
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //assert(loader != NULL);
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
129160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("FindClassNoInit '%s' %p", descriptor, loader);
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*descriptor == '[') {
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Array class.  Find in table, generate if not found.
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return dvmFindArrayClass(descriptor, loader);
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Regular class.  Find in table, load if not found.
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (loader != NULL) {
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return findClassFromLoaderNoInit(descriptor, loader);
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return dvmFindSystemClassNoInit(descriptor);
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified class
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader.  This calls out to let the ClassLoader object do its thing.
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns with NULL and an exception raised on error.
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader)
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
13194308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("##### findClassFromLoaderNoInit (%s,%p)",
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        descriptor, loader);
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(loader != NULL);
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do we already have it?
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class loader code does the "is it already loaded" check as
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * well.  However, this call is much faster than calling through
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * interpreted code.  Doing this does mean that in the common case
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (365 out of 420 calls booting the sim) we're doing the
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * lookup-by-descriptor twice.  It appears this is still a win, so
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm keeping it in.
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1336dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    ClassObject* clazz = dvmLookupClass(descriptor, loader, false);
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL) {
133860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Already loaded: %s %p", descriptor, loader);
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return clazz;
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
134160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Not already loaded: %s %p", descriptor, loader);
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dotName = NULL;
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = NULL;
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dotName = dvmDescriptorToDot(descriptor);
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dotName == NULL) {
1350d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowOutOfMemoryError(NULL);
1351dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        return NULL;
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
135381f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes    nameObj = dvmCreateStringFromCstr(dotName);
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (nameObj == NULL) {
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceClassPrepBegin();
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Invoke loadClass().  This will probably result in a couple of
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exceptions being thrown, because the ClassLoader.loadClass()
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation eventually calls VMClassLoader.loadClass to see if
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the bootstrap class loader can find it before doing its own load.
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
136760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("--- Invoking loadClass(%s, %p)", dotName, loader);
1368dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    {
1369dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        const Method* loadClass =
1370dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
1371dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        JValue result;
1372dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        dvmCallMethod(self, loadClass, loader, &result, nameObj);
1373dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        clazz = (ClassObject*) result.l;
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1375dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        dvmMethodTraceClassPrepEnd();
1376dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        Object* excep = dvmGetException(self);
1377dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        if (excep != NULL) {
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2
1379062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("NOTE: loadClass '%s' %p threw exception %s",
1380dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro                 dotName, loader, excep->clazz->descriptor);
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1382dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            dvmAddTrackedAlloc(excep, self);
1383dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            dvmClearException(self);
1384dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            dvmThrowChainedNoClassDefFoundError(descriptor, excep);
1385dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            dvmReleaseTrackedAlloc(excep, self);
1386dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            clazz = NULL;
1387dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            goto bail;
1388dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        } else if (clazz == NULL) {
1389e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("ClassLoader returned NULL w/o exception pending");
1390dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            dvmThrowNullPointerException("ClassLoader returned null");
1391dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            goto bail;
1392dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        }
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13950477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    /* not adding clazz to tracked-alloc list, because it's a ClassObject */
13960477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddInitiatingLoader(clazz, loader);
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)",
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor, clazz->classLoader, loader, clazz);
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(dotName);
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified DEX file.
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Used by class loaders to instantiate a class object from a
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-managed DEX.
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* classLoader)
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pDvmDex != NULL);
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, classLoader, pDvmDex);
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), scanning through the
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath if it hasn't already been loaded.
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" looks like "Landroid/debug/Stuff;".
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Uses NULL as the defining class loader.
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClass(const char* descriptor)
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClassNoInit(descriptor);
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), searching for it in the
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath.
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, NULL, NULL);
1457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor). If it's not already loaded,
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we load it and link it, but don't execute <clinit>. (The VM has
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specific limitations on which events can cause initialization.)
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we need to return an indication of whether we loaded the class or
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used an existing definition.  If somebody deliberately tries to load a
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class twice in the same class loader, they should get a LinkageError,
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but inadvertent simultaneous class references should "just work".
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex)
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool profilerNotified = false;
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != NULL) {
148160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("#### findClassNoInit(%s,%p,%p)", descriptor, loader,
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex->pDexFile);
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't expect an exception to be raised at this point.  The
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception handling code is good about managing this.  This *can*
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * happen if a JNI lookup fails and the JNI code doesn't do any
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * error checking before doing another class lookup, so we may just
1490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want to clear this and restore it on exit.  If we don't, some kinds
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of failures can't be detected without rearranging other stuff.
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Most often when we hit this situation it means that something is
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * broken in the VM or in JNI code, so I'm keeping it in place (and
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * making it an informative abort rather than an assert).
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
1498c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Class lookup %s attempted with exception pending", descriptor);
1499e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Pending exception is:");
1500d8d251136b7c63e1006da35197fc1962e56ae473Elliott Hughes        dvmLogExceptionStackTrace();
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpAllThreads(false);
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmLookupClass(descriptor, loader, true);
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepBegin();
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        profilerNotified = true;
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u8 startTime = dvmGetThreadCpuTimeNsec();
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL) {
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);     /* shouldn't be here otherwise */
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL || pClassDef == NULL) {
15247fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            if (gDvm.noClassDefFoundErrorObj != NULL) {
15257fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                /* usual case -- use prefabricated object */
15267fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                dvmSetException(self, gDvm.noClassDefFoundErrorObj);
15277fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            } else {
15287fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                /* dexopt case -- can't guarantee prefab (core.jar) */
1529d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowNoClassDefFoundError(descriptor);
15307fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            }
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* found a match, try to load it */
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* class was found but had issues */
1538a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            if (clazz != NULL) {
1539a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden                dvmFreeClassInnards(clazz);
1540a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden                dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1541a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            }
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Lock the class while we link it so other threads must wait for us
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to finish.  Set the "initThreadId" so we can identify recursive
154810cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden         * invocation.  (Note all accesses to initThreadId here are
154910cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden         * guarded by the class object's lock.)
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->initThreadId = self->threadId;
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add to hash table so lookups succeed.
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * [Are circular references possible when linking a class?]
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->classLoader == loader);
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmAddClassToHash(clazz)) {
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Another thread must have loaded the class after we
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * started but before we finished.  Discard what we've
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * done and leave some hints for the GC.
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (Yes, this happens.)
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1568e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            //ALOGW("WOW: somebody loaded %s simultaneously", descriptor);
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let the GC free the class.
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1574a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            dvmFreeClassInnards(clazz);
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Grab the winning class.
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = dvmLookupClass(descriptor, loader, true);
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz != NULL);
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto got_class;
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoadWithTime('>', clazz, startTime);
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Prepare and resolve.
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1591c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (!dvmLinkClass(clazz)) {
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Make note of the error and clean up the class.
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            removeClassFromHash(clazz);
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFreeClassInnards(clazz);
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let any waiters know.
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmObjectNotifyAll(self, (Object*) clazz);
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
16071663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s",
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, get_process_name());
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: It would probably be better to use a new type code here (instead of '<') to
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * indicate the failure.  This change would require a matching change in the parser
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * and analysis code in frameworks/base/tools/preload.
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            logClassLoad('<', clazz);
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.optimizing) {
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* happens with "external" libs */
162092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("Link of class '%s' failed", descriptor);
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1622e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                ALOGW("Link of class '%s' failed", descriptor);
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectNotifyAll(self, (Object*) clazz);
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add class stats to global counters.
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: these should probably be atomic ops.
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numLoadedClasses++;
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods +=
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethodCount + clazz->directMethodCount;
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredInstFields += clazz->ifieldCount;
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Cache pointers to basic classes.  We want to use these in
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * various places, and it's easiest to initialize them on first
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * use rather than trying to force them to initialize (startup
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * ordering makes it weird).
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classJavaLangObject == NULL &&
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(descriptor, "Ljava/lang/Object;") == 0)
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* It should be impossible to get here with anything
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * but the bootclasspath loader.
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.classJavaLangObject = clazz;
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('<', clazz);
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectgot_class:
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can race with other threads for class linking.  We should
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never get here recursively; doing so indicates that two
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes have circular dependencies.
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * One exception: we force discovery of java.lang.Class in
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * dvmLinkClass(), and Class has Object as its superclass.  So
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * if the first thing we ever load is Object, we will init
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Object->Class->Object.  The easiest way to avoid this is to
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * ensure that Object is never the first thing we look up, so
1673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we get Foo->Class->Object instead.
1674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
1676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsClassLinked(clazz) &&
1677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->initThreadId == self->threadId)
1678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1679e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                ALOGW("Recursive link on class %s", clazz->descriptor);
1680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmUnlockObject(self, (Object*) clazz);
168170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein                dvmThrowClassCircularityError(clazz->descriptor);
1682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz = NULL;
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
16854308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            //ALOGI("WAITING  for '%s' (owner=%d)",
1686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor, clazz->initThreadId);
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
1693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Somebody else tried to load this and failed.  We need to raise
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * an exception and report failure.
1696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check some invariants */
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz));
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.classJavaLangClass != NULL);
1706dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(clazz->clazz == gDvm.classJavaLangClass);
1707dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(dvmIsClassObject(clazz));
17089ef5ca666a214f2a96b16e0830e19d37742ab8caAndy McFadden    assert(clazz == gDvm.classJavaLangObject || clazz->super != NULL);
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
17104308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        //ALOGI("class=%s vtableCount=%d, virtualMeth=%d",
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->vtableCount,
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->virtualMethodCount);
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtableCount >= clazz->virtualMethodCount);
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (profilerNotified)
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepEnd();
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != NULL || dvmCheckException(self));
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * encoded data pointer in addition to the other arguments.
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData, Object* classLoader)
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* newClass = NULL;
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make sure the aren't any "bonus" flags set, since we use them for
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * runtime state.
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1744e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Invalid file flags in class %s: %04x",
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            descriptor, pClassDef->accessFlags);
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage for the class object on the GC heap, so that other
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects can have references to it.  We bypass the usual mechanism
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (allocObject), because we don't have all the bits and pieces yet.
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that we assume that java.lang.Class does not override
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finalize().
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1757c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    /* TODO: Can there be fewer special checks in the usual path? */
1758c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(descriptor != NULL);
1759c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (classLoader == NULL &&
1760c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        strcmp(descriptor, "Ljava/lang/Class;") == 0) {
1761c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        assert(gDvm.classJavaLangClass != NULL);
1762c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        newClass = gDvm.classJavaLangClass;
1763c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    } else {
1764c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        size_t size = classObjectSize(pHeader->staticFieldsSize);
176552e2626eb3bf620c53459a90d912733de2ce0369Carl Shapiro        newClass = (ClassObject*) dvmMalloc(size, ALLOC_NON_MOVING);
1766c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newClass == NULL)
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1770dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    DVM_OBJECT_INIT(newClass, gDvm.classJavaLangClass);
1771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetClassSerialNumber(newClass);
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->descriptor = descriptor;
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(newClass->descriptorAlloc == NULL);
1774c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    SET_CLASS_FLAG(newClass, pClassDef->accessFlags);
1775364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    dvmSetFieldObject((Object *)newClass,
1776dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro                      OFFSETOF_MEMBER(ClassObject, classLoader),
1777364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                      (Object *)classLoader);
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->pDvmDex = pDvmDex;
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->primitiveType = PRIM_NOT;
1780c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    newClass->status = CLASS_IDX;
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff the superclass index into the object pointer field.  The linker
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pulls it out and replaces it with a resolved ClassObject pointer.
1785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm doing it this way (rather than having a dedicated superclassIdx
1786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field) to save a few bytes of overhead per class.
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this is safe.
1790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1791c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(sizeof(u4) == sizeof(ClassObject*)); /* 32-bit check */
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->super = (ClassObject*) pClassDef->superclassIdx;
1793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff class reference indices into the pointer fields.
1796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The elements of newClass->interfaces are not traversed or freed by
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmFreeClassInnards, so this is GC-safe.
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexTypeList* pInterfacesList;
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pInterfacesList != NULL) {
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaceCount = pInterfacesList->size;
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                newClass->interfaceCount * sizeof(ClassObject*));
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < newClass->interfaceCount; i++) {
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->interfaces);
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* load field definitions */
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
181703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * Over-allocate the class object and append static field info
181803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * onto the end.  It's fixed-size and known at alloc time.  This
181903aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * seems to increase zygote sharing.  Heap compaction will have to
182003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * be careful if it ever tries to move ClassObject instances,
182103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * because we pass Field pointers around internally. But at least
182203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * now these Field pointers are in the object heap.
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->staticFieldsSize != 0) {
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* static fields stay on system heap; field data isn't "write once" */
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->staticFieldsSize;
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->sfieldCount = count;
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->instanceFieldsSize != 0) {
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->instanceFieldsSize;
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifieldCount = count;
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(InstField));
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->ifields);
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /*
185499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Load method definitions.  We do this in two batches, direct then
185599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * virtual.
185699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *
185799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * If register maps have already been generated for this class, and
185899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * precise GC is enabled, we pull out pointers to them.  We know that
185999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * they were streamed to the DEX file in the same order in which the
186099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * methods appear.
186199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *
186299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * If the class wasn't pre-verified, the maps will be generated when
186399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * the class is verified during class initialization.
186499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
186599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
186699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const void* classMapData;
186799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u4 numMethods;
186899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
186999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (gDvm.preciseGc) {
187099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        classMapData =
1871d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden            dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
187299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
187399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /* sanity check */
187499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (classMapData != NULL &&
187599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
187699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        {
1877c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d",
187899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                newClass->descriptor, pHeader->directMethodsSize,
187999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                pHeader->virtualMethodsSize, numMethods);
188099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            assert(false);
188199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            classMapData = NULL;        /* abandon */
188299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
188399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } else {
188499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        classMapData = NULL;
188599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->directMethodsSize != 0) {
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->directMethodsSize;
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethodCount = count;
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
189899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            if (classMapData != NULL) {
1899d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1900d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
190199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    newClass->directMethods[i].registerMap = pMap;
190299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    /* TODO: add rigorous checks */
190399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    assert((newClass->directMethods[i].registersSize+7) / 8 ==
190499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                        newClass->directMethods[i].registerMap->regWidth);
190599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                }
190699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            }
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->directMethods);
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->virtualMethodsSize != 0) {
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->virtualMethodsSize;
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethodCount = count;
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
192299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            if (classMapData != NULL) {
1923d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1924d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
192599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    newClass->virtualMethods[i].registerMap = pMap;
192699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    /* TODO: add rigorous checks */
192799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
192899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                        newClass->virtualMethods[i].registerMap->regWidth);
192999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                }
193099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            }
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* caller must call dvmReleaseTrackedAlloc */
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newClass;
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to load the indicated class from the specified DEX file.
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is effectively loadClass()+defineClass() for a DexClassDef.  The
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loading was largely done when we crunched through the DEX.
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL on failure.  If we locate the class but encounter an error
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while processing it, an appropriate exception is thrown.
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, Object* classLoader)
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result;
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassDataHeader header;
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData;
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((pDvmDex != NULL) && (pClassDef != NULL));
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass) {
196292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("CLASS: loading '%s'...",
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexGetClassDescriptor(pDexFile, pClassDef));
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEncodedData = dexGetClassData(pDexFile, pClassDef);
1967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pEncodedData != NULL) {
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexReadClassDataHeader(&pEncodedData, &header);
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Provide an all-zeroes header for the rest of the loading.
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memset(&header, 0, sizeof(header));
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            classLoader);
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass && (result != NULL)) {
19794308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("[Loaded %s from DEX %p (cl=%p)]",
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result->descriptor, pDvmDex, classLoader);
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a ClassObject that was allocated on the system heap.
1988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ClassObject itself is allocated on the GC heap, so we leave it for
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the garbage collector.
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this may be called with a partially-constructed object.
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: there is no particular ordering imposed, so don't go poking at
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclasses.
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeClassInnards(ClassObject* clazz)
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void *tp;
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
2002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2004dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(clazz->clazz == gDvm.classJavaLangClass);
2005dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(dvmIsClassObject(clazz));
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Guarantee that dvmFreeClassInnards can be called on a given
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class multiple times by clearing things out as we free them.
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't make any attempt at real atomicity here; higher
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * levels need to make sure that no two threads can free the
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * same ClassObject at the same time.
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: maybe just make it so the GC will never free the
2014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * innards of an already-freed class.
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_FREE(p) \
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
2023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(tp); \
2024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
2025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
2026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_LINEAR_FREE(p) \
2027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
2028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
2029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
2030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
2031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearFree(clazz->classLoader, tp); \
2032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
2033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
2034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* arrays just point at Object's vtable; don't free vtable in this case.
2036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtableCount = -1;
203833a192e2096cff25029ae339de84d33a443e7c8eBarry Hayes    if (clazz->vtable == gDvm.classJavaLangObject->vtable) {
2039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = NULL;
2040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL_AND_LINEAR_FREE(clazz->vtable);
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->descriptor = NULL;
2045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_FREE(clazz->descriptorAlloc);
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->directMethods != NULL) {
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *directMethods = clazz->directMethods;
2049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int directMethodCount = clazz->directMethodCount;
2050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethods = NULL;
2051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethodCount = -1;
2052b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(clazz->classLoader, directMethods);
2053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < directMethodCount; i++) {
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&directMethods[i]);
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2056b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadOnly(clazz->classLoader, directMethods);
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, directMethods);
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->virtualMethods != NULL) {
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *virtualMethods = clazz->virtualMethods;
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int virtualMethodCount = clazz->virtualMethodCount;
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount = -1;
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = NULL;
2064b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(clazz->classLoader, virtualMethods);
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < virtualMethodCount; i++) {
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&virtualMethods[i]);
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2068b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadOnly(clazz->classLoader, virtualMethods);
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, virtualMethods);
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20722c98747b403970ef4b3352e271633f93935b9825Barry Hayes    InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
20732c98747b403970ef4b3352e271633f93935b9825Barry Hayes    loaderList->initiatingLoaderCount = -1;
20742c98747b403970ef4b3352e271633f93935b9825Barry Hayes    NULL_AND_FREE(loaderList->initiatingLoaders);
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->interfaceCount = -1;
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->interfaces);
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = -1;
2080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->iftable);
2081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = -1;
2083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifviPool);
2084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->sfieldCount = -1;
208603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes    /* The sfields are attached to the ClassObject, and will be freed
208703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * with it. */
2088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldCount = -1;
2090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifields);
2091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_FREE
2093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_LINEAR_FREE
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a Method that was allocated on the system heap.
209899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
209999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * The containing class is largely torn down by this point.
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeMethodInnards(Method* meth)
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->exceptions);
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->lines);
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->locals);
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
210899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
210999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /*
211099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Some register maps are allocated on the heap, either because of late
211199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * verification or because we're caching an uncompressed form.
211299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
211399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const RegisterMap* pMap = meth->registerMap;
2114d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden    if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
211599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dvmFreeRegisterMap((RegisterMap*) pMap);
211699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        meth->registerMap = NULL;
211799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
2118b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2119b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    /*
2120b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden     * We may have copied the instructions.
2121b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden     */
2122b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2123b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2124b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearFree(meth->clazz->classLoader, methodDexCode);
2125b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clone a Method, making new copies of anything that will be freed up
213099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * by freeMethodInnards().  This is used for "miranda" methods.
2131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void cloneMethod(Method* dst, const Method* src)
2133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
213499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (src->registerMap != NULL) {
2135c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("GLITCH: only expected abstract methods here");
2136c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("        cloning %s.%s", src->clazz->descriptor, src->name);
213799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dvmAbort();
213899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
2139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(dst, src, sizeof(Method));
2140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pull the interesting pieces out of a DexMethod.
2144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The DEX file isn't going anywhere, so we don't need to make copies of
2146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the code area.
2147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
2149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth)
2150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexMethodId* pMethodId;
2153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pDexCode;
2154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
2156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->shorty = dexProtoGetShorty(&meth->prototype);
2160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->accessFlags = pDexMethod->accessFlags;
2161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->clazz = clazz;
2162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->jniArgInfo = 0;
2163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2165ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        /*
2166ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * The Enum class declares a "final" finalize() method to
2167ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * prevent subclasses from introducing a finalizer.  We don't
2168ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * want to set the finalizable flag for Enum or its subclasses,
2169ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * so we check for it here.
2170ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         *
2171ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * We also want to avoid setting it on Object, but it's easier
2172ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * to just strip that out later.
2173ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         */
2174ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        if (clazz->classLoader != NULL ||
2175ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden            strcmp(clazz->descriptor, "Ljava/lang/Enum;") != 0)
2176ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        {
2177ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden            SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2178ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        }
2179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexCode = dexGetCode(pDexFile, pDexMethod);
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexCode != NULL) {
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* integer constants, copy over for faster access */
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = pDexCode->registersSize;
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insSize = pDexCode->insSize;
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->outsSize = pDexCode->outsSize;
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* pointer to code area */
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insns = pDexCode->insns;
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't have a DexCode block, but we still want to know how
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * much space is needed for the arguments (so we don't have to
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * compute it later).  We also take this opportunity to compute
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * JNI argument info.
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We do this for abstract methods as well, because we want to
2198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be able to substitute our exception-throwing "stub" in.
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int argsSize = dvmComputeMethodArgsSize(meth);
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsStaticMethod(meth))
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            argsSize++;
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = meth->insSize = argsSize;
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->outsSize == 0);
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->insns == NULL);
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = dvmResolveNativeMethod;
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#if 0       /* replaced with private/read-write mapping */
2215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2216b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * We usually map bytecode directly out of the DEX file, which is mapped
2217b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * shared read-only.  If we want to be able to modify it, we have to make
2218b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * a new copy.
2219b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2220b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Once copied, the code will be in the LinearAlloc region, which may be
2221b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * marked read-only.
2222b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2223b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * The bytecode instructions are embedded inside a DexCode structure, so we
2224b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * need to copy all of that.  (The dvmGetMethodCode function backs up the
2225b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * instruction pointer to find the start of the DexCode.)
2226b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
2227b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmMakeCodeReadWrite(Method* meth)
2228b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
2229b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2230b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2231b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2232b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
2233b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        return;
2234b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
2235b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2236b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
2237b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2238b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
2239062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    ALOGD("Making a copy of %s.%s code (%d bytes)",
2240b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        meth->clazz->descriptor, meth->name, dexCodeSize);
2241b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2242b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* newCode =
2243b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
2244b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    memcpy(newCode, methodDexCode, dexCodeSize);
2245b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2246b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    meth->insns = newCode->insns;
2247b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
2248b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
2249b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2250b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
2251b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Mark the bytecode read-only.
2252b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2253b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * If the contents of the DexCode haven't actually changed, we could revert
2254b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * to the original shared page.
2255b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
2256b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmMakeCodeReadOnly(Method* meth)
2257b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
2258b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
225992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("+++ marking %p read-only", methodDexCode);
2260b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
2261b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
226296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif
2263b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2264b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2265b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jniArgInfo (32-bit int) layout:
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   S - if set, do things the hard way (scan the signature)
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   R - return-type enumeration
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   H - target-specific hints
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This info is used at invocation time by dvmPlatformInvoke.  In most
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * having to fully parse the signature.
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The return-type bits are always set, even if target-specific hint bits
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are unavailable.
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeJniArgInfo(const DexProto* proto)
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = dexProtoGetShorty(proto);
2283e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    int returnType, jniArgInfo;
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hints;
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The first shorty character is the return type. */
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (*(sig++)) {
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_VOID;
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_FLOAT;
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_DOUBLE;
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S8;
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2300e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'Z':
2301e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'B':
2302e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_S1;
2303e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2304e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'C':
2305e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_U2;
2306e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2307e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'S':
2308e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_S2;
2309e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S4;
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hints = dvmPlatformInvokeHints(proto);
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (hints & DALVIK_JNI_NO_ARG_INFO) {
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= hints;
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return jniArgInfo;
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about a static field.
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This also "prepares" static fields by initializing them
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to their "standard default values".
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadSFieldFromDex(ClassObject* clazz,
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexSField, StaticField* sfield)
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2343a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    sfield->clazz = clazz;
2344a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    sfield->name = dexStringById(pDexFile, pFieldId->nameIdx);
2345a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    sfield->signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2346a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    sfield->accessFlags = pDexSField->accessFlags;
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Static object field values are set to "standard default values"
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (null or 0) until the class is initialized.  We delay loading
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant values from the class until that time.
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //sfield->value.j = 0;
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sfield->value.j == 0LL);     // cleared earlier with calloc
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about an instance field.
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadIFieldFromDex(ClassObject* clazz,
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexIField, InstField* ifield)
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2367a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    ifield->clazz = clazz;
2368a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    ifield->name = dexStringById(pDexFile, pFieldId->nameIdx);
2369a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    ifield->signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2370a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro    ifield->accessFlags = pDexIField->accessFlags;
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(ifield->byteOffset == 0);    // cleared earlier with calloc
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->byteOffset = -1;    // make it obvious if we fail to set later
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache java.lang.ref.Reference fields and methods.
2379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
23806daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic bool precacheReferenceOffsets(ClassObject* clazz)
2381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* We trick the GC object scanner by not counting
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.ref.Reference.referent as an object
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field.  It will get explicitly scanned as part
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the reference-walking process.
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Find the object field named "referent" and put it
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just after the list of object reference fields.
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldRefCount; i++) {
2394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
2395a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        if (strcmp(pField->name, "referent") == 0) {
2396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int targetIndex;
2397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Swap this field with the last object field.
2399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targetIndex = clazz->ifieldRefCount - 1;
2401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i != targetIndex) {
2402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField *swapField = &clazz->ifields[targetIndex];
2403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField tmpField;
2404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int tmpByteOffset;
2405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* It's not currently strictly necessary
2407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * for the fields to be in byteOffset order,
2408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * but it's more predictable that way.
2409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpByteOffset = swapField->byteOffset;
2411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                swapField->byteOffset = pField->byteOffset;
2412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pField->byteOffset = tmpByteOffset;
2413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpField = *swapField;
2415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *swapField = *pField;
2416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *pField = tmpField;
2417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* One fewer object field (wink wink).
2420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount--;
2422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i--;        /* don't trip "didn't find it" test if field was last */
2423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i == clazz->ifieldRefCount) {
2428c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Unable to reorder 'referent' in %s", clazz->descriptor);
2429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243240fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein    /*
243340fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein     * Now that the above has been done, it is safe to cache
243440fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein     * info about the class.
2435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
243640fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein    if (!dvmFindReferenceMembers(clazz)) {
2437c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Trouble with Reference setup");
243840fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein        return false;
243940fcd04f6b2a776aae1d52d1a49e6652e735051fDan Bornstein    }
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
24466daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes * Set the bitmap of reference offsets, refOffsets, from the ifields
24476daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes * list.
24486daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes */
24496daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic void computeRefOffsets(ClassObject* clazz)
24506daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes{
24516daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    if (clazz->super != NULL) {
24526daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        clazz->refOffsets = clazz->super->refOffsets;
24536daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    } else {
24546daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        clazz->refOffsets = 0;
24556daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    }
24566daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    /*
24576daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * If our superclass overflowed, we don't stand a chance.
24586daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     */
24596daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    if (clazz->refOffsets != CLASS_WALK_SUPER) {
24606daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        InstField *f;
24616daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        int i;
24626daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24636daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        /* All of the fields that contain object references
24646daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes         * are guaranteed to be at the beginning of the ifields list.
24656daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes         */
24666daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        f = clazz->ifields;
24676daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        const int ifieldRefCount = clazz->ifieldRefCount;
24686daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        for (i = 0; i < ifieldRefCount; i++) {
24696daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          /*
24706daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * Note that, per the comment on struct InstField,
24716daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * f->byteOffset is the offset from the beginning of
24726daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * obj, not the offset into obj->instanceData.
24736daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           */
24742fbe6d15ed8d266ed55fb76e97f866dbd07d5fa6Andy McFadden          assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
24756daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
24766daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
24776daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
24786daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              assert(newBit != 0);
24796daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              clazz->refOffsets |= newBit;
24806daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          } else {
24816daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              clazz->refOffsets = CLASS_WALK_SUPER;
24826daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              break;
24836daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          }
24846daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          f++;
24856daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        }
24866daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    }
24876daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes}
24886daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24896daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24906daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes/*
2491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Link (prepare and resolve).  Verification is deferred until later.
2492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This converts symbolic references into pointers.  It's independent of
2494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the source file format.
2495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2496c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * If clazz->status is CLASS_IDX, then clazz->super and interfaces[] are
2497c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * holding class reference indices rather than pointers.  The class
2498c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * references will be resolved during link.  (This is done when
2499c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * loading from DEX to avoid having to create additional storage to
2500c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * pass the indices around.)
2501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" with an exception pending on failure.
2503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2504c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayesbool dvmLinkClass(ClassObject* clazz)
2505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 superclassIdx = 0;
2507c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    u4 *interfaceIdxArray = NULL;
2508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool okay = false;
2509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2511c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz != NULL);
2512c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->descriptor != NULL);
2513c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->status == CLASS_IDX || clazz->status == CLASS_LOADED);
2514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
251592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("CLASS: linking '%s'...", clazz->descriptor);
2516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2517c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(gDvm.classJavaLangClass != NULL);
2518dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(clazz->clazz == gDvm.classJavaLangClass);
2519dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro    assert(dvmIsClassObject(clazz));
2520c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (clazz->classLoader == NULL &&
2521c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        (strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
2522c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    {
2523c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (gDvm.classJavaLangClass->ifieldCount > CLASS_FIELD_SLOTS) {
2524c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("java.lang.Class has %d instance fields (expected at most %d)",
2525c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                 gDvm.classJavaLangClass->ifieldCount, CLASS_FIELD_SLOTS);
2526c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmAbort();
2527c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2528c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (gDvm.classJavaLangClass->sfieldCount != CLASS_SFIELD_SLOTS) {
2529c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("java.lang.Class has %d static fields (expected %d)",
2530c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                 gDvm.classJavaLangClass->sfieldCount, CLASS_SFIELD_SLOTS);
2531c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmAbort();
2532c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2533c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2534c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein
2535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "Resolve" the class.
2536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2537c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * At this point, clazz's reference fields may contain Dex file
2538c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * indices instead of direct object references.  Proxy objects are
2539c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * an exception, and may be the only exception.  We need to
2540c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * translate those indices into real references, and let the GC
2541c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * look inside this ClassObject.
2542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2543c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (clazz->status == CLASS_IDX) {
2544c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->interfaceCount > 0) {
2545c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            /* Copy u4 DEX idx values out of the ClassObject* array
2546c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes             * where we stashed them.
2547c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes             */
2548c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            assert(sizeof(*interfaceIdxArray) == sizeof(*clazz->interfaces));
2549c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            size_t len = clazz->interfaceCount * sizeof(*interfaceIdxArray);
2550fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            interfaceIdxArray = (u4*)malloc(len);
2551c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            if (interfaceIdxArray == NULL) {
2552e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                ALOGW("Unable to allocate memory to link %s", clazz->descriptor);
2553c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                goto bail;
25543595a09a6fff5483f69f0f714128646c17a03216Barry Hayes            }
2555c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            memcpy(interfaceIdxArray, clazz->interfaces, len);
25561145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden
25571145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden            dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2558c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            memset(clazz->interfaces, 0, len);
25591145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden            dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2560c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2561c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2562c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        assert(sizeof(superclassIdx) == sizeof(clazz->super));
2563c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        superclassIdx = (u4) clazz->super;
2564c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        clazz->super = NULL;
2565c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        /* After this line, clazz will be fair game for the GC. The
2566c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes         * superclass and interfaces are all NULL.
2567c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes         */
2568c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        clazz->status = CLASS_LOADED;
2569c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2570c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (superclassIdx != kDexNoIndex) {
2571364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            ClassObject* super = dvmResolveClass(clazz, superclassIdx, false);
2572364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            if (super == NULL) {
2573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(dvmThreadSelf()));
2574c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (gDvm.optimizing) {
2575c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    /* happens with "external" libs */
257692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                    ALOGV("Unable to resolve superclass of %s (%d)",
2577c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->descriptor, superclassIdx);
2578c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                } else {
2579e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                    ALOGW("Unable to resolve superclass of %s (%d)",
2580c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->descriptor, superclassIdx);
2581c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2584364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            dvmSetFieldObject((Object *)clazz,
2585dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro                              OFFSETOF_MEMBER(ClassObject, super),
2586364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                              (Object *)super);
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2589c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->interfaceCount > 0) {
2590c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            /* Resolve the interfaces implemented directly by this class. */
2591c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            assert(interfaceIdxArray != NULL);
2592c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2593c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            for (i = 0; i < clazz->interfaceCount; i++) {
2594c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                assert(interfaceIdxArray[i] != kDexNoIndex);
2595c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                clazz->interfaces[i] =
2596c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmResolveClass(clazz, interfaceIdxArray[i], false);
2597c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (clazz->interfaces[i] == NULL) {
2598c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2599c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2600c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    assert(dvmCheckException(dvmThreadSelf()));
2601c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2602c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2603c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    const char* classDescriptor;
2604c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    classDescriptor =
2605c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        dexStringByTypeIdx(pDexFile, interfaceIdxArray[i]);
2606c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    if (gDvm.optimizing) {
2607c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        /* happens with "external" libs */
260892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                        ALOGV("Failed resolving %s interface %d '%s'",
2609c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             clazz->descriptor, interfaceIdxArray[i],
2610c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             classDescriptor);
2611c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    } else {
26124308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block                        ALOGI("Failed resolving %s interface %d '%s'",
2613c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             clazz->descriptor, interfaceIdxArray[i],
2614c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             classDescriptor);
2615c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    }
2616c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    goto bail;
2617c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
2618c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2619c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                /* are we allowed to implement this interface? */
2620c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2621c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2622e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                    ALOGW("Interface '%s' is not accessible to '%s'",
2623c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->interfaces[i]->descriptor, clazz->descriptor);
2624d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                    dvmThrowIllegalAccessError("interface not accessible");
2625c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    goto bail;
2626c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
262760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGVV("+++  found interface '%s'",
2628c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                      clazz->interfaces[i]->descriptor);
2629c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            }
2630c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2631c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2632c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2634c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * There are now Class references visible to the GC in super and
2635c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * interfaces.
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2639c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * All classes have a direct superclass, except for
2640c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * java/lang/Object and primitive classes. Primitive classes are
2641c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * are created CLASS_INITIALIZED, so won't get here.
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2643c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->primitiveType == PRIM_NOT);
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
2645c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->super != NULL) {
2646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* TODO: is this invariant true for all java/lang/Objects,
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * regardless of the class loader?  For now, assume it is.
2648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
264970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowClassFormatError("java.lang.Object has a superclass");
2650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't finalize objects whose classes use the
2654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * default (empty) Object.finalize().
2655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2658c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->super == NULL) {
265970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowLinkageError("no superclass defined");
2660c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            goto bail;
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify */
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsFinalClass(clazz->super)) {
2664e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Superclass of '%s' is final '%s'",
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
266670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowIncompatibleClassChangeError("superclass is final");
2667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (dvmIsInterfaceClass(clazz->super)) {
2669e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Superclass of '%s' is interface '%s'",
2670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
267170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowIncompatibleClassChangeError("superclass is an interface");
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2674e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Superclass of '%s' (%s) is not accessible",
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2676d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            dvmThrowIllegalAccessError("superclass not accessible");
2677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Inherit finalizability from the superclass.  If this
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class also overrides finalize(), its CLASS_ISFINALIZABLE
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * bit will already be set.
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* See if this class descends from java.lang.Reference
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and set the class flags appropriately.
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 superRefFlags;
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We've already determined the reference type of this
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * inheritance chain.  Inherit reference-ness from the superclass.
2696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
27003475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro                    CLASS_ISFINALIZERREFERENCE |
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE);
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, superRefFlags);
2703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (clazz->classLoader == NULL &&
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->super->classLoader == NULL &&
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                strcmp(clazz->super->descriptor,
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/Reference;") == 0)
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 refFlags;
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This class extends Reference, which means it should
2711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * be one of the magic Soft/Weak/PhantomReference classes.
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            refFlags = CLASS_ISREFERENCE;
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (strcmp(clazz->descriptor,
2715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/SoftReference;") == 0)
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Only CLASS_ISREFERENCE is set for soft references.
2718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
2720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/WeakReference;") == 0)
2721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISWEAKREFERENCE;
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
27243475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro                       "Ljava/lang/ref/FinalizerReference;") == 0)
27253475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro            {
27263475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro                refFlags |= CLASS_ISFINALIZERREFERENCE;
27273475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro            }  else if (strcmp(clazz->descriptor,
2728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/PhantomReference;") == 0)
2729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISPHANTOMREFERENCE;
2731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* No-one else is allowed to inherit directly
2733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * from Reference.
2734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//xxx is this the right exception?  better than an assertion.
273670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein                dvmThrowLinkageError("illegal inheritance from Reference");
2737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* The class should not have any reference bits set yet.
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(GET_CLASS_FLAG_GROUP(clazz,
2743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
27453475f9cdb47a6d6f8ad2ce49bbc3af46bca92f09Carl Shapiro                    CLASS_ISFINALIZERREFERENCE |
2746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE) == 0);
2747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, refFlags);
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate vtable.
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz)) {
2756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no vtable; just set the method indices */
2757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2760c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Too many methods (%d) in interface '%s'", count,
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++)
2768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!createVtable(clazz)) {
2773e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("failed creating vtable");
2774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate interface method tables.  Can alter the vtable.
2780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!createIftable(clazz))
2782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Insert special-purpose "stub" method implementations.
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!insertMethodStubs(clazz))
2788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute instance field offsets and, hence, the size of the object.
2792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!computeFieldOffsets(clazz))
2794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2797c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein     * Cache field and method info for the class Reference (as loaded
2798c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein     * by the boot classloader). This has to happen after the call to
2799c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein     * computeFieldOffsets().
2800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2801c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein    if ((clazz->classLoader == NULL)
2802c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein            && (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0)) {
2803c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein        if (!precacheReferenceOffsets(clazz)) {
2804c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("failed pre-caching Reference offsets");
2805c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein            dvmThrowInternalError(NULL);
2806c399ea527d0d50c6e2b4ae15fc4a3e9a18f3f1f1Dan Bornstein            goto bail;
2807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
28116daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * Compact the offsets the GC has to examine into a bitmap, if
28126daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * possible.  (This has to happen after Reference.referent is
28136daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * massaged in precacheReferenceOffsets.)
28146daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     */
28156daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    computeRefOffsets(clazz);
28166daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
28176daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    /*
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Done!
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
2822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_RESOLVED;
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    okay = true;
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
282692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("CLASS: linked '%s'", clazz->descriptor);
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We send CLASS_PREPARE events to the debugger from here.  The
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * definition of "preparation" is creating the static fields for a
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class and initializing them to the standard default values, but not
2832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * executing any code (that comes later, during "initialization").
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We did the static prep in loadSFieldFromDex() while loading the class.
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been prepared and resolved but possibly not yet verified
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at this point.
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
28399a3147c7412f4794434b4c2604aa2ba784867774buzbee    if (gDvm.debuggerActive) {
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDbgPostClassPrepare(clazz);
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!okay) {
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
2846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckException(dvmThreadSelf())) {
284770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowVirtualMachineError(NULL);
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2850c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (interfaceIdxArray != NULL) {
2851c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        free(interfaceIdxArray);
2852c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2853c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein
2854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return okay;
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the virtual method table.
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the table is a copy of the table from our superclass,
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with our local methods overriding theirs.  The bottom part of the table
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has any new methods we defined.
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createVtable(ClassObject* clazz)
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int maxCount;
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
28714308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        //ALOGI("SUPER METHODS %d %s->%s", clazz->super->vtableCount,
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->super->descriptor);
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* the virtual methods we define, plus the superclass vtable size */
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    maxCount = clazz->virtualMethodCount;
2877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        maxCount += clazz->super->vtableCount;
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* TODO: is this invariant true for all java/lang/Objects,
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * regardless of the class loader?  For now, assume it is.
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2885062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    //ALOGD("+++ max vmethods for '%s' is %d", clazz->descriptor, maxCount);
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Over-allocate the table, then realloc it down if necessary.  So
2889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * long as we don't allocate anything in between we won't cause
2890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fragmentation, and reducing the size should be unlikely to cause
2891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a buffer copy.
2892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * maxCount);
2896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->vtable == NULL)
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int actualCount;
2901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->vtable, clazz->super->vtable,
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualCount = clazz->super->vtableCount;
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * See if any of our virtual methods override the superclass.
2908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
2910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* localMeth = &clazz->virtualMethods[i];
2911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int si;
2912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (si = 0; si < clazz->super->vtableCount; si++) {
2914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Method* superMeth = clazz->vtable[si];
2915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
2918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* verify */
2919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmIsFinalMethod(superMeth)) {
2920e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                        ALOGW("Method %s.%s overrides final %s.%s",
2921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            localMeth->clazz->descriptor, localMeth->name,
2922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            superMeth->clazz->descriptor, superMeth->name);
2923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
2924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtable[si] = localMeth;
2926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    localMeth->methodIndex = (u2) si;
292792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                    //ALOGV("+++   override %s.%s (slot %d)",
2928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    clazz->descriptor, localMeth->name, si);
2929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (si == clazz->super->vtableCount) {
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* not an override, add to end */
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[actualCount] = localMeth;
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                localMeth->methodIndex = (u2) actualCount;
2937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                actualCount++;
2938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                //ALOGV("+++   add method %s.%s",
2940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //    clazz->descriptor, localMeth->name);
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount != (u2) actualCount) {
2945c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Too many methods (%d) in class '%s'", actualCount,
2946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(actualCount <= maxCount);
2951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount < maxCount) {
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->vtable != NULL);
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2955fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            clazz->vtable = (Method **)dvmLinearRealloc(clazz->classLoader,
2956fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                clazz->vtable, sizeof(*(clazz->vtable)) * actualCount);
2957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz->vtable == NULL) {
2958c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("vtable realloc failed");
2959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
296160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGVV("+++  reduced vtable from %d to %d",
2962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    maxCount, actualCount);
2963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = actualCount;
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* java/lang/Object case */
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2971c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Too many methods (%d) in base class '%s'", count,
2972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[i] = &clazz->virtualMethods[i];
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = clazz->virtualMethodCount;
2981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
2984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and populate "iftable".
2993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The set of interfaces we support is the combination of the interfaces
2995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we implement directly and those implemented by our superclass.  Each
2996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interface can have one or more "superinterfaces", which we must also
2997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * support.  For speed we flatten the tree out.
2998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to speed this up when there are lots of interfaces
3000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by merge-sorting the class pointers and binary-searching when removing
3001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * duplicates.  We could also drop the duplicate removal -- it's only
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there to reduce the memory footprint.
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createIftable(ClassObject* clazz)
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIftable = false;
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapVtable = false;
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIfvipool = false;
3014dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int poolOffset = 0, poolSize = 0;
3015dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    Method** mirandaList = NULL;
3016dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int mirandaCount = 0, mirandaAlloc = 0;
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3018dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int superIfCount;
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = clazz->super->iftableCount;
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = 0;
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3024dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int ifCount = superIfCount;
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifCount += clazz->interfaceCount;
3026dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    for (int i = 0; i < clazz->interfaceCount; i++)
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ifCount += clazz->interfaces[i]->iftableCount;
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d",
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ifCount == 0) {
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftableCount == 0);
3034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftable == NULL);
3035dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        return true;
3036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a table with enough space for all interfaces, and copy the
3040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass' table in.
3041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
3043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(InterfaceEntry) * ifCount);
3044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIftable = true;
3045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
3046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (superIfCount != 0) {
3047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->iftable, clazz->super->iftable,
3048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(InterfaceEntry) * superIfCount);
3049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a flattened interface hierarchy of our immediate interfaces.
3053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3054dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int idx = superIfCount;
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3056dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    for (int i = 0; i < clazz->interfaceCount; i++) {
3057dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        ClassObject* interf = clazz->interfaces[i];
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(interf != NULL);
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure this is still an interface class */
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsInterfaceClass(interf)) {
3062e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Class '%s' implements non-interface '%s'",
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, interf->descriptor);
306470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowIncompatibleClassChangeErrorWithClassMessage(
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entry for this interface */
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[idx++].clazz = interf;
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entries for the interface's superinterfaces */
3073dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        for (int j = 0; j < interf->iftableCount; j++) {
3074d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            int k;
3075d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            ClassObject *cand;
3076d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph
3077d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            cand = interf->iftable[j].clazz;
3078d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph
3079d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            /*
3080d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * Check if this interface was already added and add only if new.
3081d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * This is to avoid a potential blowup in the number of
3082d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * interfaces for sufficiently complicated interface hierarchies.
3083d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * This has quadratic runtime in the number of interfaces.
3084d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * However, in common cases with little interface inheritance, this
3085d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             * doesn't make much of a difference.
3086d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph             */
3087d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            for (k = 0; k < idx; k++)
3088d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph                if (clazz->iftable[k].clazz == cand)
3089d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph                    break;
3090d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph
3091d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            if (k == idx)
3092d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph                clazz->iftable[idx++].clazz = cand;
3093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3096d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph    assert(idx <= ifCount);
3097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3098d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph    /*
3099d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph     * Adjust the ifCount. We could reallocate the interface memory here,
3100d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph     * but it's probably not worth the effort, the important thing here
3101d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph     * is to avoid the interface blowup and keep the ifCount low.
3102d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph     */
3103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
3104d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph        if (idx != ifCount) {
3105d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            int newIfCount = idx;
3106d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            InterfaceEntry* oldmem = clazz->iftable;
3107d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph
3108d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
3109d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph                            sizeof(InterfaceEntry) * newIfCount);
3110d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            memcpy(clazz->iftable, oldmem, sizeof(InterfaceEntry) * newIfCount);
3111d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph            dvmLinearFree(clazz->classLoader, oldmem);
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3113d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph    }
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3115d8a81cfd749c629de84db32eee3703cc5e0dc28fJohannes Rudolph    ifCount = idx;
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = ifCount;
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we're an interface, we don't need the vtable pointers, so
3120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're done.  If this class doesn't implement an interface that our
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass doesn't have, then we again have nothing to do.
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //dvmDumpClass(clazz, kDumpClassFullDetail);
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * When we're handling invokeinterface, we probably have an object
3131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * whose type is an interface class rather than a concrete class.  We
3132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * need to convert the method reference into a vtable index.  So, for
3133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * every entry in "iftable", we create a list of vtable indices.
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Because our vtable encompasses the superclass vtable, we can use
3136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the vtable indices from our superclass for all of the interfaces
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that weren't directly implemented by us.
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Each entry in "iftable" has a pointer to the start of its set of
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * vtable offsets.  The iftable entries in the superclass point to
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * storage allocated in the superclass, and the iftable entries added
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for this class point to storage allocated in this class.  "iftable"
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is flat for fast access in a class and all of its subclasses, but
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "ifviPool" is only created for the topmost implementor.
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3146dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    for (int i = superIfCount; i < ifCount; i++) {
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note it's valid for an interface to have no methods (e.g.
3149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * java/io/Serializable).
3150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
315160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("INTF: pool: %d from %s",
3152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->virtualMethodCount,
3153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->descriptor);
3154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (poolSize == 0) {
315860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("INTF: didn't find any new interfaces with methods");
3159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
3160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
3161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = poolSize;
3164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        poolSize * sizeof(int*));
3166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIfvipool = true;
3167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Fill in the vtable offsets for the interfaces that weren't part of
3170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our superclass.
3171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3172dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    for (int i = superIfCount; i < ifCount; i++) {
3173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* interface;
3174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int methIdx;
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        interface = clazz->iftable[i].clazz;
3178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolOffset += interface->virtualMethodCount;    // end here
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * For each method listed in the interface's method list, find the
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matching method in our class's method list.  We want to favor the
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass over the superclass, which just requires walking
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * back from the end of the vtable.  (This only matters if the
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass defines a private method and this class redefines
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it -- otherwise it would use the same vtable slot.  In Dalvik
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * those don't end up in the virtual method table, so it shouldn't
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matter which direction we go.  We walk it backward anyway.)
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Suppose we have the following arrangement:
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public interface MyInterface
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface();
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public abstract class MirandaAbstract implements MirandaInterface
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     //public abstract boolean inInterface(); // not declared!
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public class MirandClass extends MirandaAbstract
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface() { stuff }
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The javac compiler happily compiles MirandaAbstract even though
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it doesn't declare all methods from its interface.  When we try
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to set up a vtable for MirandaAbstract, we find that we don't
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have an slot for inInterface.  To prevent this, we synthesize
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * abstract method declarations in MirandaAbstract.
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We have to expand vtable and update some things that point at it,
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so we accumulate the method list and do it all at once below.
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* imeth = &interface->virtualMethods[methIdx];
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            IF_LOGVV() {
3215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
321660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGVV("INTF:  matching '%s' '%s'", imeth->name, desc);
3217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(desc);
3218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = clazz->vtableCount-1; j >= 0; j--) {
3221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    == 0)
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
322460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                    LOGVV("INTF:   matched at %d", j);
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsPublicMethod(clazz->vtable[j])) {
3226e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                        ALOGW("Implementation of %s.%s is not public",
3227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            clazz->descriptor, clazz->vtable[j]->name);
3228d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                        dvmThrowIllegalAccessError(
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "interface implementation not public");
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->iftable[i].methodIndexArray[methIdx] = j;
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (j < 0) {
323792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                IF_ALOGV() {
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    char* desc =
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dexProtoCopyMethodDescriptor(&imeth->prototype);
324092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                    ALOGV("No match for '%s' '%s' in '%s' (creating miranda)",
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            imeth->name, desc, clazz->descriptor);
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(desc);
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3244d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                //dvmThrowRuntimeException("Miranda!");
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //return false;
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mirandaCount == mirandaAlloc) {
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaAlloc += 8;
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (mirandaList == NULL) {
3250fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                        mirandaList = (Method**)dvmLinearAlloc(
3251fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                                        clazz->classLoader,
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        mirandaAlloc * sizeof(Method*));
3253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3255fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                        mirandaList = (Method**)dvmLinearRealloc(
3256fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                                clazz->classLoader,
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList, mirandaAlloc * sizeof(Method*));
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(mirandaList != NULL);    // mem failed + we leaked
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * These may be redundant (e.g. method with same name and
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * signature declared in two interfaces implemented by the
3265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * same abstract class).  We can squeeze the duplicates
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * out here.
3267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int mir;
3269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (mir = 0; mir < mirandaCount; mir++) {
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmCompareMethodNamesAndProtos(
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            mirandaList[mir], imeth) == 0)
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    {
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        IF_LOGVV() {
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            char* desc = dexProtoCopyMethodDescriptor(
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    &imeth->prototype);
327660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                            LOGVV("MIRANDA dupe: %s and %s %s%s",
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList[mir]->clazz->descriptor,
3278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->clazz->descriptor,
3279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->name, desc);
3280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            free(desc);
3281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
3282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* point the iftable at a phantom slot index */
3287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->iftable[i].methodIndexArray[methIdx] =
3288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtableCount + mir;
328960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGVV("MIRANDA: %s points at slot %d",
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    imeth->name, clazz->vtableCount + mir);
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if non-duplicate among Mirandas, add to Miranda list */
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mir == mirandaCount) {
329492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                    //ALOGV("MIRANDA: holding '%s' in slot %d",
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    imeth->name, mir);
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaList[mirandaCount++] = imeth;
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mirandaCount != 0) {
330368825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        static const int kManyMirandas = 150;   /* arbitrary */
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* newVirtualMethods;
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int oldMethodCount, oldVtableCount;
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3308dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        for (int i = 0; i < mirandaCount; i++) {
330960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("MIRANDA %d: %s.%s", i,
3310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
331268825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        if (mirandaCount > kManyMirandas) {
331368825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden            /*
331468825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * Some obfuscators like to create an interface with a huge
331568825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * pile of methods, declare classes as implementing it, and then
331668825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * only define a couple of methods.  This leads to a rather
331768825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * massive collection of Miranda methods and a lot of wasted
331868825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * space, sometimes enough to blow out the LinearAlloc cap.
331968825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             */
3320062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Note: class %s has %d unimplemented (abstract) methods",
332168825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden                clazz->descriptor, mirandaCount);
332268825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        }
3323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We found methods in one or more interfaces for which we do not
3326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have vtable entries.  We have to expand our virtualMethods
3327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * table (which might be empty) to hold some new entries.
3328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->virtualMethods == NULL) {
3330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods,
3336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newVirtualMethods != clazz->virtualMethods) {
3339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Table was moved in memory.  We have to run through the
3341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * vtable and fix the pointers.  The vtable entries might be
3342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * pointing at superclasses, so we flip it around: run through
3343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * all locally-defined virtual methods, and fix their entries
3344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in the vtable.  (This would get really messy if sub-classes
3345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * had already been loaded.)
3346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * hold the virtual methods declared by this class.  The
3349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method's methodIndex is the vtable index, and is the same
3350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * for all sub-classes (and all super classes in which it is
3351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * defined).  We're messing with these because the Miranda
3352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * stuff makes it look like the class actually has an abstract
3353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method declaration in it.
3354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
335560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("MIRANDA fixing vtable pointers");
3356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* meth = newVirtualMethods;
3358dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro            for (int i = 0; i < clazz->virtualMethodCount; i++, meth++)
3359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[meth->methodIndex] = meth;
3360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldMethodCount = clazz->virtualMethodCount;
3364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = newVirtualMethods;
3365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount += mirandaCount;
3366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We also have to expand the vtable.
3371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtable != NULL);
3373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable,
3375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->vtable == NULL) {
3377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zapVtable = true;
3381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldVtableCount = clazz->vtableCount;
3383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount += mirandaCount;
3384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Now we need to create the fake methods.  We clone the abstract
3387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method definition from the interface and then replace a few
3388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * things.
338968825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         *
339068825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         * The Method will be an "abstract native", with nativeFunc set to
339168825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         * dvmAbstractMethodStub().
3392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = clazz->virtualMethods + oldMethodCount;
3394dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro        for (int i = 0; i < mirandaCount; i++, meth++) {
3395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cloneMethod(meth, mirandaList[i]);
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->clazz = clazz;
3398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_MIRANDA;
3399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->methodIndex = (u2) (oldVtableCount + i);
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* point the new vtable entry at the new method */
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[oldVtableCount + i] = meth;
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, mirandaList);
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO?
3413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sort the interfaces by number of declared methods.  All we really
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want is to get the interfaces with zero methods at the end of the
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * list, so that when we walk through the list during invoke-interface
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we don't examine interfaces that can't possibly be useful.
3417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The set will usually be small, so a simple insertion sort works.
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to be careful not to change the order of two interfaces
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that define the same method.  (Not a problem if we only move the
3422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * zero-method interfaces to the end.)
3423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * PROBLEM:
3425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we do this, we will no longer be able to identify super vs.
3426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * current class interfaces by comparing clazz->super->iftableCount.  This
3427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * breaks anything that only wants to find interfaces declared directly
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmDbgOutputAllInterfaces, etc).  Need to provide a workaround.
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can sort just the interfaces implemented directly by this class,
3432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but that doesn't seem like it would provide much of an advantage.  I'm
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not sure this is worthwhile.
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This has been made largely obsolete by the interface cache mechanism.)
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpClass(clazz);
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIftable)
3444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapVtable)
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIfvipool)
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Provide "stub" implementations for methods without them.
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently we provide an implementation for all abstract methods that
3457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throws an AbstractMethodError exception.  This allows us to avoid an
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * explicit check for abstract methods in every virtual call.
3459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: for Miranda methods, the method declaration is a clone of what
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * was found in the interface class.  That copy may already have had the
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * function pointer filled in, so don't be surprised if it's not NULL.
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which is nonsensical.  Need to make sure that this doesn't escape the
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM.  We can either mask it out in reflection calls, or copy "native"
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the high 16 bits of accessFlags and check that internally.
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool insertMethodStubs(ClassObject* clazz)
3470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth;
3474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = clazz->virtualMethods;
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(meth)) {
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->insns == NULL);
3480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->nativeFunc == NULL ||
3481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_NATIVE;
3484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Swap two instance fields.
3495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void swapField(InstField* pOne, InstField* pTwo)
3497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    InstField swap;
3499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("  --- swap '%s' and '%s'", pOne->name, pTwo->name);
3501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    swap = *pOne;
3502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pOne = *pTwo;
3503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pTwo = swap;
3504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assign instance fields to u4 slots.
3508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top portion of the instance field area is occupied by the superclass
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields, the bottom by the fields for this class.
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "long" and "double" fields occupy two adjacent slots.  On some
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * arrange fields (or introduce padding) to ensure this.  We assume the
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can just ensure that the offset is "even".  To avoid wasting space,
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we want to move non-reference 32-bit fields into gaps rather than
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creating pad words.
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the worst case we will waste 4 bytes, but because objects are
3521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (assuming this is the most-derived class).
3523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pad words are not represented in the field table, so the field table
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * itself does not change size.
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The number of field slots determines the size of the object, so we
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set that here too.
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This function feels a little more complicated than I'd like, but it
3531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has the property of moving the smallest possible set of fields, which
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should reduce the time required to load a class.
3533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will break.
3536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool computeFieldOffsets(ClassObject* clazz)
3538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int fieldOffset;
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset = clazz->super->objectSize;
3546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
35477cc095f8e3ec52ba94d91e1d327354f61236496aCarl Shapiro        fieldOffset = OFFSETOF_MEMBER(DataObject, instanceData);
3548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
354960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("--- computeFieldOffsets '%s'", clazz->descriptor);
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35514308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("OFFSETS fieldCount=%d", clazz->ifieldCount);
35524308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("dataobj, instance: %d", offsetof(DataObject, instanceData));
35534308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("classobj, access: %d", offsetof(ClassObject, accessFlags));
35544308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    //ALOGI("super=%p, fieldOffset=%d", clazz->super, fieldOffset);
3555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start by moving all reference fields to the front.
3558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldRefCount = 0;
3560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3563a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        char c = pField->signature[0];
3564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a reference field; see if any reference fields
3567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* refField = &clazz->ifields[j--];
3572a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                char rc = refField->signature[0];
3573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == '[' || rc == 'L') {
3575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a reference field that follows at least one
3576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-reference field.  Swap it with the current field.
3577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "refField" points to the non-ref field.)
3579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, refField);
3581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Fix the signature.
3583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->ifieldRefCount++;
3587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a reference field.
3594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount++;
3596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we've hit the end of the reference fields, break.
3600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L')
3602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
3605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
360660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("  --- offset1 '%s'=%d", pField->name,pField->byteOffset);
3607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Now we want to pack all of the double-wide fields together.  If we're
3611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not aligned, though, we want to shuffle one 32-bit field into place.
3612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we can't find one, we'll have to pad it.
3613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
361560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("  +++ not aligned");
3616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3618a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        char c = pField->signature[0];
3619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'J' && c != 'D') {
3621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The field that comes next is 32-bit, so just advance past it.
3623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(c != '[' && c != 'L');
3625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pField->byteOffset = fieldOffset;
3626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i++;
362860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGVV("  --- offset2 '%s'=%d",
3629a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                pField->name, pField->byteOffset);
3630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Next field is 64-bit, so search for a 32-bit field we can
3633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swap into it.
3634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool found = false;
3636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            j = clazz->ifieldCount - 1;
3637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* singleField = &clazz->ifields[j--];
3639a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                char rc = singleField->signature[0];
3640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc != 'J' && rc != 'D') {
3642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, singleField);
3643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //c = rc;
364460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                    LOGVV("  +++ swapped '%s' for alignment",
3645a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                        pField->name);
3646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pField->byteOffset = fieldOffset;
3647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fieldOffset += sizeof(u4);
364860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                    LOGVV("  --- offset3 '%s'=%d",
3649a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                        pField->name, pField->byteOffset);
3650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
3651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i++;
3652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!found) {
365692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block                ALOGV("  +++ inserting pad field in '%s'", clazz->descriptor);
3657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fieldOffset += sizeof(u4);
3658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Alignment is good, shuffle any double-wide fields forward, and
3664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finish assigning field offsets to all fields.
3665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for ( ; i < clazz->ifieldCount; i++) {
3669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3670a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        char c = pField->signature[0];
3671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'D' && c != 'J') {
3673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a double-wide field; see if any double fields
3674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* doubleField = &clazz->ifields[j--];
3679a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                char rc = doubleField->signature[0];
3680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == 'D' || rc == 'J') {
3682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a double-wide field that follows at least one
3683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-double field.  Swap it with the current field.
3684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "doubleField" points to the non-double field.)
3686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, doubleField);
3688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a double-wide field, leave it be.
3697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
370160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("  --- offset4 '%s'=%d", pField->name,pField->byteOffset);
3702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
3703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'J' || c == 'D')
3704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure that all reference fields appear before
3709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * non-reference fields, and all double-wide fields are aligned.
3710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = 0;  // seen non-ref
3712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
3714a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        char c = pField->signature[0];
3715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'D' || c == 'J') {
3717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((pField->byteOffset & 0x07) == 0);
3718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!j) {
3722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(i == clazz->ifieldRefCount);
3723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                j = 1;
3724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (j) {
3726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!j) {
3730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->ifieldRefCount == clazz->ifieldCount);
3731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We map a C struct directly on top of java/lang/Class objects.  Make
3736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sure we left enough room for the instance fields.
3737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3738c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein    assert(!dvmIsTheClassClass(clazz) || (size_t)fieldOffset <
3739dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro        OFFSETOF_MEMBER(ClassObject, instanceData) + sizeof(clazz->instanceData));
3740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->objectSize = fieldOffset;
3742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class failed to initialize on a previous attempt, so we want to throw
3749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
3750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * failed in verification, in which case v2 5.4.1 says we need to re-throw
3751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the previous error.
3752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwEarlierClassFailure(ClassObject* clazz)
3754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
37554308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("Rejecting re-init on previously-failed class %s v=%p",
3756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->verifyErrorClass);
3757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->verifyErrorClass == NULL) {
3759d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNoClassDefFoundError(clazz->descriptor);
3760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
37610b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein        dvmThrowExceptionWithClassMessage(clazz->verifyErrorClass,
3762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor);
3763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize any static fields whose values are stored in
3768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the DEX file.  This must be done during class initialization.
3769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void initSFields(ClassObject* clazz)
3771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile;
3774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef;
3775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexEncodedArray* pValueList;
3776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EncodedArrayIterator iterator;
3777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount == 0) {
3780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->pDvmDex == NULL) {
3783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* generated class; any static fields should already be set up */
378492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Not initializing static fields in %s", clazz->descriptor);
3785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = clazz->pDvmDex->pDexFile;
3788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pClassDef != NULL);
3791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pValueList == NULL) {
3794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Iterate over the initial values array, setting the corresponding
3801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * static field for each array element.
3802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AnnotationValue value;
3806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StaticField* sfield = &clazz->sfields[i];
3808a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro        const char* descriptor = sfield->signature;
3809364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        bool isObj = false;
3810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! parsed) {
3812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: Eventually verification should attempt to ensure
3814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that this can't happen at least due to a data integrity
3815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * problem.
3816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3817c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Static initializer parse failed for %s at index %d",
3818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->descriptor, i);
3819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Verify that the value we got was of a valid type. */
3823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (descriptor[0]) {
3825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'B': parsed = (value.type == kDexAnnotationByte);    break;
3827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'C': parsed = (value.type == kDexAnnotationChar);    break;
3828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'S': parsed = (value.type == kDexAnnotationShort);   break;
3829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'I': parsed = (value.type == kDexAnnotationInt);     break;
3830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J': parsed = (value.type == kDexAnnotationLong);    break;
3831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': parsed = (value.type == kDexAnnotationFloat);   break;
3832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': parsed = (value.type == kDexAnnotationDouble);  break;
3833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '[': parsed = (value.type == kDexAnnotationNull);    break;
3834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'L': {
3835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                switch (value.type) {
3836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationNull: {
3837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /* No need for further tests. */
3838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationString: {
3841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/String;") == 0);
3843364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                        isObj = true;
3844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationType: {
3847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3849364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                        isObj = true;
3850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    default: {
3853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed = false;
3854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
3860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                parsed = false;
3861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parsed) {
3866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3867364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes             * All's well, so store the value.
3868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3869364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            if (isObj) {
3870fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmSetStaticFieldObject(sfield, (Object*)value.value.l);
3871fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmReleaseTrackedAlloc((Object*)value.value.l, self);
3872364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            } else {
3873364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                /*
3874364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * Note: This always stores the full width of a
3875364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * JValue, even though most of the time only the first
3876364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * word is needed.
3877364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 */
3878364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                sfield->value = value.value;
3879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Something up above had a problem. TODO: See comment
3883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * above the switch about verfication.
3884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3885c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Bogus static initialization: value type %d in field type "
3886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "%s for %s at index %d",
3887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value.type, descriptor, clazz->descriptor, i);
3888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
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 * Determine whether "descriptor" yields the same class object in the
3896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of clazz1 and clazz2.
3897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must hold gDvm.loadedClasses.
3899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if they match.
3901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool compareDescriptorClasses(const char* descriptor,
3903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
3904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result1;
3906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result2;
3907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do the first lookup by name.
3910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can skip a second lookup by name if the second class loader is
3915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the initiating loader list of the class object we retrieved.
3916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This means that somebody already did a lookup of this class through
3917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the second loader, and it resolved to the same class.)  If it's not
3918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * there, we may simply not have had an opportunity to add it yet, so
3919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we do the full lookup.
3920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The initiating loader test should catch the majority of cases
3922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (in particular, the zillions of references to String/Object).
3923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For this to work, the superclass/interface should be the first
3927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * argument, so that way if it's from the bootstrap loader this test
3928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will work.  (The bootstrap loader, by definition, never shows up
3929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * as the initiating loader of a class defined by some other loader.)
3930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
3932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
3934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isInit) {
3936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
3940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result1 == NULL || result2 == NULL) {
3948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(dvmThreadSelf());
3949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result1 == result2) {
3950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Neither class loader could find this class.  Apparently it
3952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * doesn't exist.
3953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can either throw some sort of exception now, or just
3955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * assume that it'll fail later when something actually tries
3956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to use the class.  For strict handling we should throw now,
3957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * because a "tricky" class loader could start returning
3958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * something later, and a pair of "tricky" loaders could set
3959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * us up for confusion.
3960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * I'm not sure if we're allowed to complain about nonexistent
3962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes in method signatures during class init, so for now
3963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * this will just return "true" and let nature take its course.
3964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
3966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* only one was found, so clearly they're not the same */
3968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
3969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result1 == result2;
3973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For every component in the method descriptor, resolve the class in the
3977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of the two classes and compare the results.
3978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For best results, the "superclass" class should be first.
3980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the classes match, "false" otherwise.
3982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkMethodDescriptorClasses(const Method* meth,
3984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
3985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexParameterIterator iterator;
3987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
3988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* walk through the list of parameters */
3990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexParameterIteratorInit(&iterator, &meth->prototype);
3991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
3992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor = dexParameterIteratorNextDescriptor(&iterator);
3993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor == NULL)
3995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor[0] == 'L' || descriptor[0] == '[') {
3998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* non-primitive type */
3999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
4001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check the return type */
4005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexProtoGetReturnType(&meth->prototype);
4006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (descriptor[0] == 'L' || descriptor[0] == '[') {
4007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
4009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
4011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validate the descriptors in the superclass and interfaces.
4015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * What we need to do is ensure that the classes named in the method
4017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptors in our ancestors and ourselves resolve to the same class
4018cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * objects.  We can get conflicts when the classes come from different
4019cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * class loaders, and the resolver comes up with different results for
4020cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * the same class name in different contexts.
4021cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4022cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * An easy way to cause the problem is to declare a base class that uses
4023cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * class Foo in a method signature (e.g. as the return type).  Then,
4024cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * define a subclass and a different version of Foo, and load them from a
4025cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * different class loader.  If the subclass overrides the method, it will
4026cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * have a different concept of what Foo is than its parent does, so even
4027cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * though the method signature strings are identical, they actually mean
4028cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * different things.
4029cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4030cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * A call to the method through a base-class reference would be treated
4031cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * differently than a call to the method through a subclass reference, which
4032cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * isn't the way polymorphism works, so we have to reject the subclass.
4033cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * If the subclass doesn't override the base method, then there's no
4034cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * problem, because calls through base-class references and subclass
4035cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * references end up in the same place.
4036cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4037cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * We don't need to check to see if an interface's methods match with its
4038cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * superinterface's methods, because you can't instantiate an interface
4039cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and do something inappropriate with it.  If interface I1 extends I2
4040cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and is implemented by C, and I1 and I2 are in separate class loaders
4041cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and have conflicting views of other classes, we will catch the conflict
4042cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * when we process C.  Anything that implements I1 is doomed to failure,
4043cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * but we don't need to catch that while processing I1.
4044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
4046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool validateSuperDescriptors(const ClassObject* clazz)
4048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz))
4052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
4053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start with the superclass-declared methods.
4056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL &&
4058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->classLoader != clazz->super->classLoader)
4059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
4060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4061cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * Walk through every overridden method and compare resolved
4062cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * descriptor components.  We pull the Method structs out of
4063cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * the vtable.  It doesn't matter whether we get the struct from
4064cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * the parent or child, since we just need the UTF-8 descriptor,
4065cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * which must match.
4066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
4067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to do this even for the stuff inherited from Object,
4068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because it's possible that the new class loader has redefined
4069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a basic class like String.
4070e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         *
4071e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         * We don't need to check stuff defined in a superclass because
4072e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         * it was checked when the superclass was loaded.
4073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;
4075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("Checking %s %p vs %s %p\n",
4077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->classLoader,
4078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->super->descriptor, clazz->super->classLoader);
4079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth = clazz->vtable[i];
4081cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden            if (meth != clazz->super->vtable[i] &&
4082cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden                !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4083cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden            {
4084e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                ALOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)",
4085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->name, clazz->descriptor, clazz->classLoader,
4086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->super->descriptor, clazz->super->classLoader);
408770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein                dvmThrowLinkageError(
4088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Classes resolve differently in superclass");
4089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
4090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4095e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * Check the methods defined by this class against the interfaces it
4096e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * implements.  If we inherited the implementation from a superclass,
4097e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * we have to check it against the superclass (which might be in a
4098e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * different class loader).  If the superclass also implements the
4099e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * interface, we could skip the check since by definition it was
4100e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * performed when the class was loaded.
4101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->iftableCount; i++) {
4103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const InterfaceEntry* iftable = &clazz->iftable[i];
4104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->classLoader != iftable->clazz->classLoader) {
4106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ClassObject* iface = iftable->clazz;
4107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
4108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = 0; j < iface->virtualMethodCount; j++) {
4110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const Method* meth;
4111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int vtableIndex;
4112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vtableIndex = iftable->methodIndexArray[j];
4114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth = clazz->vtable[vtableIndex];
4115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4116e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden                if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
4117e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                    ALOGW("Method mismatch: %s in %s (cl=%p) and "
41186f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein                            "iface %s (cl=%p)",
4119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->name, clazz->descriptor, clazz->classLoader,
4120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        iface->descriptor, iface->classLoader);
412170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein                    dvmThrowLinkageError(
4122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Classes resolve differently in interface");
4123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
4124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
4130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the class is being initialized by us (which means that
4134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calling dvmInitClass will return immediately after fiddling with locks).
413510cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * Returns false if it's not being initialized, or if it's being
413610cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * initialized by another thread.
4137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
413810cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * The value for initThreadId is always set to "self->threadId", by the
413910cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * thread doing the initializing.  If it was done by the current thread,
414010cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * we are guaranteed to see "initializing" and our thread ID, even on SMP.
414110cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * If it was done by another thread, the only bad situation is one in
414210cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * which we see "initializing" and a stale copy of our own thread ID
414310cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * while another thread is actually handling init.
414410cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden *
414510cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * The initThreadId field is used during class linking, so it *is*
414610cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * possible to have a stale value floating around.  We need to ensure
414710cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * that memory accesses happen in the correct order.
4148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsClassInitializing(const ClassObject* clazz)
4150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4151dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    const int32_t* addr = (const int32_t*)(const void*)&clazz->status;
4152dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    int32_t value = android_atomic_acquire_load(addr);
4153dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    ClassStatus status = static_cast<ClassStatus>(value);
415410cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    return (status == CLASS_INITIALIZING &&
4155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId == dvmThreadSelf()->threadId);
4156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If a class has not been initialized, do so by executing the code in
4160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <clinit>.  The sequence is described in the VM spec v2 2.17.5.
4161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible for multiple threads to arrive here simultaneously, so
4163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to lock the class while we check stuff.  We know that no
4164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code has access to the class yet, so we can use the class's
4165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor lock.
4166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We will often be called recursively, e.g. when the <clinit> code resolves
4168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of its fields, the field resolution will try to initialize the class.
416977514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * In that case we will return "true" even though the class isn't actually
417077514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * ready to go.  The ambiguity can be resolved with dvmIsClassInitializing().
417177514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * (TODO: consider having this return an enum to avoid the extra call --
417277514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * return -1 on failure, 0 on success, 1 on still-initializing.  Looks like
417377514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * dvmIsClassInitializing() is always paired with *Initialized())
4174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can get very interesting if a class has a static field initialized
4176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to a new instance of itself.  <clinit> will end up calling <init> on
4177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the members it is initializing, which is fine unless it uses the contents
4178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of static fields to initialize instance fields.  This will leave the
4179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * static-referenced objects in a partially initialized state.  This is
4180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reasonably rare and can sometimes be cured with proper field ordering.
4181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, returns "false" with an exception raised.
4183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -----
4185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible to cause a deadlock by having a situation like this:
4187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class A { static { sleep(10000); new B(); } }
4188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class B { static { sleep(10000); new A(); } }
4189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new A(); } }.start();
4190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new B(); } }.start();
4191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This appears to be expected under the spec.
4192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The interesting question is what to do if somebody calls Thread.interrupt()
4194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on one of the deadlocked threads.  According to the VM spec, they're both
4195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sitting in "wait".  Should the interrupt code quietly raise the
4196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "interrupted" flag, or should the "wait" return immediately with an
4197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception raised?
4198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This gets a little murky.  The VM spec says we call "wait", and the
4200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec for Thread.interrupt says Object.wait is interruptible.  So it
4201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * seems that, if we get unlucky and interrupt class initialization, we
4202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are expected to throw (which gets converted to ExceptionInInitializerError
4203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * since InterruptedException is checked).
4204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are a couple of problems here.  First, all threads are expected to
4206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * present a consistent view of class initialization, so we can't have it
4207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fail in one thread and succeed in another.  Second, once a class fails
4208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to initialize, it must *always* fail.  This means that a stray interrupt()
4209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call could render a class unusable for the lifetime of the VM.
4210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In most cases -- the deadlock example above being a counter-example --
4212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interrupting thread can't tell whether the target thread handled
4213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization itself or had to wait while another thread did the
4214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work.  Refusing to interrupt class initialization is, in most cases,
4215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not something that a program can reliably detect.
4216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On the assumption that interrupting class initialization is highly
4218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * undesirable in most circumstances, and that failing to do so does not
4219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deviate from the spec in a meaningful way, we don't allow class init
4220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to be interrupted by Thread.interrupt().
4221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitClass(ClassObject* clazz)
4223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4224dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    u8 startWhen = 0;
4225dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro
4226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool initializedByUs = false;
4228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
4231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* method;
4232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockObject(self, (Object*) clazz);
4234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the class hasn't been verified yet, do so now.
4238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status < CLASS_VERIFIED) {
4240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we're in an "erroneous" state, throw an exception and bail.
4242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
4245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_RESOLVED);
4249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             clazz->classLoader == NULL))
4254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4255d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            /* advance to "verified" state */
425692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("+++ not verifying class %s (cl=%p)",
4257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->classLoader);
4258d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            clazz->status = CLASS_VERIFIED;
4259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto noverify;
4260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!gDvm.optimizing)
426392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            ALOGV("+++ late verify on %s", clazz->descriptor);
4264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're not supposed to optimize an unverified class, but during
4267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * development this mode was useful.  We can't verify an optimized
4268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class because the optimization process discards information.
4269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4271e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Class '%s' was optimized without verification; "
42726f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein                 "not verifying now",
4273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4274e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("  ('rm /data/dalvik-cache/*' and restart to fix this)");
4275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto verify_failed;
4276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFYING;
4279228a6b01918304f2cd1213c722e028a6e25252bbAndy McFadden        if (!dvmVerifyClass(clazz)) {
4280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverify_failed:
428185ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein            dvmThrowVerifyError(clazz->descriptor);
4282fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden            dvmSetFieldObject((Object*) clazz,
4283dc2a1881fe75a8dd961fb24509621c7c97694c9aCarl Shapiro                OFFSETOF_MEMBER(ClassObject, verifyErrorClass),
4284fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden                (Object*) dvmGetException(self)->clazz);
4285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
4290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnoverify:
4292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4293fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    /*
4294fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * We need to ensure that certain instructions, notably accesses to
4295fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * volatile fields, are replaced before any code is executed.  This
4296fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * must happen even if DEX optimizations are disabled.
4297ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     *
4298ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * The only exception to this rule is that we don't want to do this
4299ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * during dexopt.  We don't generally initialize classes at all
4300ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * during dexopt, but because we're loading classes we need Class and
4301ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * Object (and possibly some Throwable stuff if a class isn't found).
4302ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * If optimizations are disabled, we don't want to output optimized
4303ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * instructions at this time.  This means we will be executing <clinit>
4304ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * code with un-fixed volatiles, but we're only doing it for a few
4305ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * system classes, and dexopt runs single-threaded.
4306fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     */
4307ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden    if (!IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED) && !gDvm.optimizing) {
430892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("+++ late optimize on %s (pv=%d)",
4309fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden            clazz->descriptor, IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4310d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden        bool essentialOnly = (gDvm.dexOptMode != OPTIMIZE_MODE_FULL);
4311d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden        dvmOptimizeClass(clazz, essentialOnly);
4312fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden        SET_CLASS_FLAG(clazz, CLASS_ISOPTIMIZED);
4313fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    }
4314fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden
4315fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    /* update instruction stream now that verification + optimization is done */
4316d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmFlushBreakpoints(clazz);
4317d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden
4318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_INITIALIZED)
4319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (clazz->status == CLASS_INITIALIZING) {
4322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* we caught somebody else in the act; was it us? */
4323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->initThreadId == self->threadId) {
432492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block            //ALOGV("HEY: found a recursive <clinit>");
4325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
4329e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("GLITCH: exception pending at start of class init");
4330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
4331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Wait for the other thread to finish initialization.  We pass
4335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "false" for the "interruptShouldThrow" arg so it doesn't throw
4336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception on interrupt.
4337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * When we wake up, repeat the test for init-in-progress.  If there's
4342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception pending (only possible if "interruptShouldThrow"
4343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * was set), bail out.
4344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
43464308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("Class init of '%s' failing with wait() exception",
4347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: this is bogus, because it means the two threads have a
4350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different idea of the class status.  We need to flag the
4351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class as bad and ensure that the initializer thread respects
4352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * our notice.  If we get lucky and wake up after the class has
4353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * finished initialization but before being woken, we have to
4354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swallow the exception, perhaps raising thread->interrupted
4355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to preserve semantics.
4356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
4357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Since we're not currently allowing interrupts, this should
4358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never happen and we don't need to fix this.
4359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
43619b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            dvmThrowExceptionInInitializerError();
4362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_INITIALIZING) {
43664308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("Waiting again for class init");
4367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
4368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_INITIALIZED ||
4370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               clazz->status == CLASS_ERROR);
4371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The caller wants an exception, but it was thrown in a
4374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different thread.  Synthesize one here.
4375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
437670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            dvmThrowUnsatisfiedLinkError(
4377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "(<clinit> failed, see exception in other thread)");
4378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* see if we failed previously */
4383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_ERROR) {
4384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // might be wise to unlock before throwing; depends on which class
4385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // it is that we have locked
4386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
4387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwEarlierClassFailure(clazz);
4388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
4389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4391e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden    if (gDvm.allocProf.enabled) {
4392e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        startWhen = dvmGetRelativeTimeNsec();
4393e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden    }
4394e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden
4395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're ready to go, and have exclusive access to the class.
4397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Before we start initialization, we need to do one extra bit of
4399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * validation: make sure that the methods declared here match up
4400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with our superclass and interfaces.  We know that the UTF-8
4401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * descriptors match, but classes from different class loaders can
4402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have the same name.
4403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We do this now, rather than at load/link time, for the same reason
4405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we defer verification.
4406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's unfortunate that we need to do this at all, but we risk
4408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mixing reference types with identical names (see Dalvik test 068).
4409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateSuperDescriptors(clazz)) {
4411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
4412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Let's initialize this thing.
4418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We unlock the object so that other threads can politely sleep on
4420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our mutex with Object.wait(), instead of hanging or spinning trying
4421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to grab our mutex.
4422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->status < CLASS_INITIALIZING);
4424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // We started initializing.
4427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    logClassLoad('+', clazz);
4428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initializedByUs = true;
4429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
443110cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    /* order matters here, esp. interaction with dvmIsClassInitializing */
4432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->initThreadId = self->threadId;
4433dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro    android_atomic_release_store(CLASS_INITIALIZING,
4434dabd15a98449c6554579457aa4639bcdc3434eaaCarl Shapiro                                 (int32_t*)(void*)&clazz->status);
4435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init our superclass */
4438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsInterfaceClass(clazz));
4440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz->super)) {
4441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
4442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* wake up anybody who started waiting while we were unlocked */
4444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
4445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_notify;
4446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize any static fields whose values are
4450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stored in the Dex file.  This should include all of the
4451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * simple "final static" fields, which are required to
4452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * More-complicated final static fields should be set
4454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the beginning of <clinit>;  all we can do is trust
4455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the compiler did the right thing.
4456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initSFields(clazz);
4458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Execute any static initialization code.
4460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method == NULL) {
446360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("No <clinit> found for %s", clazz->descriptor);
4464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
446560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Invoking %s.<clinit>", clazz->descriptor);
4466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
4467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, method, NULL, &unused);
4468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
4471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We've had an exception thrown during static initialization.  We
4473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * need to throw an ExceptionInInitializerError, but we want to
4474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * tuck the original exception into the "cause" field.
4475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4476e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Exception %s thrown while initializing %s",
4477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
44789b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        dvmThrowExceptionInInitializerError();
4479e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        //ALOGW("+++ replaced");
4480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* success! */
4485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_INITIALIZED;
448760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("Initialized class: %s", clazz->descriptor);
4488e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden
4489e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        /*
4490e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden         * Update alloc counters.  TODO: guard with mutex.
4491e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden         */
4492e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        if (gDvm.allocProf.enabled && startWhen != 0) {
4493e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4494e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            gDvm.allocProf.classInitTime += initDuration;
4495e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            self->allocProf.classInitTime += initDuration;
4496e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            gDvm.allocProf.classInitCount++;
4497e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            self->allocProf.classInitCount++;
4498e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        }
4499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_notify:
4502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Notify anybody waiting on the object.
4504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmObjectNotifyAll(self, (Object*) clazz);
4506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
4508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initializedByUs) {
4511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // We finished initializing.
4512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('-', clazz);
4513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (clazz->status != CLASS_ERROR);
4519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Replace method->nativeFunc and method->insns with new values.  This is
45231e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * commonly performed after successful resolution of a native method.
45241e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45251e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * There are three basic states:
45261e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (1) (initial) nativeFunc = dvmResolveNativeMethod, insns = NULL
45271e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (2) (internal native) nativeFunc = <impl>, insns = NULL
45281e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (3) (JNI) nativeFunc = JNI call bridge, insns = <impl>
45291e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45301e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * nativeFunc must never be NULL for a native method.
45311e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45321e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * The most common transitions are (1)->(2) and (1)->(3).  The former is
45331e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * atomic, since only one field is updated; the latter is not, but since
45341e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * dvmResolveNativeMethod ignores the "insns" field we just need to make
45351e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * sure the update happens in the correct order.
45361e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45371e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * A transition from (2)->(1) would work fine, but (3)->(1) will not,
45381e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * because both fields change.  If we did this while a thread was executing
45391e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * in the call bridge, we could null out the "insns" field right before
45401e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * the bridge tried to call through it.  So, once "insns" is set, we do
45411e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * not allow it to be cleared.  A NULL value for the "insns" argument is
45421e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * treated as "do not change existing value".
4543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
45441e83b4d026199073c057edcb7836d06ae0716390Andy McFaddenvoid dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
4545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns)
4546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45491e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    assert(func != NULL);
45501e83b4d026199073c057edcb7836d06ae0716390Andy McFadden
4551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* just open up both; easier that way */
4552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45551e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    if (insns != NULL) {
45561e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        /* update both, ensuring that "insns" is observed first */
45571e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        method->insns = insns;
45581e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        android_atomic_release_store((int32_t) func,
4559fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            (volatile int32_t*)(void*) &method->nativeFunc);
45601e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    } else {
45611e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        /* only update nativeFunc */
45621e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        method->nativeFunc = func;
45631e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    }
4564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a RegisterMap to a Method.  This is done when we verify the class
457199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and compute the register maps at class initialization time (i.e. when
457299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * we don't have a pre-generated map).  This means "pMap" is on the heap
457399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and should be freed when the Method is discarded.
4574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method->registerMap != NULL) {
4580d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden        /* unexpected during class loading, okay on first use (uncompress) */
458192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("NOTE: registerMap already set for %s.%s",
4582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
4583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* keep going */
4584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
458599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
4586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* might be virtual or direct */
4588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->registerMap = pMap;
4592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmHashForeach callback.  A nonzero return value causes foreach to
4599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bail out.
4600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findClassCallback(void* vclazz, void* arg)
4602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4603fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ClassObject* clazz = (ClassObject*)vclazz;
4604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor = (const char*) arg;
4605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, descriptor) == 0)
4607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (int) clazz;
4608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a loaded class by descriptor. Returns the first one found.
4613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because there can be more than one if class loaders are involved,
4614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this is not an especially good API. (Currently only used by the
4615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * debugger and "checking" JNI.)
4616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" should have the form "Ljava/lang/Class;" or
4618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class name.
4620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindLoadedClass(const char* descriptor)
4622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
4624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (void*) descriptor);
4628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) result;
4631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Retrieve the system (a/k/a application) class loader.
463550cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden *
463650cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden * The caller must call dvmReleaseTrackedAlloc on the result.
4637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
46381e1433e78f560a01744e870c19c162ab88df9dc1Carl ShapiroObject* dvmGetSystemClassLoader()
4639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
464050cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    Thread* self = dvmThreadSelf();
4641f5e6de992c4b1b9b89c5f327be453e7e8fba312bAndy McFadden    ClassObject* clClass = gDvm.classJavaLangClassLoader;
4642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4643f5e6de992c4b1b9b89c5f327be453e7e8fba312bAndy McFadden    if (!dvmIsClassInitialized(clClass) && !dvmInitClass(clClass))
4644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
4645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
4647f5e6de992c4b1b9b89c5f327be453e7e8fba312bAndy McFadden    dvmCallMethod(self, gDvm.methJavaLangClassLoader_getSystemClassLoader,
4648f5e6de992c4b1b9b89c5f327be453e7e8fba312bAndy McFadden        NULL, &result);
4649f5e6de992c4b1b9b89c5f327be453e7e8fba312bAndy McFadden    Object* loader = (Object*)result.l;
465050cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(loader, self);
4651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return loader;
4652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a dvmHashForeach callback.
4657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpClass(void* vclazz, void* varg)
4659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
4661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* super;
4662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int flags = (int) varg;
4663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* desc;
4664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
46674308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("dumpClass: ignoring request to dump null class");
4668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & kDumpClassFullDetail) == 0) {
4672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showInit = (flags & kDumpClassInitialized) != 0;
4673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showLoader = (flags & kDumpClassClassLoader) != 0;
4674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* initStr;
4675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (showInit && showLoader)
46794308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("%s %p %s", clazz->descriptor, clazz->classLoader, initStr);
4680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showInit)
46814308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("%s %s", clazz->descriptor, initStr);
4682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showLoader)
46834308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("%s %p", clazz->descriptor, clazz->classLoader);
4684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
46854308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("%s", clazz->descriptor);
4686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* clazz->super briefly holds the superclass index during class prep */
4691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = clazz->super;
4693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
4694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = NULL;
4695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46964308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("----- %s '%s' cl=%p ser=0x%08x -----",
4697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmIsInterfaceClass(clazz) ? "interface" : "class",
4698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader, clazz->serialNumber);
46994308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("  objectSize=%d (%d from super)", (int) clazz->objectSize,
4700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super != NULL ? (int) super->objectSize : -1);
47014308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("  access=0x%04x.%04x", clazz->accessFlags >> 16,
4702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->accessFlags & JAVA_FLAGS_MASK);
4703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (super != NULL)
47044308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  super='%s' (cl=%p)", super->descriptor, super->classLoader);
4705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsArrayClass(clazz)) {
47064308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  dimensions=%d elementClass=%s",
4707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->arrayDim, clazz->elementClass->descriptor);
4708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->iftableCount > 0) {
47104308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  interfaces (%d):", clazz->iftableCount);
4711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->iftableCount; i++) {
4712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InterfaceEntry* ent = &clazz->iftable[i];
4713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
4714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47154308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %2d: %s (cl=%p)",
4716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                i, ent->clazz->descriptor, ent->clazz->classLoader);
4717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* enable when needed */
4719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (false && ent->methodIndexArray != NULL) {
4720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (j = 0; j < ent->clazz->virtualMethodCount; j++)
47214308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block                    ALOGI("      %2d: %d %s %s",
4722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        j, ent->methodIndexArray[j],
4723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        ent->clazz->virtualMethods[j].name,
4724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable[ent->methodIndexArray[j]]->name);
4725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
47294308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  vtable (%d entries, %d in super):", clazz->vtableCount,
4730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super != NULL ? super->vtableCount : 0);
4731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->vtableCount; i++) {
4732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
47334308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %s%2d: %p %20s %s",
4734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[i]->name, desc);
4737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
47394308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  direct methods (%d entries):", clazz->directMethodCount);
4740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->directMethodCount; i++) {
4741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->directMethods[i].prototype);
47434308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %2d: %20s %s", i, clazz->directMethods[i].name,
4744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
47484308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  interface methods (%d):", clazz->virtualMethodCount);
4749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
4750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->virtualMethods[i].prototype);
47524308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %2d: %2d %20s %s", i,
4753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->virtualMethods[i].methodIndex,
4754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods[i].name,
4755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount > 0) {
47604308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  static fields (%d entries):", clazz->sfieldCount);
4761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->sfieldCount; i++) {
47624308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %2d: %20s %s", i, clazz->sfields[i].name,
4763a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                clazz->sfields[i].signature);
4764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->ifieldCount > 0) {
47674308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("  instance fields (%d entries):", clazz->ifieldCount);
4768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->ifieldCount; i++) {
47694308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("    %2d: %20s %s", i, clazz->ifields[i].name,
4770a7323974309c3b81cfe342db635d0bf30f36ff62Carl Shapiro                clazz->ifields[i].signature);
4771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a single class.
4778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpClass(const ClassObject* clazz, int flags)
4782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClass((void*) clazz, (void*) flags);
4784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of all classes.
4788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpAllClasses(int flags)
4790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of loaded classes
4798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetNumLoadedClasses()
4800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count;
4802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = dvmHashTableNumEntries(gDvm.loadedClasses);
4804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
4806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write some statistics to the log file.
4810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpLoaderStats(const char* msg)
4812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
481392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d",
4814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef COUNT_PRECISE_METHODS
48184308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("GC precise methods: %d",
4819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPointerSetGetCount(gDvm.preciseMethods));
4820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Method Prototypes and Descriptors
4826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(). The
4831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name is considered the "major" order and the prototype the "minor"
4832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * order. The prototypes are compared as if by dvmCompareMethodProtos().
4833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndProtos(const Method* method1,
4835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodProtos(method1, method2);
4844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(), ignoring
4848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the return value. The name is considered the "major" order and the
4849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * prototype the "minor" order. The prototypes are compared as if by
4850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmCompareMethodArgProtos().
4851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodParameterProtos(method1, method2);
4862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, prototype) pair with the (name, prototype) of
4866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameProtoAndMethod(const char* name,
4871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexProto* proto, const Method* method)
4872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dexProtoCompare(proto, &method->prototype);
4880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, method descriptor) pair with the (name, prototype) of
4884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameDescriptorAndMethod(const char* name,
4889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor, const Method* method)
4890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareDescriptorAndMethodProto(descriptor, method);
4898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4899