Class.cpp revision ca02b580a542e97f273e1adfb6d26e7b20cc99a0
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
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOG(LOG_INFO, "PRELOAD", "%c%d:%d:%d:%s:%d:%s:%lld\n", 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!");
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("GOT: '%s'\n", 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);
2817605a84a9a0a1764c1fb290d9c93e8114eaf620aAndy McFadden    LOGI("Should be 1: %d\n", dvmLinearAllocContains(fiddle, 12));
2827605a84a9a0a1764c1fb290d9c93e8114eaf620aAndy McFadden    LOGI("Should be 0: %d\n", dvmLinearAllocContains(fiddle, 13));
2837605a84a9a0a1764c1fb290d9c93e8114eaf620aAndy McFadden    LOGI("Should be 0: %d\n", 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{
291c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    size_t size;
292c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
293c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    size = offsetof(ClassObject, sfields);
294c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    size += sizeof(StaticField) * sfieldCount;
295c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    return size;
296c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes}
297c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
298c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayessize_t dvmClassObjectSize(const ClassObject *clazz)
299c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes{
300c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz != NULL);
301c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    return classObjectSize(clazz->sfieldCount);
302c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes}
303c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the bootstrap class loader.
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call this after the bootclasspath string has been finalized.
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmClassStartup(void)
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make this a requirement -- don't currently support dirs in path */
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(gDvm.bootClassPathStr, ".") == 0) {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("ERROR: must specify non-'.' bootclasspath\n");
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses =
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.pBootLoaderAlloc = dvmLinearAllocCreate(NULL);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.pBootLoaderAlloc == NULL)
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        linearAllocTests();
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(0);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Class serial number.  We start with a high value to make it distinct
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in binary dumps (e.g. hprof).
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3332c98747b403970ef4b3352e271633f93935b9825Barry Hayes    gDvm.classSerialNumber = INITIAL_CLASS_SERIAL_NUMBER;
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3352c98747b403970ef4b3352e271633f93935b9825Barry Hayes    /* Set up the table we'll use for tracking initiating loaders for
3362c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * early classes.
3372c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * If it's NULL, we just fall back to the InitiatingLoaderList in the
3382c98747b403970ef4b3352e271633f93935b9825Barry Hayes     * ClassObject, so it's not fatal to fail this allocation.
3392c98747b403970ef4b3352e271633f93935b9825Barry Hayes     */
340fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    gDvm.initiatingLoaderList = (InitiatingLoaderList*)
3412c98747b403970ef4b3352e271633f93935b9825Barry Hayes        calloc(ZYGOTE_CLASS_CUTOFF, sizeof(InitiatingLoaderList));
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
343c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    gDvm.classJavaLangClass = (ClassObject*) dvmMalloc(
344c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        classObjectSize(CLASS_SFIELD_SLOTS), ALLOC_DEFAULT);
345c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    DVM_OBJECT_INIT(&gDvm.classJavaLangClass->obj, gDvm.classJavaLangClass);
346c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    gDvm.classJavaLangClass->descriptor = "Ljava/lang/Class;";
3470477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Process the bootstrap class path.  This means opening the specified
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * DEX or Jar files and possibly running them through the optimizer.
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.bootClassPath == NULL);
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    processClassPath(gDvm.bootClassPathStr, true);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPath == NULL)
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
358a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden    return true;
359a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden}
360a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden
361a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden/*
362a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden * We should be able to find classes now.  Get the vtable index for
363a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden * the class loader loadClass() method.
364a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden *
365a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden * This doesn't work in dexopt when operating on core.jar, because
366a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden * there aren't any classes to load.
367a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden */
368a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFaddenbool dvmBaseClassStartup(void)
369a7f5f9043f1ec312b3020ddae9b98937c9d462d3Andy McFadden{
3700477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    ClassObject* clClass = dvmFindSystemClassNoInit("Ljava/lang/ClassLoader;");
3710477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    Method* meth = dvmFindVirtualMethodByDescriptor(clClass, "loadClass",
3720477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden            "(Ljava/lang/String;)Ljava/lang/Class;");
3730477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    if (meth == NULL) {
3740477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden        LOGE("Unable to find loadClass() in java.lang.ClassLoader\n");
3750477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden        return false;
3760477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    }
3770477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    gDvm.voffJavaLangClassLoader_loadClass = meth->methodIndex;
3780477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up.
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClassShutdown(void)
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard all system-loaded classes */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableFree(gDvm.loadedClasses);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.loadedClasses = NULL;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* discard primitive classes created for arrays */
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < PRIM_MAX; i++)
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFreeClassInnards(gDvm.primitiveClass[i]);
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* this closes DEX files, JAR files, etc. */
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    freeCpeArray(gDvm.bootClassPath);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = NULL;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearAllocDestroy(NULL);
4022c98747b403970ef4b3352e271633f93935b9825Barry Hayes
4032c98747b403970ef4b3352e271633f93935b9825Barry Hayes    free(gDvm.initiatingLoaderList);
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Bootstrap class loader
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a ClassPathEntry array.
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpClassPath(const ClassPathEntry* cpe)
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx = 0;
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* kindStr;
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDir:       kindStr = "dir";    break;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:       kindStr = "jar";    break;
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:       kindStr = "dex";    break;
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:            kindStr = "???";    break;
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  %2d: type=%s %s %p\n", idx, kindStr, cpe->fileName, cpe->ptr);
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (CALC_CACHE_STATS && cpe->kind == kCpeJar) {
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DvmDex* pDvmDex = dvmGetJarFileDex(pJarFile);
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmDumpAtomicCacheStats(pDvmDex->pInterfaceCache);
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        idx++;
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of the bootstrap class path.
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpBootClassPath(void)
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClassPath(gDvm.bootClassPath);
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the class path contains the specified path.
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmClassPathContains(const ClassPathEntry* cpe, const char* path)
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(cpe->fileName, path) == 0)
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free an array of ClassPathEntry structs.
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We release the contents of each entry, then free the array itself.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeCpeArray(ClassPathEntry* cpe)
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpeStart = cpe;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe == NULL)
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free JarFile */
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmJarFileFree((JarFile*) cpe->ptr);
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* free RawDexFile */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmRawDexFileFree((RawDexFile*) cpe->ptr);
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* e.g. kCpeDir */
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(cpe->ptr == NULL);
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cpe->fileName);
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(cpeStart);
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Prepare a ClassPathEntry struct, which at this point only has a valid
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filename.  We need to figure out what kind of file it is, and for
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * everything other than directories we need to open it up and see
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * what's inside.
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap)
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile* pJarFile = NULL;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RawDexFile* pRawDexFile = NULL;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct stat sb;
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cc = stat(cpe->fileName, &sb);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cc < 0) {
5141b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden        LOGD("Unable to stat classpath element '%s'\n", cpe->fileName);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (S_ISDIR(sb.st_mode)) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The directory will usually have .class files in subdirectories,
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * which may be a few levels down.  Doing a recursive scan and
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * caching the results would help us avoid hitting the filesystem
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * on misses.  Whether or not this is of measureable benefit
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * depends on a number of factors, but most likely it is not
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * worth the effort (especially since most of our stuff will be
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in DEX or JAR).
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeDir;
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(cpe->ptr == NULL);
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) {
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeJar;
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->ptr = pJarFile;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: do we still want to support "raw" DEX files in the classpath?
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0)
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->kind = kCpeDex;
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe->ptr = pRawDexFile;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5461b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden    LOGD("Unable to process classpath element '%s'\n", cpe->fileName);
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a colon-separated list of directories, Zip files, and DEX files
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into an array of ClassPathEntry structs.
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * During normal startup we fail if there are no entries, because we won't
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * get very far without the basic language support classes, but if we're
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * optimizing a DEX file we allow it.
5571b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden *
5581b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * If entries are added or removed from the bootstrap class path, the
5591b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * dependencies in the DEX files will break, and everything except the
5601b5895818bfe6c703b8803dd3f954709bf725983Andy McFadden * very first entry will need to be regenerated.
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassPathEntry* cpe = NULL;
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangle;
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* end;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int idx, count;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pathStr != NULL);
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mangle = strdup(pathStr);
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through and essentially strtok() the string.  Get a count of
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the #of elements while we're at it.
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the path was constructed strangely (e.g. ":foo::bar:") this will
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * over-allocate, which isn't ideal but is mostly harmless.
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = 1;
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (cp = mangle; *cp != '\0'; cp++) {
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == ':') {   /* separates two entries */
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count++;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    end = cp;
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage.  We over-alloc by one so we can set an "end" marker.
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe = (ClassPathEntry*) calloc(count+1, sizeof(ClassPathEntry));
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set the global pointer so the DEX file dependency stuff can find it.
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Go through a second time, pulling stuff out.
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cp = mangle;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = 0;
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cp < end) {
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '\0') {
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leading, trailing, or doubled ':'; ignore it */
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
60932bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            if (isBootstrap &&
61032bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                    dvmPathToAbsolutePortion(cp) == NULL) {
61132bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                LOGE("Non-absolute bootclasspath entry '%s'\n", cp);
61232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                free(cpe);
61332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                cpe = NULL;
61432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein                goto bail;
61532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            }
61632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassPathEntry tmp;
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.kind = kCpeUnknown;
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.fileName = strdup(cp);
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tmp.ptr = NULL;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein            /*
62332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             * Drop an end marker here so DEX loader can walk unfinished
62432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             * list.
62532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein             */
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].kind = kCpeLastEntry;
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].fileName = NULL;
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cpe[idx].ptr = NULL;
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!prepareCpe(&tmp, isBootstrap)) {
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* drop from list and continue on */
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(tmp.fileName);
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* copy over, pointers and all */
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cpe[idx] = tmp;
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                idx++;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp += strlen(cp) +1;
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx <= count);
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (idx == 0 && !gDvm.optimizing) {
64432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein        LOGE("No valid entries found in bootclasspath '%s'\n", pathStr);
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cpe);
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe = NULL;
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("  (filled %d of %d slots)\n", idx, count);
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* put end marker in over-alloc slot */
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].kind = kCpeLastEntry;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].fileName = NULL;
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cpe[idx].ptr = NULL;
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dumpClassPath(cpe);
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangle);
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPath = cpe;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe;
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the DEX files we loaded from the bootstrap class path for a DEX
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file that has the class with the matching descriptor.
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the matching DEX file and DexClassDef entry if found, otherwise
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * returns NULL.
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic DvmDex* searchBootPathForClass(const char* descriptor,
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef** ppClassDef)
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pFoundDef = NULL;
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pFoundFile = NULL;
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...\n",
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor);
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry) {
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGV("+++  checking '%s' (%d)\n", cpe->fileName, cpe->kind);
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (cpe->kind) {
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDir:
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Directory entries ('%s') not supported in bootclasspath\n",
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cpe->fileName);
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeJar:
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JarFile* pJarFile = (JarFile*) cpe->ptr;
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetJarFileDex(pJarFile);
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case kCpeDex:
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr;
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const DexClassDef* pClassDef;
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DvmDex* pDvmDex;
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDvmDex = dvmGetRawDexFileDex(pRawDexFile);
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (pClassDef != NULL) {
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* found */
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundDef = pClassDef;
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pFoundFile = pDvmDex;
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    goto found;
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unknown kind %d\n", cpe->kind);
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Special handling during verification + optimization.
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The DEX optimizer needs to load classes from the DEX file it's working
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * on.  Rather than trying to insert it into the bootstrap class path
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * or synthesizing a class loader to manage it, we just make it available
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here.  It logically comes after all existing entries in the bootstrap
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class path.
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.bootClassPathOptExtra != NULL) {
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef =
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor);
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pClassDef != NULL) {
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* found */
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundDef = pClassDef;
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pFoundFile = gDvm.bootClassPathOptExtra;
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfound:
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ppClassDef = pFoundDef;
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pFoundFile;
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set the "extra" DEX, which becomes a de facto member of the bootstrap
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class set.
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetBootPathExtraDex(DvmDex* pDvmDex)
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.bootClassPathOptExtra = pDvmDex;
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the #of entries in the bootstrap class path.
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Used for ClassLoader.getResources().)
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetBootPathSize(void)
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cpe->kind != kCpeLastEntry)
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return cpe - gDvm.bootClassPath;
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a resource with the specified name in entry N of the boot class path.
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We return a newly-allocated String of one of these forms:
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   file://path/name
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   jar:file://path!/name
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Where "path" is the bootstrap class path entry and "name" is the string
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * passed into this method.  "path" needs to be an absolute path (starting
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with '/'); if it's not we'd need to "absolutify" it as part of forming
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the URL string.
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectStringObject* dvmGetBootPathResource(const char* name, int idx)
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int kUrlOverhead = 13;        // worst case for Jar URL
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassPathEntry* cpe = gDvm.bootClassPath;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* urlObj = NULL;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ searching for resource '%s' in %d(%s)\n",
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        name, idx, cpe[idx].fileName);
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we could use direct array index, but I don't entirely trust "idx" */
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (idx-- && cpe->kind != kCpeLastEntry)
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cpe++;
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cpe->kind == kCpeLastEntry) {
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1];
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (cpe->kind) {
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeDir:
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(urlBuf, "file://%s/%s", cpe->fileName, name);
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (access(urlBuf+7, F_OK) != 0)
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeJar:
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile* pJarFile = (JarFile*) cpe->ptr;
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dexZipFindEntry(&pJarFile->archive, name) == NULL)
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name);
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kCpeDex:
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("No resources in DEX files\n");
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ using URL='%s'\n", urlBuf);
83581f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes    urlObj = dvmCreateStringFromCstr(urlBuf);
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return urlObj;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class list management
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* search for these criteria in the Class hash table */
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct ClassMatchCriteria {
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     loader;
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} ClassMatchCriteria;
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kInitLoaderInc  4       /* must be power of 2 */
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8562c98747b403970ef4b3352e271633f93935b9825Barry Hayesstatic InitiatingLoaderList *dvmGetInitiatingLoaderList(ClassObject* clazz)
8572c98747b403970ef4b3352e271633f93935b9825Barry Hayes{
858c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->serialNumber >= INITIAL_CLASS_SERIAL_NUMBER);
8592c98747b403970ef4b3352e271633f93935b9825Barry Hayes    int classIndex = clazz->serialNumber-INITIAL_CLASS_SERIAL_NUMBER;
8602c98747b403970ef4b3352e271633f93935b9825Barry Hayes    if (gDvm.initiatingLoaderList != NULL &&
8612c98747b403970ef4b3352e271633f93935b9825Barry Hayes        classIndex < ZYGOTE_CLASS_CUTOFF) {
8622c98747b403970ef4b3352e271633f93935b9825Barry Hayes        return &(gDvm.initiatingLoaderList[classIndex]);
8632c98747b403970ef4b3352e271633f93935b9825Barry Hayes    } else {
8642c98747b403970ef4b3352e271633f93935b9825Barry Hayes        return &(clazz->initiatingLoaderList);
8652c98747b403970ef4b3352e271633f93935b9825Barry Hayes    }
8662c98747b403970ef4b3352e271633f93935b9825Barry Hayes}
8672c98747b403970ef4b3352e271633f93935b9825Barry Hayes
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine if "loader" appears in clazz' initiating loader list.
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class hash table lock must be held when calling here, since
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it's also used when updating a class' initiating loader list.
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: switch to some sort of lock-free data structure so we don't have
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to grab the lock to do a lookup.  Among other things, this would improve
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the speed of compareDescriptorClasses().
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader)
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The bootstrap class loader can't be just an initiating loader for
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * anything (it's always the defining loader if the class is visible
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to it).  We don't put defining loaders in the initiating list.
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader == NULL)
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Scan the list for a match.  The list is expected to be short.
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
8912c98747b403970ef4b3352e271633f93935b9825Barry Hayes    /* Cast to remove the const from clazz, but use const loaderList */
8922c98747b403970ef4b3352e271633f93935b9825Barry Hayes    ClassObject* nonConstClazz = (ClassObject*) clazz;
8932c98747b403970ef4b3352e271633f93935b9825Barry Hayes    const InitiatingLoaderList *loaderList =
8942c98747b403970ef4b3352e271633f93935b9825Barry Hayes        dvmGetInitiatingLoaderList(nonConstClazz);
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
8962c98747b403970ef4b3352e271633f93935b9825Barry Hayes    for (i = loaderList->initiatingLoaderCount-1; i >= 0; --i) {
8972c98747b403970ef4b3352e271633f93935b9825Barry Hayes        if (loaderList->initiatingLoaders[i] == loader) {
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("+++ found initiating match %p in %s\n",
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    loader, clazz->descriptor);
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return false;
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add "loader" to clazz's initiating loader set, unless it's the defining
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader.
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the common case this will be a short list, so we don't need to do
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything too fancy here.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This locks gDvm.loadedClasses for synchronization, so don't hold it
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * when calling here.
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmAddInitiatingLoader(ClassObject* clazz, Object* loader)
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != clazz->classLoader) {
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(loader != NULL);
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Adding %p to '%s' init list\n", loader, clazz->descriptor);
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.loadedClasses);
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Make sure nobody snuck in.  The penalty for adding twice is
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pretty minor, and probably outweighs the O(n^2) hit for
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * checking before every add, so we may not want to do this.
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
9292c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //if (dvmLoaderInInitiatingList(clazz, loader)) {
9302c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //    LOGW("WOW: simultaneous add of initiating class loader\n");
9312c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //    goto bail_unlock;
9322c98747b403970ef4b3352e271633f93935b9825Barry Hayes        //}
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The list never shrinks, so we just keep a count of the
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * number of elements in it, and reallocate the buffer when
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we run off the end.
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The pointer is initially NULL, so we *do* want to call realloc
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when count==0.
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
9422c98747b403970ef4b3352e271633f93935b9825Barry Hayes        InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
9432c98747b403970ef4b3352e271633f93935b9825Barry Hayes        if ((loaderList->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) {
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object** newList;
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9462c98747b403970ef4b3352e271633f93935b9825Barry Hayes            newList = (Object**) realloc(loaderList->initiatingLoaders,
9472c98747b403970ef4b3352e271633f93935b9825Barry Hayes                        (loaderList->initiatingLoaderCount + kInitLoaderInc)
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * sizeof(Object*));
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (newList == NULL) {
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* this is mainly a cache, so it's not the EotW */
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(false);
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail_unlock;
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
9542c98747b403970ef4b3352e271633f93935b9825Barry Hayes            loaderList->initiatingLoaders = newList;
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("Expanded init list to %d (%s)\n",
9572c98747b403970ef4b3352e271633f93935b9825Barry Hayes            //    loaderList->initiatingLoaderCount+kInitLoaderInc,
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor);
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
9602c98747b403970ef4b3352e271633f93935b9825Barry Hayes        loaderList->initiatingLoaders[loaderList->initiatingLoaderCount++] =
9612c98747b403970ef4b3352e271633f93935b9825Barry Hayes            loader;
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.loadedClasses);
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.)
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Entries in the class hash table are stored as { descriptor, d-loader }
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * tuples.  If the hashed class descriptor matches the requested descriptor,
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the hashed defining class loader matches the requested class
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader, we're good.  If only the descriptor matches, we check to see if the
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader is in the hashed class' initiating loader list.  If so, we
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can return "true" immediately and skip some of the loadClass melodrama.
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must lock the hash table before calling here.
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns 0 if a matching entry is found, nonzero otherwise.
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByCrit(const void* vclazz, const void* vcrit)
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit;
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 &&
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == pCrit->loader ||
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (pCrit->loader != NULL &&
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, pCrit->loader)) ));
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //if (match)
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //    LOGI("+++ %s %p matches existing %s %p\n",
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        pCrit->descriptor, pCrit->loader,
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        clazz->descriptor, clazz->classLoader);
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instead of a ClassMatchCriteria.
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpClassByClass(const void* vclazz, const void* vaddclazz)
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* addClazz = (const ClassObject*) vaddclazz;
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool match;
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 &&
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             (clazz->classLoader == addClazz->classLoader ||
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project              (addClazz->classLoader != NULL &&
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) ));
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return !match;
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search through the hash table to find an entry with a matching descriptor
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and an initiating class loader that matches "loader".
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The table entries are hashed on descriptor only, because they're unique
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on *defining* class loader, not *initiating* class loader.  This isn't
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * great, because it guarantees we will have to probe when multiple
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loaders are used.
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note this does NOT try to load a class; it just finds a class that
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has already been loaded.
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "unprepOkay" is set, this will return classes that have been added
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the hash table but are not yet fully loaded and linked.  Otherwise,
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * such classes are ignored.  (The only place that should set "unprepOkay"
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is findClassNoInit(), which will wait for the prep to finish.)
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if not found.
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmLookupClass(const char* descriptor, Object* loader,
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool unprepOkay)
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassMatchCriteria crit;
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.descriptor = descriptor;
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crit.loader = loader;
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(descriptor);
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p\n",
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThreadSelf()->threadId, descriptor, loader);
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit,
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByCrit, false);
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been added to the hash table but isn't ready for use.
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're going to act like we didn't see it, so that the caller will
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * go through the full "find class" path, which includes locking the
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * object and waiting until it's ready.  We could do that lock/wait
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * here, but this is an extremely rare case, and it's simpler to have
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the wait-for-class code centralized.
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1062fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    if (found && !unprepOkay && !dvmIsClassLinked((ClassObject*)found)) {
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Ignoring not-yet-ready %s, using slow path\n",
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((ClassObject*)found)->descriptor);
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        found = NULL;
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) found;
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add a new class to the hash table.
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class is considered "new" if it doesn't match on both the class
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor and the defining class loader.
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we should probably have separate hash tables for each
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader. This could speed up dvmLookupClass and
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * other common operations. It does imply a VM-visible data structure
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for each ClassLoader object with loaded classes, which we don't
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have yet.
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmAddClassToHash(ClassObject* clazz)
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* found;
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash;
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hash = dvmComputeUtf8Hash(clazz->descriptor);
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz,
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpClassByClass, true);
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p\n",
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader,
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (found == (void*) clazz), clazz);
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmCheckClassTablePerf();
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* can happen if two threads load the same class simultaneously */
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (found == (void*) clazz);
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute hash value for a class.
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectu4 hashcalcClass(const void* item)
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor);
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check the performance of the "loadedClasses" hash table.
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCheckClassTablePerf(void)
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hashcmpClassByClass);
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove a class object from the hash table.
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void removeClassFromHash(ClassObject* clazz)
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ removeClassFromHash '%s'\n", clazz->descriptor);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash = dvmComputeUtf8Hash(clazz->descriptor);
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz))
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Hash table remove failed on class '%s'\n", clazz->descriptor);
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Class creation
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Set clazz->serialNumber to the next available value.
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This usually happens *very* early in class creation, so don't expect
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything else in the class to be ready.
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetClassSerialNumber(ClassObject* clazz)
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->serialNumber == 0);
1157fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden    clazz->serialNumber = android_atomic_inc(&gDvm.classSerialNumber);
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded and initialized if it has not already been.
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If necessary, the superclass will be loaded.
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClass(const char* descriptor, Object* loader)
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindClassNoInit(descriptor, loader);
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), using the specified
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initiating ClassLoader.
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class will be loaded if it has not already been, as will its
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass.  It will not be initialized.
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the class can't be found, returns NULL with an appropriate exception
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * raised.
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindClassNoInit(const char* descriptor,
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* loader)
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(descriptor != NULL);
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //assert(loader != NULL);
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (*descriptor == '[') {
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Array class.  Find in table, generate if not found.
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return dvmFindArrayClass(descriptor, loader);
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Regular class.  Find in table, load if not found.
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (loader != NULL) {
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return findClassFromLoaderNoInit(descriptor, loader);
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return dvmFindSystemClassNoInit(descriptor);
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified class
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader.  This calls out to let the ClassLoader object do its thing.
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns with NULL and an exception raised on error.
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader)
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //        descriptor, loader);
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(loader != NULL);
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do we already have it?
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class loader code does the "is it already loaded" check as
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * well.  However, this call is much faster than calling through
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * interpreted code.  Doing this does mean that in the common case
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (365 out of 420 calls booting the sim) we're doing the
1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * lookup-by-descriptor twice.  It appears this is still a win, so
1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm keeping it in.
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmLookupClass(descriptor, loader, false);
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL) {
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Already loaded: %s %p\n", descriptor, loader);
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return clazz;
1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* dotName = NULL;
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = NULL;
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dotName = dvmDescriptorToDot(descriptor);
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dotName == NULL) {
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
126881f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes    nameObj = dvmCreateStringFromCstr(dotName);
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (nameObj == NULL) {
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceClassPrepBegin();
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Invoke loadClass().  This will probably result in a couple of
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exceptions being thrown, because the ClassLoader.loadClass()
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implementation eventually calls VMClassLoader.loadClass to see if
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the bootstrap class loader can find it before doing its own load.
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
12830477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    const Method* loadClass =
12840477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden        loader->clazz->vtable[gDvm.voffJavaLangClassLoader_loadClass];
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethod(self, loadClass, loader, &result, nameObj);
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = (ClassObject*) result.l;
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmMethodTraceClassPrepEnd();
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12910477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    Object* excep = dvmGetException(self);
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excep != NULL) {
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DVM_SHOW_EXCEPTION >= 2
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dotName, loader, excep->clazz->descriptor);
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAddTrackedAlloc(excep, self);
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(self);
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowChainedExceptionWithClassMessage(
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(excep, self);
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = NULL;
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1304d0f0ee6929af654a42b290e6886d4d9d19ae9ee8Andy McFadden    } else if (clazz == NULL) {
1305d0f0ee6929af654a42b290e6886d4d9d19ae9ee8Andy McFadden        LOGW("ClassLoader returned NULL w/o exception pending\n");
1306d0f0ee6929af654a42b290e6886d4d9d19ae9ee8Andy McFadden        dvmThrowException("Ljava/lang/NullPointerException;",
1307d0f0ee6929af654a42b290e6886d4d9d19ae9ee8Andy McFadden            "ClassLoader returned null");
1308d0f0ee6929af654a42b290e6886d4d9d19ae9ee8Andy McFadden        goto bail;
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13110477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden    /* not adding clazz to tracked-alloc list, because it's a ClassObject */
13120477139e2b3e614c6bc20d15c43e5e9b28ae9c13Andy McFadden
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddInitiatingLoader(clazz, loader);
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor, clazz->classLoader, loader, clazz);
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(dotName);
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load the named class (by descriptor) from the specified DEX file.
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Used by class loaders to instantiate a class object from a
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-managed DEX.
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* classLoader)
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pDvmDex != NULL);
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, classLoader, pDvmDex);
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), scanning through the
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath if it hasn't already been loaded.
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" looks like "Landroid/debug/Stuff;".
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Uses NULL as the defining class loader.
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClass(const char* descriptor)
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClassNoInit(descriptor);
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* initialize class */
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz)) {
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* init failed; leave it in the list, marked as bad */
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->status == CLASS_ERROR);
1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return NULL;
1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor), searching for it in the
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bootclasspath.
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return findClassNoInit(descriptor, NULL, NULL);
1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the named class (by descriptor). If it's not already loaded,
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we load it and link it, but don't execute <clinit>. (The VM has
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specific limitations on which events can cause initialization.)
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, this returns NULL with an exception raised.
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: we need to return an indication of whether we loaded the class or
1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used an existing definition.  If somebody deliberately tries to load a
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class twice in the same class loader, they should get a LinkageError,
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * but inadvertent simultaneous class references should "just work".
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex)
1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool profilerNotified = false;
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (loader != NULL) {
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex->pDexFile);
1399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't expect an exception to be raised at this point.  The
1403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception handling code is good about managing this.  This *can*
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * happen if a JNI lookup fails and the JNI code doesn't do any
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * error checking before doing another class lookup, so we may just
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want to clear this and restore it on exit.  If we don't, some kinds
1407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of failures can't be detected without rearranging other stuff.
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Most often when we hit this situation it means that something is
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * broken in the VM or in JNI code, so I'm keeping it in place (and
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * making it an informative abort rather than an assert).
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
1414504e9f4441c3a013047931d24a978523a26fde2dAndy McFadden        LOGE("Class lookup %s attempted while exception %s pending\n",
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            descriptor, dvmGetException(self)->clazz->descriptor);
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDumpAllThreads(false);
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmLookupClass(descriptor, loader, true);
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef;
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepBegin();
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        profilerNotified = true;
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u8 startTime = dvmGetThreadCpuTimeNsec();
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL) {
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);     /* shouldn't be here otherwise */
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pDvmDex == NULL || pClassDef == NULL) {
14397fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            if (gDvm.noClassDefFoundErrorObj != NULL) {
14407fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                /* usual case -- use prefabricated object */
14417fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                dvmSetException(self, gDvm.noClassDefFoundErrorObj);
14427fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            } else {
14437fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                /* dexopt case -- can't guarantee prefab (core.jar) */
14447fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                dvmThrowExceptionWithClassMessage(
14457fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden                    "Ljava/lang/NoClassDefFoundError;", descriptor);
14467fc3ce8f0223a90006ad2c431a43b0bc841ee3c2Andy McFadden            }
1447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* found a match, try to load it */
1451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
1453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* class was found but had issues */
1454a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            if (clazz != NULL) {
1455a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden                dvmFreeClassInnards(clazz);
1456a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden                dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1457a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            }
1458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Lock the class while we link it so other threads must wait for us
1463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to finish.  Set the "initThreadId" so we can identify recursive
146410cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden         * invocation.  (Note all accesses to initThreadId here are
146510cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden         * guarded by the class object's lock.)
1466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
1468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->initThreadId = self->threadId;
1469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add to hash table so lookups succeed.
1472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * [Are circular references possible when linking a class?]
1474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->classLoader == loader);
1476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmAddClassToHash(clazz)) {
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Another thread must have loaded the class after we
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * started but before we finished.  Discard what we've
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * done and leave some hints for the GC.
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (Yes, this happens.)
1483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let the GC free the class.
1489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1490a0b525d50b8b514e1e8f5c9b2852ce056a5eb89dAndy McFadden            dvmFreeClassInnards(clazz);
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Grab the winning class.
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = dvmLookupClass(descriptor, loader, true);
1496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz != NULL);
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto got_class;
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoadWithTime('>', clazz, startTime);
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Prepare and resolve.
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1507c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (!dvmLinkClass(clazz)) {
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Make note of the error and clean up the class.
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            removeClassFromHash(clazz);
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
1514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFreeClassInnards(clazz);
1515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Let any waiters know.
1517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId = 0;
1519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmObjectNotifyAll(self, (Object*) clazz);
1520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, get_process_name());
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: It would probably be better to use a new type code here (instead of '<') to
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * indicate the failure.  This change would require a matching change in the parser
1529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * and analysis code in frameworks/base/tools/preload.
1530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            logClassLoad('<', clazz);
1532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.optimizing) {
1535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* happens with "external" libs */
1536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Link of class '%s' failed\n", descriptor);
1537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Link of class '%s' failed\n", descriptor);
1539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectNotifyAll(self, (Object*) clazz);
1543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
1544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Add class stats to global counters.
1547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
1548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: these should probably be atomic ops.
1549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numLoadedClasses++;
1551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods +=
1552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethodCount + clazz->directMethodCount;
1553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredInstFields += clazz->ifieldCount;
1554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Cache pointers to basic classes.  We want to use these in
1558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * various places, and it's easiest to initialize them on first
1559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * use rather than trying to force them to initialize (startup
1560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * ordering makes it weird).
1561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classJavaLangObject == NULL &&
1563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(descriptor, "Ljava/lang/Object;") == 0)
1564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* It should be impossible to get here with anything
1566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * but the bootclasspath loader.
1567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(loader == NULL);
1569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.classJavaLangObject = clazz;
1570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
1573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('<', clazz);
1574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
1575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectgot_class:
1578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can race with other threads for class linking.  We should
1581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never get here recursively; doing so indicates that two
1582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes have circular dependencies.
1583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
1584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * One exception: we force discovery of java.lang.Class in
1585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * dvmLinkClass(), and Class has Object as its superclass.  So
1586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * if the first thing we ever load is Object, we will init
1587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Object->Class->Object.  The easiest way to avoid this is to
1588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * ensure that Object is never the first thing we look up, so
1589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we get Foo->Class->Object instead.
1590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
1592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmIsClassLinked(clazz) &&
1593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->initThreadId == self->threadId)
1594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
1595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Recursive link on class %s\n", clazz->descriptor);
1596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmUnlockObject(self, (Object*) clazz);
1597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowExceptionWithClassMessage(
1598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz = NULL;
1600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
1601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGI("WAITING  for '%s' (owner=%d)\n",
1603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    clazz->descriptor, clazz->initThreadId);
1604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockObject(self, (Object*) clazz);
1608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
1610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Somebody else tried to load this and failed.  We need to raise
1612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * an exception and report failure.
1613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
1615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz = NULL;
1616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check some invariants */
1621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz));
1622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.classJavaLangClass != NULL);
1623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->obj.clazz == gDvm.classJavaLangClass);
16249ef5ca666a214f2a96b16e0830e19d37742ab8caAndy McFadden    assert(clazz == gDvm.classJavaLangObject || clazz->super != NULL);
1625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
1626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->vtableCount,
1628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->virtualMethodCount);
1629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtableCount >= clazz->virtualMethodCount);
1630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (profilerNotified)
1634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmMethodTraceClassPrepEnd();
1635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != NULL || dvmCheckException(self));
1636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return clazz;
1637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * encoded data pointer in addition to the other arguments.
1642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData, Object* classLoader)
1646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* newClass = NULL;
1648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
1650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Make sure the aren't any "bonus" flags set, since we use them for
1657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * runtime state.
1658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Invalid file flags in class %s: %04x\n",
1661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            descriptor, pClassDef->accessFlags);
1662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate storage for the class object on the GC heap, so that other
1667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * objects can have references to it.  We bypass the usual mechanism
1668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (allocObject), because we don't have all the bits and pieces yet.
1669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that we assume that java.lang.Class does not override
1671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finalize().
1672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1673c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    /* TODO: Can there be fewer special checks in the usual path? */
1674c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(descriptor != NULL);
1675c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (classLoader == NULL &&
1676c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        strcmp(descriptor, "Ljava/lang/Class;") == 0) {
1677c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        assert(gDvm.classJavaLangClass != NULL);
1678c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        newClass = gDvm.classJavaLangClass;
1679c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    } else {
1680c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        size_t size = classObjectSize(pHeader->staticFieldsSize);
1681c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        newClass = (ClassObject*) dvmMalloc(size, ALLOC_DEFAULT);
1682c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
1683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (newClass == NULL)
1684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
1685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1686c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
1687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetClassSerialNumber(newClass);
1688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->descriptor = descriptor;
1689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(newClass->descriptorAlloc == NULL);
1690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->accessFlags = pClassDef->accessFlags;
1691364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    dvmSetFieldObject((Object *)newClass,
1692364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                      offsetof(ClassObject, classLoader),
1693364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                      (Object *)classLoader);
1694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->pDvmDex = pDvmDex;
1695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->primitiveType = PRIM_NOT;
1696c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    newClass->status = CLASS_IDX;
1697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff the superclass index into the object pointer field.  The linker
1700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pulls it out and replaces it with a resolved ClassObject pointer.
1701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * I'm doing it this way (rather than having a dedicated superclassIdx
1702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field) to save a few bytes of overhead per class.
1703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this is safe.
1706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1707c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(sizeof(u4) == sizeof(ClassObject*)); /* 32-bit check */
1708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->super = (ClassObject*) pClassDef->superclassIdx;
1709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Stuff class reference indices into the pointer fields.
1712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The elements of newClass->interfaces are not traversed or freed by
1714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmFreeClassInnards, so this is GC-safe.
1715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexTypeList* pInterfacesList;
1717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pInterfacesList != NULL) {
1719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaceCount = pInterfacesList->size;
1720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                newClass->interfaceCount * sizeof(ClassObject*));
1722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < newClass->interfaceCount; i++) {
1724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->interfaces);
1728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* load field definitions */
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
173303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * Over-allocate the class object and append static field info
173403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * onto the end.  It's fixed-size and known at alloc time.  This
173503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * seems to increase zygote sharing.  Heap compaction will have to
173603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * be careful if it ever tries to move ClassObject instances,
173703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * because we pass Field pointers around internally. But at least
173803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * now these Field pointers are in the object heap.
1739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->staticFieldsSize != 0) {
1742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* static fields stay on system heap; field data isn't "write once" */
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->staticFieldsSize;
1744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->sfieldCount = count;
1748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->instanceFieldsSize != 0) {
1755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->instanceFieldsSize;
1756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexField field;
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifieldCount = count;
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(InstField));
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->ifields);
1767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /*
177099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Load method definitions.  We do this in two batches, direct then
177199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * virtual.
177299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *
177399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * If register maps have already been generated for this class, and
177499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * precise GC is enabled, we pull out pointers to them.  We know that
177599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * they were streamed to the DEX file in the same order in which the
177699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * methods appear.
177799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *
177899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * If the class wasn't pre-verified, the maps will be generated when
177999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * the class is verified during class initialization.
178099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
178199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
178299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const void* classMapData;
178399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u4 numMethods;
178499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
178599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (gDvm.preciseGc) {
178699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        classMapData =
1787d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden            dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
178899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
178999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /* sanity check */
179099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (classMapData != NULL &&
179199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
179299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        {
179399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
179499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                newClass->descriptor, pHeader->directMethodsSize,
179599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                pHeader->virtualMethodsSize, numMethods);
179699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            assert(false);
179799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            classMapData = NULL;        /* abandon */
179899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
179999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } else {
180099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        classMapData = NULL;
180199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->directMethodsSize != 0) {
1804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->directMethodsSize;
1805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethodCount = count;
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
181499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            if (classMapData != NULL) {
1815d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1816d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
181799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    newClass->directMethods[i].registerMap = pMap;
181899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    /* TODO: add rigorous checks */
181999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    assert((newClass->directMethods[i].registersSize+7) / 8 ==
182099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                        newClass->directMethods[i].registerMap->regWidth);
182199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                }
182299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            }
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->directMethods);
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pHeader->virtualMethodsSize != 0) {
1828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = (int) pHeader->virtualMethodsSize;
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 lastIndex = 0;
1830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexMethod method;
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethodCount = count;
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count * sizeof(Method));
1835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
1836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
183899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            if (classMapData != NULL) {
1839d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
1840d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
184199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    newClass->virtualMethods[i].registerMap = pMap;
184299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    /* TODO: add rigorous checks */
184399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                    assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
184499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                        newClass->virtualMethods[i].registerMap->regWidth);
184599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                }
184699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            }
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* caller must call dvmReleaseTrackedAlloc */
1854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newClass;
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Try to load the indicated class from the specified DEX file.
1859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is effectively loadClass()+defineClass() for a DexClassDef.  The
1861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loading was largely done when we crunched through the DEX.
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL on failure.  If we locate the class but encounter an error
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while processing it, an appropriate exception is thrown.
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef, Object* classLoader)
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result;
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassDataHeader header;
1871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData;
1872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFile* pDexFile;
1873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((pDvmDex != NULL) && (pClassDef != NULL));
1875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
1876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass) {
1878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: loading '%s'...\n",
1879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexGetClassDescriptor(pDexFile, pClassDef));
1880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEncodedData = dexGetClassData(pDexFile, pClassDef);
1883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pEncodedData != NULL) {
1885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexReadClassDataHeader(&pEncodedData, &header);
1886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Provide an all-zeroes header for the rest of the loading.
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memset(&header, 0, sizeof(header));
1889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            classLoader);
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass && (result != NULL)) {
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result->descriptor, pDvmDex, classLoader);
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a ClassObject that was allocated on the system heap.
1904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ClassObject itself is allocated on the GC heap, so we leave it for
1906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the garbage collector.
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this may be called with a partially-constructed object.
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: there is no particular ordering imposed, so don't go poking at
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclasses.
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeClassInnards(ClassObject* clazz)
1913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void *tp;
1915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1920c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->obj.clazz == gDvm.classJavaLangClass);
1921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Guarantee that dvmFreeClassInnards can be called on a given
1923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class multiple times by clearing things out as we free them.
1924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We don't make any attempt at real atomicity here; higher
1925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * levels need to make sure that no two threads can free the
1926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * same ClassObject at the same time.
1927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: maybe just make it so the GC will never free the
1929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * innards of an already-freed class.
1930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_FREE(p) \
1934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
1935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
1936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
1937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
1938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(tp); \
1939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
1940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
1941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NULL_AND_LINEAR_FREE(p) \
1942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    do { \
1943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((p) != NULL) { \
1944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tp = (p); \
1945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (p) = NULL; \
1946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearFree(clazz->classLoader, tp); \
1947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } \
1948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (0)
1949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* arrays just point at Object's vtable; don't free vtable in this case.
1951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtableCount = -1;
195333a192e2096cff25029ae339de84d33a443e7c8eBarry Hayes    if (clazz->vtable == gDvm.classJavaLangObject->vtable) {
1954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = NULL;
1955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        NULL_AND_LINEAR_FREE(clazz->vtable);
1957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->descriptor = NULL;
1960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_FREE(clazz->descriptorAlloc);
1961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->directMethods != NULL) {
1963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *directMethods = clazz->directMethods;
1964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int directMethodCount = clazz->directMethodCount;
1965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethods = NULL;
1966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->directMethodCount = -1;
1967b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(clazz->classLoader, directMethods);
1968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < directMethodCount; i++) {
1969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&directMethods[i]);
1970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1971b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadOnly(clazz->classLoader, directMethods);
1972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, directMethods);
1973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->virtualMethods != NULL) {
1975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method *virtualMethods = clazz->virtualMethods;
1976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int virtualMethodCount = clazz->virtualMethodCount;
1977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount = -1;
1978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = NULL;
1979b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(clazz->classLoader, virtualMethods);
1980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < virtualMethodCount; i++) {
1981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            freeMethodInnards(&virtualMethods[i]);
1982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1983b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadOnly(clazz->classLoader, virtualMethods);
1984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, virtualMethods);
1985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19872c98747b403970ef4b3352e271633f93935b9825Barry Hayes    InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
19882c98747b403970ef4b3352e271633f93935b9825Barry Hayes    loaderList->initiatingLoaderCount = -1;
19892c98747b403970ef4b3352e271633f93935b9825Barry Hayes    NULL_AND_FREE(loaderList->initiatingLoaders);
1990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->interfaceCount = -1;
1992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->interfaces);
1993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = -1;
1995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->iftable);
1996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = -1;
1998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifviPool);
1999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->sfieldCount = -1;
200103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes    /* The sfields are attached to the ClassObject, and will be freed
200203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes     * with it. */
2003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldCount = -1;
2005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    NULL_AND_LINEAR_FREE(clazz->ifields);
2006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_FREE
2008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#undef NULL_AND_LINEAR_FREE
2009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free anything in a Method that was allocated on the system heap.
201399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
201499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * The containing class is largely torn down by this point.
2015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeMethodInnards(Method* meth)
2017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
2019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->exceptions);
2020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->lines);
2021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(meth->locals);
2022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
202399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
202499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /*
202599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Some register maps are allocated on the heap, either because of late
202699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * verification or because we're caching an uncompressed form.
202799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
202899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const RegisterMap* pMap = meth->registerMap;
2029d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden    if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
203099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dvmFreeRegisterMap((RegisterMap*) pMap);
203199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        meth->registerMap = NULL;
203299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
2033b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2034b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    /*
2035b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden     * We may have copied the instructions.
2036b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden     */
2037b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2038b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2039b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearFree(meth->clazz->classLoader, methodDexCode);
2040b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
2041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clone a Method, making new copies of anything that will be freed up
204599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * by freeMethodInnards().  This is used for "miranda" methods.
2046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void cloneMethod(Method* dst, const Method* src)
2048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
204999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (src->registerMap != NULL) {
205099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        LOGE("GLITCH: only expected abstract methods here\n");
205199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        LOGE("        cloning %s.%s\n", src->clazz->descriptor, src->name);
205299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dvmAbort();
205399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
2054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(dst, src, sizeof(Method));
2055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pull the interesting pieces out of a DexMethod.
2059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The DEX file isn't going anywhere, so we don't need to make copies of
2061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the code area.
2062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
2064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth)
2065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexMethodId* pMethodId;
2068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pDexCode;
2069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
2071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->shorty = dexProtoGetShorty(&meth->prototype);
2075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->accessFlags = pDexMethod->accessFlags;
2076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->clazz = clazz;
2077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth->jniArgInfo = 0;
2078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2080ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        /*
2081ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * The Enum class declares a "final" finalize() method to
2082ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * prevent subclasses from introducing a finalizer.  We don't
2083ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * want to set the finalizable flag for Enum or its subclasses,
2084ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * so we check for it here.
2085ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         *
2086ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * We also want to avoid setting it on Object, but it's easier
2087ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         * to just strip that out later.
2088ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden         */
2089ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        if (clazz->classLoader != NULL ||
2090ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden            strcmp(clazz->descriptor, "Ljava/lang/Enum;") != 0)
2091ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        {
2092ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden            SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2093ca02b580a542e97f273e1adfb6d26e7b20cc99a0Andy McFadden        }
2094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexCode = dexGetCode(pDexFile, pDexMethod);
2097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexCode != NULL) {
2098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* integer constants, copy over for faster access */
2099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = pDexCode->registersSize;
2100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insSize = pDexCode->insSize;
2101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->outsSize = pDexCode->outsSize;
2102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* pointer to code area */
2104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->insns = pDexCode->insns;
2105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We don't have a DexCode block, but we still want to know how
2108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * much space is needed for the arguments (so we don't have to
2109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * compute it later).  We also take this opportunity to compute
2110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * JNI argument info.
2111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
2112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We do this for abstract methods as well, because we want to
2113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be able to substitute our exception-throwing "stub" in.
2114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int argsSize = dvmComputeMethodArgsSize(meth);
2116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsStaticMethod(meth))
2117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            argsSize++;
2118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth->registersSize = meth->insSize = argsSize;
2119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->outsSize == 0);
2120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(meth->insns == NULL);
2121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
2123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = dvmResolveNativeMethod;
2124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#if 0       /* replaced with private/read-write mapping */
2130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2131b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * We usually map bytecode directly out of the DEX file, which is mapped
2132b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * shared read-only.  If we want to be able to modify it, we have to make
2133b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * a new copy.
2134b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2135b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Once copied, the code will be in the LinearAlloc region, which may be
2136b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * marked read-only.
2137b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2138b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * The bytecode instructions are embedded inside a DexCode structure, so we
2139b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * need to copy all of that.  (The dvmGetMethodCode function backs up the
2140b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * instruction pointer to find the start of the DexCode.)
2141b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
2142b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmMakeCodeReadWrite(Method* meth)
2143b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
2144b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2145b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2146b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
2147b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
2148b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        return;
2149b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    }
2150b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2151b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
2152b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2153b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
2154b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    LOGD("Making a copy of %s.%s code (%d bytes)\n",
2155b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        meth->clazz->descriptor, meth->name, dexCodeSize);
2156b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2157b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* newCode =
2158b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden        (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
2159b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    memcpy(newCode, methodDexCode, dexCodeSize);
2160b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2161b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    meth->insns = newCode->insns;
2162b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
2163b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
2164b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2165b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
2166b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Mark the bytecode read-only.
2167b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden *
2168b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * If the contents of the DexCode haven't actually changed, we could revert
2169b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * to the original shared page.
2170b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */
2171b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmMakeCodeReadOnly(Method* meth)
2172b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{
2173b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
2174b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    LOGV("+++ marking %p read-only\n", methodDexCode);
2175b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden    dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
2176b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden}
217796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#endif
2178b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2179b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden
2180b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/*
2181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jniArgInfo (32-bit int) layout:
2182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   S - if set, do things the hard way (scan the signature)
2185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   R - return-type enumeration
2186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   H - target-specific hints
2187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This info is used at invocation time by dvmPlatformInvoke.  In most
2189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * having to fully parse the signature.
2191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The return-type bits are always set, even if target-specific hint bits
2193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are unavailable.
2194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int computeJniArgInfo(const DexProto* proto)
2196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* sig = dexProtoGetShorty(proto);
2198e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    int returnType, jniArgInfo;
2199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hints;
2200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The first shorty character is the return type. */
2202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (*(sig++)) {
2203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'V':
2204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_VOID;
2205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F':
2207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_FLOAT;
2208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D':
2210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_DOUBLE;
2211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J':
2213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S8;
2214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2215e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'Z':
2216e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'B':
2217e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_S1;
2218e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2219e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'C':
2220e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_U2;
2221e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2222e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee    case 'S':
2223e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        returnType = DALVIK_JNI_RETURN_S2;
2224e2557513420f6be2d70c19a4d826731174c828d1Bill Buzbee        break;
2225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
2226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnType = DALVIK_JNI_RETURN_S4;
2227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
2228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hints = dvmPlatformInvokeHints(proto);
2233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (hints & DALVIK_JNI_NO_ARG_INFO) {
2235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jniArgInfo |= hints;
2239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return jniArgInfo;
2242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about a static field.
2246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This also "prepares" static fields by initializing them
2248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to their "standard default values".
2249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadSFieldFromDex(ClassObject* clazz,
2251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexSField, StaticField* sfield)
2252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.clazz = clazz;
2259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.accessFlags = pDexSField->accessFlags;
2262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Static object field values are set to "standard default values"
2264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (null or 0) until the class is initialized.  We delay loading
2265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constant values from the class until that time.
2266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //sfield->value.j = 0;
2268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(sfield->value.j == 0LL);     // cleared earlier with calloc
2269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
2271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sfield->field.gets = sfield->field.puts = 0;
2272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load information about an instance field.
2277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void loadIFieldFromDex(ClassObject* clazz,
2279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexField* pDexIField, InstField* ifield)
2280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
2283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.clazz = clazz;
2287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.accessFlags = pDexIField->accessFlags;
2290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
2291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(ifield->byteOffset == 0);    // cleared earlier with calloc
2292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->byteOffset = -1;    // make it obvious if we fail to set later
2293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
2296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifield->field.gets = ifield->field.puts = 0;
2297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
2298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache java.lang.ref.Reference fields and methods.
2302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
23036daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic bool precacheReferenceOffsets(ClassObject* clazz)
2304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method *meth;
2306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* We trick the GC object scanner by not counting
2309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.ref.Reference.referent as an object
2310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * field.  It will get explicitly scanned as part
2311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of the reference-walking process.
2312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Find the object field named "referent" and put it
2314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * just after the list of object reference fields.
2315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldRefCount; i++) {
2318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
2319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(pField->field.name, "referent") == 0) {
2320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int targetIndex;
2321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Swap this field with the last object field.
2323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            targetIndex = clazz->ifieldRefCount - 1;
2325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i != targetIndex) {
2326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField *swapField = &clazz->ifields[targetIndex];
2327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField tmpField;
2328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int tmpByteOffset;
2329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* It's not currently strictly necessary
2331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * for the fields to be in byteOffset order,
2332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * but it's more predictable that way.
2333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpByteOffset = swapField->byteOffset;
2335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                swapField->byteOffset = pField->byteOffset;
2336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pField->byteOffset = tmpByteOffset;
2337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tmpField = *swapField;
2339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *swapField = *pField;
2340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *pField = tmpField;
2341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* One fewer object field (wink wink).
2344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount--;
2346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i--;        /* don't trip "didn't find it" test if field was last */
2347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
2348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i == clazz->ifieldRefCount) {
2352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
2354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Cache pretty much everything about Reference so that
2357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we don't need to call interpreted code when clearing/enqueueing
2358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * references.  This is fragile, so we'll be paranoid.
2359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangRefReference = clazz;
2361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_referent =
2363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "referent", "Ljava/lang/Object;");
2365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_referent >= 0);
2366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_queue =
2368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "queue", "Ljava/lang/ref/ReferenceQueue;");
2370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_queue >= 0);
2371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangRefReference_queueNext =
2373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "queueNext", "Ljava/lang/ref/Reference;");
2375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23772a6f4846b2a9e252c914e5103270fc86cc786859Carl Shapiro    gDvm.offJavaLangRefReference_pendingNext =
23782a6f4846b2a9e252c914e5103270fc86cc786859Carl Shapiro        dvmFindFieldOffset(gDvm.classJavaLangRefReference,
23792a6f4846b2a9e252c914e5103270fc86cc786859Carl Shapiro                "pendingNext", "Ljava/lang/ref/Reference;");
23802a6f4846b2a9e252c914e5103270fc86cc786859Carl Shapiro    assert(gDvm.offJavaLangRefReference_pendingNext >= 0);
23812a6f4846b2a9e252c914e5103270fc86cc786859Carl Shapiro
2382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* enqueueInternal() is private and thus a direct method. */
2383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(meth != NULL);
2385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.methJavaLangRefReference_enqueueInternal = meth;
2386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
2388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
23926daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes * Set the bitmap of reference offsets, refOffsets, from the ifields
23936daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes * list.
23946daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes */
23956daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayesstatic void computeRefOffsets(ClassObject* clazz)
23966daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes{
23976daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    if (clazz->super != NULL) {
23986daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        clazz->refOffsets = clazz->super->refOffsets;
23996daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    } else {
24006daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        clazz->refOffsets = 0;
24016daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    }
24026daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    /*
24036daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * If our superclass overflowed, we don't stand a chance.
24046daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     */
24056daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    if (clazz->refOffsets != CLASS_WALK_SUPER) {
24066daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        InstField *f;
24076daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        int i;
24086daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24096daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        /* All of the fields that contain object references
24106daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes         * are guaranteed to be at the beginning of the ifields list.
24116daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes         */
24126daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        f = clazz->ifields;
24136daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        const int ifieldRefCount = clazz->ifieldRefCount;
24146daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        for (i = 0; i < ifieldRefCount; i++) {
24156daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          /*
24166daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * Note that, per the comment on struct InstField,
24176daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * f->byteOffset is the offset from the beginning of
24186daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           * obj, not the offset into obj->instanceData.
24196daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes           */
24202fbe6d15ed8d266ed55fb76e97f866dbd07d5fa6Andy McFadden          assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
24216daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
24226daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
24236daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
24246daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              assert(newBit != 0);
24256daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              clazz->refOffsets |= newBit;
24266daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          } else {
24276daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              clazz->refOffsets = CLASS_WALK_SUPER;
24286daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes              break;
24296daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          }
24306daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes          f++;
24316daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes        }
24326daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    }
24336daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes}
24346daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24356daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
24366daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes/*
2437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Link (prepare and resolve).  Verification is deferred until later.
2438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This converts symbolic references into pointers.  It's independent of
2440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the source file format.
2441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2442c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * If clazz->status is CLASS_IDX, then clazz->super and interfaces[] are
2443c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * holding class reference indices rather than pointers.  The class
2444c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * references will be resolved during link.  (This is done when
2445c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * loading from DEX to avoid having to create additional storage to
2446c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes * pass the indices around.)
2447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" with an exception pending on failure.
2449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2450c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayesbool dvmLinkClass(ClassObject* clazz)
2451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 superclassIdx = 0;
2453c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    u4 *interfaceIdxArray = NULL;
2454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool okay = false;
2455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2457c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz != NULL);
2458c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->descriptor != NULL);
2459c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->status == CLASS_IDX || clazz->status == CLASS_LOADED);
2460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
2461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2463c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(gDvm.classJavaLangClass != NULL);
2464c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->obj.clazz == gDvm.classJavaLangClass);
2465c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (clazz->classLoader == NULL &&
2466c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        (strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0))
2467c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    {
2468c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (gDvm.classJavaLangClass->ifieldCount > CLASS_FIELD_SLOTS) {
2469c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            LOGE("java.lang.Class has %d instance fields (expected at most %d)",
2470c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                 gDvm.classJavaLangClass->ifieldCount, CLASS_FIELD_SLOTS);
2471c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmAbort();
2472c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2473c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (gDvm.classJavaLangClass->sfieldCount != CLASS_SFIELD_SLOTS) {
2474c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            LOGE("java.lang.Class has %d static fields (expected %d)",
2475c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                 gDvm.classJavaLangClass->sfieldCount, CLASS_SFIELD_SLOTS);
2476c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmAbort();
2477c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2478c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* "Resolve" the class.
2480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2481c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * At this point, clazz's reference fields may contain Dex file
2482c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * indices instead of direct object references.  Proxy objects are
2483c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * an exception, and may be the only exception.  We need to
2484c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * translate those indices into real references, and let the GC
2485c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * look inside this ClassObject.
2486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2487c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (clazz->status == CLASS_IDX) {
2488c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->interfaceCount > 0) {
2489c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            /* Copy u4 DEX idx values out of the ClassObject* array
2490c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes             * where we stashed them.
2491c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes             */
2492c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            assert(sizeof(*interfaceIdxArray) == sizeof(*clazz->interfaces));
2493c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            size_t len = clazz->interfaceCount * sizeof(*interfaceIdxArray);
2494fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            interfaceIdxArray = (u4*)malloc(len);
2495c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            if (interfaceIdxArray == NULL) {
2496c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                LOGW("Unable to allocate memory to link %s", clazz->descriptor);
2497c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                goto bail;
24983595a09a6fff5483f69f0f714128646c17a03216Barry Hayes            }
2499c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            memcpy(interfaceIdxArray, clazz->interfaces, len);
25001145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden
25011145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden            dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2502c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            memset(clazz->interfaces, 0, len);
25031145f22c92b0fb2c3bfc4de2d0d38bd54046127cAndy McFadden            dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2504c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2505c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2506c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        assert(sizeof(superclassIdx) == sizeof(clazz->super));
2507c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        superclassIdx = (u4) clazz->super;
2508c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        clazz->super = NULL;
2509c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        /* After this line, clazz will be fair game for the GC. The
2510c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes         * superclass and interfaces are all NULL.
2511c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes         */
2512c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        clazz->status = CLASS_LOADED;
2513c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2514c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (superclassIdx != kDexNoIndex) {
2515364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            ClassObject* super = dvmResolveClass(clazz, superclassIdx, false);
2516364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            if (super == NULL) {
2517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(dvmCheckException(dvmThreadSelf()));
2518c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (gDvm.optimizing) {
2519c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    /* happens with "external" libs */
2520c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    LOGV("Unable to resolve superclass of %s (%d)\n",
2521c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->descriptor, superclassIdx);
2522c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                } else {
2523c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    LOGW("Unable to resolve superclass of %s (%d)\n",
2524c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->descriptor, superclassIdx);
2525c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
2526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2528364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            dvmSetFieldObject((Object *)clazz,
2529364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                              offsetof(ClassObject, super),
2530364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                              (Object *)super);
2531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2533c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->interfaceCount > 0) {
2534c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            /* Resolve the interfaces implemented directly by this class. */
2535c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            assert(interfaceIdxArray != NULL);
2536c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2537c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            for (i = 0; i < clazz->interfaceCount; i++) {
2538c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                assert(interfaceIdxArray[i] != kDexNoIndex);
2539c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                clazz->interfaces[i] =
2540c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmResolveClass(clazz, interfaceIdxArray[i], false);
2541c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (clazz->interfaces[i] == NULL) {
2542c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2543c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2544c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    assert(dvmCheckException(dvmThreadSelf()));
2545c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2546c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2547c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    const char* classDescriptor;
2548c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    classDescriptor =
2549c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        dexStringByTypeIdx(pDexFile, interfaceIdxArray[i]);
2550c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    if (gDvm.optimizing) {
2551c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        /* happens with "external" libs */
2552c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        LOGV("Failed resolving %s interface %d '%s'\n",
2553c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             clazz->descriptor, interfaceIdxArray[i],
2554c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             classDescriptor);
2555c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    } else {
2556c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                        LOGI("Failed resolving %s interface %d '%s'\n",
2557c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             clazz->descriptor, interfaceIdxArray[i],
2558c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                             classDescriptor);
2559c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    }
2560c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    goto bail;
2561c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
2562c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes
2563c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                /* are we allowed to implement this interface? */
2564c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2565c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2566c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    LOGW("Interface '%s' is not accessible to '%s'\n",
2567c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                         clazz->interfaces[i]->descriptor, clazz->descriptor);
2568c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    dvmThrowException("Ljava/lang/IllegalAccessError;",
2569c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                                      "interface not accessible");
2570c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                    goto bail;
2571c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                }
2572c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                LOGVV("+++  found interface '%s'\n",
2573c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                      clazz->interfaces[i]->descriptor);
2574c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            }
2575c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2576c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        }
2577c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2579c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * There are now Class references visible to the GC in super and
2580c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * interfaces.
2581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2584c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * All classes have a direct superclass, except for
2585c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * java/lang/Object and primitive classes. Primitive classes are
2586c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes     * are created CLASS_INITIALIZED, so won't get here.
2587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2588c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    assert(clazz->primitiveType == PRIM_NOT);
2589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
2590c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->super != NULL) {
2591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* TODO: is this invariant true for all java/lang/Objects,
2592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * regardless of the class loader?  For now, assume it is.
2593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/ClassFormatError;",
2595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "java.lang.Object has a superclass");
2596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Don't finalize objects whose classes use the
2600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * default (empty) Object.finalize().
2601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2604c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        if (clazz->super == NULL) {
2605c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            dvmThrowException("Ljava/lang/LinkageError;",
2606c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes                              "no superclass defined");
2607c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            goto bail;
2608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* verify */
2610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsFinalClass(clazz->super)) {
2611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' is final '%s'\n",
2612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass is final");
2615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (dvmIsInterfaceClass(clazz->super)) {
2617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' is interface '%s'\n",
2618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass is an interface");
2621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Superclass of '%s' (%s) is not accessible\n",
2624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->super->descriptor);
2625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/IllegalAccessError;",
2626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "superclass not accessible");
2627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Inherit finalizability from the superclass.  If this
2631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class also overrides finalize(), its CLASS_ISFINALIZABLE
2632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * bit will already be set.
2633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* See if this class descends from java.lang.Reference
2639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and set the class flags appropriately.
2640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 superRefFlags;
2643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We've already determined the reference type of this
2645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * inheritance chain.  Inherit reference-ness from the superclass.
2646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
2650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE);
2651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, superRefFlags);
2652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (clazz->classLoader == NULL &&
2653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->super->classLoader == NULL &&
2654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                strcmp(clazz->super->descriptor,
2655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/Reference;") == 0)
2656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
2657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 refFlags;
2658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This class extends Reference, which means it should
2660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * be one of the magic Soft/Weak/PhantomReference classes.
2661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            refFlags = CLASS_ISREFERENCE;
2663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (strcmp(clazz->descriptor,
2664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/SoftReference;") == 0)
2665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Only CLASS_ISREFERENCE is set for soft references.
2667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
2669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/WeakReference;") == 0)
2670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISWEAKREFERENCE;
2672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (strcmp(clazz->descriptor,
2673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       "Ljava/lang/ref/PhantomReference;") == 0)
2674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
2675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                refFlags |= CLASS_ISPHANTOMREFERENCE;
2676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* No-one else is allowed to inherit directly
2678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * from Reference.
2679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
2680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//xxx is this the right exception?  better than an assertion.
2681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/LinkageError;",
2682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "illegal inheritance from Reference");
2683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* The class should not have any reference bits set yet.
2687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
2688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(GET_CLASS_FLAG_GROUP(clazz,
2689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISREFERENCE |
2690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISWEAKREFERENCE |
2691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CLASS_ISPHANTOMREFERENCE) == 0);
2692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SET_CLASS_FLAG(clazz, refFlags);
2694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate vtable.
2699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz)) {
2701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* no vtable; just set the method indices */
2702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in interface '%s'\n", count,
2706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++)
2713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!createVtable(clazz)) {
2718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("failed creating vtable\n");
2719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Populate interface method tables.  Can alter the vtable.
2725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!createIftable(clazz))
2727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Insert special-purpose "stub" method implementations.
2731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!insertMethodStubs(clazz))
2733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute instance field offsets and, hence, the size of the object.
2737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!computeFieldOffsets(clazz))
2739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Cache fields and methods from java/lang/ref/Reference and
2743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java/lang/Class.  This has to happen after computeFieldOffsets().
2744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->classLoader == NULL) {
2746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!precacheReferenceOffsets(clazz)) {
2748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("failed pre-caching Reference offsets\n");
2749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/InternalError;", NULL);
2750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (clazz == gDvm.classJavaLangClass) {
2753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Ljava/security/ProtectionDomain;");
2755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.offJavaLangClass_pd <= 0) {
2756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("ERROR: unable to find 'pd' field in Class\n");
2757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmAbort();     /* we're not going to get much farther */
2758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
27636daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * Compact the offsets the GC has to examine into a bitmap, if
27646daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * possible.  (This has to happen after Reference.referent is
27656daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     * massaged in precacheReferenceOffsets.)
27666daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes     */
27676daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    computeRefOffsets(clazz);
27686daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes
27696daaac12e5de630749f94ff5f15e902e7b18d8e7Barry Hayes    /*
2770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Done!
2771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
2774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
2775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_RESOLVED;
2776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    okay = true;
2777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.verboseClass)
2778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We send CLASS_PREPARE events to the debugger from here.  The
2782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * definition of "preparation" is creating the static fields for a
2783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class and initializing them to the standard default values, but not
2784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * executing any code (that comes later, during "initialization").
2785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We did the static prep in loadSFieldFromDex() while loading the class.
2787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
2788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class has been prepared and resolved but possibly not yet verified
2789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at this point.
2790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2791cb3081f675109049e63380170b60871e8275f9a8buzbee    if (DEBUGGER_ACTIVE) {
2792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDbgPostClassPrepare(clazz);
2793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!okay) {
2797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
2798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckException(dvmThreadSelf())) {
2799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2802c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    if (interfaceIdxArray != NULL) {
2803c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes        free(interfaceIdxArray);
2804c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes    }
2805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return okay;
2806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the virtual method table.
2810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top part of the table is a copy of the table from our superclass,
2812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with our local methods overriding theirs.  The bottom part of the table
2813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has any new methods we defined.
2814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createVtable(ClassObject* clazz)
2816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int maxCount;
2819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->super->descriptor);
2824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* the virtual methods we define, plus the superclass vtable size */
2827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    maxCount = clazz->virtualMethodCount;
2828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        maxCount += clazz->super->vtableCount;
2830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* TODO: is this invariant true for all java/lang/Objects,
2832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * regardless of the class loader?  For now, assume it is.
2833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Over-allocate the table, then realloc it down if necessary.  So
2840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * long as we don't allocate anything in between we won't cause
2841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * fragmentation, and reducing the size should be unlikely to cause
2842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a buffer copy.
2843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * maxCount);
2847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->vtable == NULL)
2848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL) {
2851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int actualCount;
2852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->vtable, clazz->super->vtable,
2854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        actualCount = clazz->super->vtableCount;
2856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
2858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * See if any of our virtual methods override the superclass.
2859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
2860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
2861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* localMeth = &clazz->virtualMethods[i];
2862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int si;
2863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (si = 0; si < clazz->super->vtableCount; si++) {
2865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Method* superMeth = clazz->vtable[si];
2866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
2869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* verify */
2870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmIsFinalMethod(superMeth)) {
2871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        LOGW("Method %s.%s overrides final %s.%s\n",
2872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            localMeth->clazz->descriptor, localMeth->name,
2873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            superMeth->clazz->descriptor, superMeth->name);
2874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
2875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
2876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtable[si] = localMeth;
2877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    localMeth->methodIndex = (u2) si;
2878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //LOGV("+++   override %s.%s (slot %d)\n",
2879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    clazz->descriptor, localMeth->name, si);
2880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
2881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (si == clazz->super->vtableCount) {
2885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* not an override, add to end */
2886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[actualCount] = localMeth;
2887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                localMeth->methodIndex = (u2) actualCount;
2888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                actualCount++;
2889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //LOGV("+++   add method %s.%s\n",
2891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //    clazz->descriptor, localMeth->name);
2892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount != (u2) actualCount) {
2896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(actualCount <= maxCount);
2902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (actualCount < maxCount) {
2904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(clazz->vtable != NULL);
2905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2906fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            clazz->vtable = (Method **)dvmLinearRealloc(clazz->classLoader,
2907fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                clazz->vtable, sizeof(*(clazz->vtable)) * actualCount);
2908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz->vtable == NULL) {
2909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGE("vtable realloc failed\n");
2910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
2911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("+++  reduced vtable from %d to %d\n",
2913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    maxCount, actualCount);
2914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = actualCount;
2918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* java/lang/Object case */
2920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = clazz->virtualMethodCount;
2921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count != (u2) count) {
2922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many methods (%d) in base class '%s'\n", count,
2923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 clazz->descriptor);
2924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
2925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < count; i++) {
2928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[i] = &clazz->virtualMethods[i];
2929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->virtualMethods[i].methodIndex = (u2) i;
2930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
2931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount = clazz->virtualMethodCount;
2932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
2935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
2937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
2940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
2941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create and populate "iftable".
2944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The set of interfaces we support is the combination of the interfaces
2946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we implement directly and those implemented by our superclass.  Each
2947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interface can have one or more "superinterfaces", which we must also
2948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * support.  For speed we flatten the tree out.
2949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to speed this up when there are lots of interfaces
2951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by merge-sorting the class pointers and binary-searching when removing
2952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * duplicates.  We could also drop the duplicate removal -- it's only
2953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there to reduce the memory footprint.
2954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
2957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
2958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
2959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool createIftable(ClassObject* clazz)
2960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
2961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
2962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIftable = false;
2963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapVtable = false;
2964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool zapIfvipool = false;
2965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ifCount, superIfCount, idx;
2966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
2967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
2969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = clazz->super->iftableCount;
2970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
2971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superIfCount = 0;
2972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifCount = superIfCount;
2974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ifCount += clazz->interfaceCount;
2975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->interfaceCount; i++)
2976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ifCount += clazz->interfaces[i]->iftableCount;
2977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ifCount == 0) {
2982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftableCount == 0);
2983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->iftable == NULL);
2984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
2985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
2986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
2987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
2989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a table with enough space for all interfaces, and copy the
2990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass' table in.
2991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
2992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(InterfaceEntry) * ifCount);
2994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIftable = true;
2995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (superIfCount != 0) {
2997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        memcpy(clazz->iftable, clazz->super->iftable,
2998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizeof(InterfaceEntry) * superIfCount);
2999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a flattened interface hierarchy of our immediate interfaces.
3003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    idx = superIfCount;
3005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->interfaceCount; i++) {
3007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* interf;
3008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int j;
3009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        interf = clazz->interfaces[i];
3011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(interf != NULL);
3012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* make sure this is still an interface class */
3014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmIsInterfaceClass(interf)) {
3015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Class '%s' implements non-interface '%s'\n",
3016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, interf->descriptor);
3017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowExceptionWithClassMessage(
3018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Ljava/lang/IncompatibleClassChangeError;",
3019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
3020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entry for this interface */
3024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[idx++].clazz = interf;
3025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* add entries for the interface's superinterfaces */
3027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (j = 0; j < interf->iftableCount; j++) {
3028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
3029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(idx == ifCount);
3033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false) {
3035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Remove anything redundant from our recent additions.  Note we have
3037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to traverse the recent adds when looking for duplicates, because
3038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it's possible the recent additions are self-redundant.  This
3039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * reduces the memory footprint of classes with lots of inherited
3040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * interfaces.
3041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (I don't know if this will cause problems later on when we're trying
3043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to find a static field.  It looks like the proper search order is
3044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (1) current class, (2) interfaces implemented by current class,
3045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (3) repeat with superclass.  A field implemented by an interface
3046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and by a superclass might come out wrong if the superclass also
3047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * implements the interface.  The javac compiler will reject the
3048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * situation as ambiguous, so the concern is somewhat artificial.)
3049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
3051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because it wants to return just the interfaces declared to be
3052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * implemented directly by the class.  I'm excluding this code for now.
3053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = superIfCount; i < ifCount; i++) {
3055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
3056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = 0; j < ifCount; j++) {
3058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i == j)
3059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
3060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
3061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("INTF: redundant interface %s in %s\n",
3062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->iftable[i].clazz->descriptor,
3063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->descriptor);
3064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (i != ifCount-1)
3066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        memmove(&clazz->iftable[i], &clazz->iftable[i+1],
3067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (ifCount - i -1) * sizeof(InterfaceEntry));
3068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ifCount--;
3069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i--;        // adjust for i++ above
3070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
3075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } // if (false)
3076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->iftableCount = ifCount;
3078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we're an interface, we don't need the vtable pointers, so
3081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're done.  If this class doesn't implement an interface that our
3082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass doesn't have, then we again have nothing to do.
3083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
3085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //dvmDumpClass(clazz, kDumpClassFullDetail);
3086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
3087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
3088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * When we're handling invokeinterface, we probably have an object
3092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * whose type is an interface class rather than a concrete class.  We
3093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * need to convert the method reference into a vtable index.  So, for
3094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * every entry in "iftable", we create a list of vtable indices.
3095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Because our vtable encompasses the superclass vtable, we can use
3097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the vtable indices from our superclass for all of the interfaces
3098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that weren't directly implemented by us.
3099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Each entry in "iftable" has a pointer to the start of its set of
3101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * vtable offsets.  The iftable entries in the superclass point to
3102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * storage allocated in the superclass, and the iftable entries added
3103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for this class point to storage allocated in this class.  "iftable"
3104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is flat for fast access in a class and all of its subclasses, but
3105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "ifviPool" is only created for the topmost implementor.
3106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int poolSize = 0;
3108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = superIfCount; i < ifCount; i++) {
3109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note it's valid for an interface to have no methods (e.g.
3111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * java/io/Serializable).
3112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: pool: %d from %s\n",
3114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->virtualMethodCount,
3115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->iftable[i].clazz->descriptor);
3116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolSize += clazz->iftable[i].clazz->virtualMethodCount;
3117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (poolSize == 0) {
3120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("INTF: didn't find any new interfaces with methods\n");
3121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
3122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
3123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPoolCount = poolSize;
3126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
3127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        poolSize * sizeof(int*));
3128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zapIfvipool = true;
3129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Fill in the vtable offsets for the interfaces that weren't part of
3132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our superclass.
3133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int poolOffset = 0;
3135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method** mirandaList = NULL;
3136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int mirandaCount = 0, mirandaAlloc = 0;
3137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = superIfCount; i < ifCount; i++) {
3139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObject* interface;
3140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int methIdx;
3141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
3143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        interface = clazz->iftable[i].clazz;
3144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        poolOffset += interface->virtualMethodCount;    // end here
3145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * For each method listed in the interface's method list, find the
3148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matching method in our class's method list.  We want to favor the
3149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass over the superclass, which just requires walking
3150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * back from the end of the vtable.  (This only matters if the
3151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * superclass defines a private method and this class redefines
3152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it -- otherwise it would use the same vtable slot.  In Dalvik
3153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * those don't end up in the virtual method table, so it shouldn't
3154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * matter which direction we go.  We walk it backward anyway.)
3155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Suppose we have the following arrangement:
3158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public interface MyInterface
3159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface();
3160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public abstract class MirandaAbstract implements MirandaInterface
3161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     //public abstract boolean inInterface(); // not declared!
3162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
3163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *   public class MirandClass extends MirandaAbstract
3164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inInterface() { stuff }
3165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *     public boolean inAbstract() { stuff }    // in vtable
3166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The javac compiler happily compiles MirandaAbstract even though
3168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it doesn't declare all methods from its interface.  When we try
3169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to set up a vtable for MirandaAbstract, we find that we don't
3170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have an slot for inInterface.  To prevent this, we synthesize
3171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * abstract method declarations in MirandaAbstract.
3172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
3173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We have to expand vtable and update some things that point at it,
3174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * so we accumulate the method list and do it all at once below.
3175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* imeth = &interface->virtualMethods[methIdx];
3178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
3179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            IF_LOGVV() {
3181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("INTF:  matching '%s' '%s'\n", imeth->name, desc);
3183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                free(desc);
3184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = clazz->vtableCount-1; j >= 0; j--) {
3187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    == 0)
3189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                {
3190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("INTF:   matched at %d\n", j);
3191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsPublicMethod(clazz->vtable[j])) {
3192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        LOGW("Implementation of %s.%s is not public\n",
3193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            clazz->descriptor, clazz->vtable[j]->name);
3194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmThrowException("Ljava/lang/IllegalAccessError;",
3195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "interface implementation not public");
3196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        goto bail;
3197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->iftable[i].methodIndexArray[methIdx] = j;
3199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (j < 0) {
3203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                IF_LOGV() {
3204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    char* desc =
3205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dexProtoCopyMethodDescriptor(&imeth->prototype);
3206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            imeth->name, desc, clazz->descriptor);
3208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    free(desc);
3209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                //return false;
3212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mirandaCount == mirandaAlloc) {
3214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaAlloc += 8;
3215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (mirandaList == NULL) {
3216fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                        mirandaList = (Method**)dvmLinearAlloc(
3217fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                                        clazz->classLoader,
3218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        mirandaAlloc * sizeof(Method*));
3219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
3220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3221fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                        mirandaList = (Method**)dvmLinearRealloc(
3222fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                                clazz->classLoader,
3223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList, mirandaAlloc * sizeof(Method*));
3224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    assert(mirandaList != NULL);    // mem failed + we leaked
3226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
3229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * These may be redundant (e.g. method with same name and
3230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * signature declared in two interfaces implemented by the
3231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * same abstract class).  We can squeeze the duplicates
3232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * out here.
3233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
3234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int mir;
3235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (mir = 0; mir < mirandaCount; mir++) {
3236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (dvmCompareMethodNamesAndProtos(
3237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            mirandaList[mir], imeth) == 0)
3238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    {
3239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        IF_LOGVV() {
3240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            char* desc = dexProtoCopyMethodDescriptor(
3241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    &imeth->prototype);
3242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                mirandaList[mir]->clazz->descriptor,
3244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->clazz->descriptor,
3245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                imeth->name, desc);
3246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            free(desc);
3247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
3248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* point the iftable at a phantom slot index */
3253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->iftable[i].methodIndexArray[methIdx] =
3254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->vtableCount + mir;
3255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGVV("MIRANDA: %s points at slot %d\n",
3256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    imeth->name, clazz->vtableCount + mir);
3257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if non-duplicate among Mirandas, add to Miranda list */
3259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (mir == mirandaCount) {
3260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //LOGV("MIRANDA: holding '%s' in slot %d\n",
3261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //    imeth->name, mir);
3262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    mirandaList[mirandaCount++] = imeth;
3263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mirandaCount != 0) {
326968825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        static const int kManyMirandas = 150;   /* arbitrary */
3270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* newVirtualMethods;
3271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
3272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int oldMethodCount, oldVtableCount;
3273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < mirandaCount; i++) {
3275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("MIRANDA %d: %s.%s\n", i,
3276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
327868825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        if (mirandaCount > kManyMirandas) {
327968825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden            /*
328068825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * Some obfuscators like to create an interface with a huge
328168825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * pile of methods, declare classes as implementing it, and then
328268825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * only define a couple of methods.  This leads to a rather
328368825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * massive collection of Miranda methods and a lot of wasted
328468825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             * space, sometimes enough to blow out the LinearAlloc cap.
328568825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden             */
328668825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden            LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
328768825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden                clazz->descriptor, mirandaCount);
328868825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden        }
3289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We found methods in one or more interfaces for which we do not
3292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * have vtable entries.  We have to expand our virtualMethods
3293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * table (which might be empty) to hold some new entries.
3294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->virtualMethods == NULL) {
3296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods,
3302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newVirtualMethods != clazz->virtualMethods) {
3305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Table was moved in memory.  We have to run through the
3307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * vtable and fix the pointers.  The vtable entries might be
3308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * pointing at superclasses, so we flip it around: run through
3309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * all locally-defined virtual methods, and fix their entries
3310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in the vtable.  (This would get really messy if sub-classes
3311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * had already been loaded.)
3312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * hold the virtual methods declared by this class.  The
3315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method's methodIndex is the vtable index, and is the same
3316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * for all sub-classes (and all super classes in which it is
3317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * defined).  We're messing with these because the Miranda
3318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * stuff makes it look like the class actually has an abstract
3319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * method declaration in it.
3320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("MIRANDA fixing vtable pointers\n");
3322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Method* meth = newVirtualMethods;
3324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[meth->methodIndex] = meth;
3326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldMethodCount = clazz->virtualMethodCount;
3330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethods = newVirtualMethods;
3331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->virtualMethodCount += mirandaCount;
3332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We also have to expand the vtable.
3337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->vtable != NULL);
3339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable,
3341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->vtable == NULL) {
3343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
3345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        zapVtable = true;
3347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        oldVtableCount = clazz->vtableCount;
3349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->vtableCount += mirandaCount;
3350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Now we need to create the fake methods.  We clone the abstract
3353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method definition from the interface and then replace a few
3354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * things.
335568825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         *
335668825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         * The Method will be an "abstract native", with nativeFunc set to
335768825974c18f3b03330c6f4b3a0bf9eb6504d20fAndy McFadden         * dvmAbstractMethodStub().
3358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = clazz->virtualMethods + oldMethodCount;
3360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < mirandaCount; i++, meth++) {
3361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cloneMethod(meth, mirandaList[i]);
3363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->clazz = clazz;
3364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_MIRANDA;
3365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->methodIndex = (u2) (oldVtableCount + i);
3366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* point the new vtable entry at the new method */
3369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->vtable[oldVtableCount + i] = meth;
3370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, mirandaList);
3373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearFree(clazz->classLoader, mirandaList);
3374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO?
3379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sort the interfaces by number of declared methods.  All we really
3380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * want is to get the interfaces with zero methods at the end of the
3381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * list, so that when we walk through the list during invoke-interface
3382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we don't examine interfaces that can't possibly be useful.
3383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The set will usually be small, so a simple insertion sort works.
3385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to be careful not to change the order of two interfaces
3387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that define the same method.  (Not a problem if we only move the
3388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * zero-method interfaces to the end.)
3389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * PROBLEM:
3391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we do this, we will no longer be able to identify super vs.
3392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * current class interfaces by comparing clazz->super->iftableCount.  This
3393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * breaks anything that only wants to find interfaces declared directly
3394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * dvmDbgOutputAllInterfaces, etc).  Need to provide a workaround.
3396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can sort just the interfaces implemented directly by this class,
3398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but that doesn't seem like it would provide much of an advantage.  I'm
3399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not sure this is worthwhile.
3400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This has been made largely obsolete by the interface cache mechanism.)
3402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmDumpClass(clazz);
3405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
3407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
3409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIftable)
3410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapVtable)
3412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zapIfvipool)
3414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
3416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Provide "stub" implementations for methods without them.
3421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently we provide an implementation for all abstract methods that
3423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throws an AbstractMethodError exception.  This allows us to avoid an
3424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * explicit check for abstract methods in every virtual call.
3425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: for Miranda methods, the method declaration is a clone of what
3427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * was found in the interface class.  That copy may already have had the
3428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * function pointer filled in, so don't be surprised if it's not NULL.
3429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which is nonsensical.  Need to make sure that this doesn't escape the
3432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM.  We can either mask it out in reflection calls, or copy "native"
3433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the high 16 bits of accessFlags and check that internally.
3434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool insertMethodStubs(ClassObject* clazz)
3436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth;
3440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = clazz->virtualMethods;
3443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsAbstractMethod(meth)) {
3445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->insns == NULL);
3446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(meth->nativeFunc == NULL ||
3447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->accessFlags |= ACC_NATIVE;
3450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Swap two instance fields.
3461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void swapField(InstField* pOne, InstField* pTwo)
3463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    InstField swap;
3465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("  --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    swap = *pOne;
3468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pOne = *pTwo;
3469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pTwo = swap;
3470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assign instance fields to u4 slots.
3474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top portion of the instance field area is occupied by the superclass
3476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields, the bottom by the fields for this class.
3477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "long" and "double" fields occupy two adjacent slots.  On some
3479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * arrange fields (or introduce padding) to ensure this.  We assume the
3481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we can just ensure that the offset is "even".  To avoid wasting space,
3483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we want to move non-reference 32-bit fields into gaps rather than
3484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creating pad words.
3485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the worst case we will waste 4 bytes, but because objects are
3487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (assuming this is the most-derived class).
3489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pad words are not represented in the field table, so the field table
3491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * itself does not change size.
3492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The number of field slots determines the size of the object, so we
3494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * set that here too.
3495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This function feels a little more complicated than I'd like, but it
3497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has the property of moving the smallest possible set of fields, which
3498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should reduce the time required to load a class.
3499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will break.
3502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool computeFieldOffsets(ClassObject* clazz)
3504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int fieldOffset;
3506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, j;
3507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL)
3511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset = clazz->super->objectSize;
3512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
3513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset = offsetof(DataObject, instanceData);
3514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start by moving all reference fields to the front.
3524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->ifieldRefCount = 0;
3526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a reference field; see if any reference fields
3533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* refField = &clazz->ifields[j--];
3538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = refField->field.signature[0];
3539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == '[' || rc == 'L') {
3541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a reference field that follows at least one
3542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-reference field.  Swap it with the current field.
3543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "refField" points to the non-ref field.)
3545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, refField);
3547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Fix the signature.
3549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->ifieldRefCount++;
3553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a reference field.
3560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->ifieldRefCount++;
3562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we've hit the end of the reference fields, break.
3566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L')
3568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
3569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
3571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
3572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Now we want to pack all of the double-wide fields together.  If we're
3577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not aligned, though, we want to shuffle one 32-bit field into place.
3578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we can't find one, we'll have to pad it.
3579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  +++ not aligned\n");
3582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'J' && c != 'D') {
3587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The field that comes next is 32-bit, so just advance past it.
3589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(c != '[' && c != 'L');
3591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pField->byteOffset = fieldOffset;
3592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            i++;
3594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("  --- offset2 '%s'=%d\n",
3595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pField->field.name, pField->byteOffset);
3596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Next field is 64-bit, so search for a 32-bit field we can
3599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swap into it.
3600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool found = false;
3602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            j = clazz->ifieldCount - 1;
3603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* singleField = &clazz->ifields[j--];
3605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = singleField->field.signature[0];
3606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc != 'J' && rc != 'D') {
3608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, singleField);
3609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    //c = rc;
3610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("  +++ swapped '%s' for alignment\n",
3611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pField->field.name);
3612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pField->byteOffset = fieldOffset;
3613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fieldOffset += sizeof(u4);
3614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGVV("  --- offset3 '%s'=%d\n",
3615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        pField->field.name, pField->byteOffset);
3616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
3617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    i++;
3618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!found) {
3622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("  +++ inserting pad field in '%s'\n", clazz->descriptor);
3623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fieldOffset += sizeof(u4);
3624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Alignment is good, shuffle any double-wide fields forward, and
3630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * finish assigning field offsets to all fields.
3631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = clazz->ifieldCount - 1;
3634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for ( ; i < clazz->ifieldCount; i++) {
3635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField* pField = &clazz->ifields[i];
3636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != 'D' && c != 'J') {
3639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This isn't a double-wide field; see if any double fields
3640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * follow this one.  If so, we'll move it to this position.
3641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * (quicksort-style partitioning)
3642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (j > i) {
3644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                InstField* doubleField = &clazz->ifields[j--];
3645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                char rc = doubleField->field.signature[0];
3646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (rc == 'D' || rc == 'J') {
3648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /* Here's a double-wide field that follows at least one
3649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * non-double field.  Swap it with the current field.
3650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (When this returns, "pField" points to the reference
3651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * field, and "doubleField" points to the non-double field.)
3652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
3653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    swapField(pField, doubleField);
3654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    c = rc;
3655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
3657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* We may or may not have swapped a field.
3660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* This is a double-wide field, leave it be.
3663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pField->byteOffset = fieldOffset;
3667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("  --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fieldOffset += sizeof(u4);
3669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'J' || c == 'D')
3670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fieldOffset += sizeof(u4);
3671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
3674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure that all reference fields appear before
3675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * non-reference fields, and all double-wide fields are aligned.
3676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    j = 0;  // seen non-ref
3678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
3679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InstField *pField = &clazz->ifields[i];
3680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char c = pField->field.signature[0];
3681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c == 'D' || c == 'J') {
3683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert((pField->byteOffset & 0x07) == 0);
3684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (c != '[' && c != 'L') {
3687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!j) {
3688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(i == clazz->ifieldRefCount);
3689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                j = 1;
3690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (j) {
3692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
3693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!j) {
3696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->ifieldRefCount == clazz->ifieldCount);
3697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
3699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We map a C struct directly on top of java/lang/Class objects.  Make
3702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * sure we left enough room for the instance fields.
3703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->objectSize = fieldOffset;
3708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
3711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throw the VM-spec-mandated error when an exception is thrown during
3715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class initialization.
3716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The safest way to do this is to call the ExceptionInInitializerError
3718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constructor that takes a Throwable.
3719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [Do we want to wrap it if the original is an Error rather than
3721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an Exception?]
3722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwClinitError(void)
3724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
3726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
3727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* eiie;
3728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = dvmGetException(self);
3730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddTrackedAlloc(exception, self);
3731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmClearException(self);
3732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
3735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Always resolves to same thing -- no race condition.
3736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
3737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangExceptionInInitializerError =
3738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindSystemClass(
3739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Ljava/lang/ExceptionInInitializerError;");
3740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
3743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.methJavaLangExceptionInInitializerError_init =
3746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "<init>", "(Ljava/lang/Throwable;)V");
3748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto fail;
3751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ALLOC_DEFAULT);
3756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (eiie == NULL)
3757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto fail;
3758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Construct the new object, and replace the exception with it.
3761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
3763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        eiie, &unused, exception);
3765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetException(self, eiie);
3766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(eiie, NULL);
3767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
3768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return;
3769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectfail:       /* restore original exception */
3771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmSetException(self, exception);
3772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
3773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return;
3774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class failed to initialize on a previous attempt, so we want to throw
3778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
3779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * failed in verification, in which case v2 5.4.1 says we need to re-throw
3780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the previous error.
3781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void throwEarlierClassFailure(ClassObject* clazz)
3783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->verifyErrorClass);
3786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->verifyErrorClass == NULL) {
3788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor);
3790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->descriptor);
3793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize any static fields whose values are stored in
3798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the DEX file.  This must be done during class initialization.
3799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void initSFields(ClassObject* clazz)
3801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile;
3804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef;
3805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexEncodedArray* pValueList;
3806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    EncodedArrayIterator iterator;
3807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
3808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount == 0) {
3810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->pDvmDex == NULL) {
3813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* generated class; any static fields should already be set up */
3814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = clazz->pDvmDex->pDexFile;
3818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pClassDef != NULL);
3821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pValueList == NULL) {
3824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
3825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Iterate over the initial values array, setting the corresponding
3831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * static field for each array element.
3832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AnnotationValue value;
3836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StaticField* sfield = &clazz->sfields[i];
3838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* descriptor = sfield->field.signature;
3839364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        bool isObj = false;
3840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! parsed) {
3842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: Eventually verification should attempt to ensure
3844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that this can't happen at least due to a data integrity
3845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * problem.
3846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Static initializer parse failed for %s at index %d",
3848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->descriptor, i);
3849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Verify that the value we got was of a valid type. */
3853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (descriptor[0]) {
3855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'B': parsed = (value.type == kDexAnnotationByte);    break;
3857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'C': parsed = (value.type == kDexAnnotationChar);    break;
3858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'S': parsed = (value.type == kDexAnnotationShort);   break;
3859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'I': parsed = (value.type == kDexAnnotationInt);     break;
3860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'J': parsed = (value.type == kDexAnnotationLong);    break;
3861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'F': parsed = (value.type == kDexAnnotationFloat);   break;
3862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'D': parsed = (value.type == kDexAnnotationDouble);  break;
3863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '[': parsed = (value.type == kDexAnnotationNull);    break;
3864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'L': {
3865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                switch (value.type) {
3866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationNull: {
3867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /* No need for further tests. */
3868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationString: {
3871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/String;") == 0);
3873364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                        isObj = true;
3874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case kDexAnnotationType: {
3877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed =
3878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3879364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                        isObj = true;
3880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    default: {
3883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        parsed = false;
3884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
3885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
3886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
3887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
3890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                parsed = false;
3891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
3892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parsed) {
3896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3897364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes             * All's well, so store the value.
3898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3899364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            if (isObj) {
3900fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmSetStaticFieldObject(sfield, (Object*)value.value.l);
3901fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                dvmReleaseTrackedAlloc((Object*)value.value.l, self);
3902364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes            } else {
3903364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                /*
3904364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * Note: This always stores the full width of a
3905364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * JValue, even though most of the time only the first
3906364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 * word is needed.
3907364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                 */
3908364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes                sfield->value = value.value;
3909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Something up above had a problem. TODO: See comment
3913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * above the switch about verfication.
3914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Bogus static initialization: value type %d in field type "
3916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "%s for %s at index %d",
3917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                value.type, descriptor, clazz->descriptor, i);
3918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
3919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
3922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine whether "descriptor" yields the same class object in the
3926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of clazz1 and clazz2.
3927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The caller must hold gDvm.loadedClasses.
3929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if they match.
3931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool compareDescriptorClasses(const char* descriptor,
3933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
3934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result1;
3936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* result2;
3937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do the first lookup by name.
3940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
3944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can skip a second lookup by name if the second class loader is
3945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the initiating loader list of the class object we retrieved.
3946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (This means that somebody already did a lookup of this class through
3947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the second loader, and it resolved to the same class.)  If it's not
3948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * there, we may simply not have had an opportunity to add it yet, so
3949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we do the full lookup.
3950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The initiating loader test should catch the majority of cases
3952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (in particular, the zillions of references to String/Object).
3953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
3956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For this to work, the superclass/interface should be the first
3957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * argument, so that way if it's from the bootstrap loader this test
3958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will work.  (The bootstrap loader, by definition, never shows up
3959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * as the initiating loader of a class defined by some other loader.)
3960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
3962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
3964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (isInit) {
3966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
3970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
3971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    result1->descriptor, result1,
3973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz2->descriptor, clazz2->classLoader);
3974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
3976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result1 == NULL || result2 == NULL) {
3978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmClearException(dvmThreadSelf());
3979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result1 == result2) {
3980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
3981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Neither class loader could find this class.  Apparently it
3982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * doesn't exist.
3983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We can either throw some sort of exception now, or just
3985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * assume that it'll fail later when something actually tries
3986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to use the class.  For strict handling we should throw now,
3987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * because a "tricky" class loader could start returning
3988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * something later, and a pair of "tricky" loaders could set
3989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * us up for confusion.
3990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
3991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * I'm not sure if we're allowed to complain about nonexistent
3992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * classes in method signatures during class init, so for now
3993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * this will just return "true" and let nature take its course.
3994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
3995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
3996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* only one was found, so clearly they're not the same */
3998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
3999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result1 == result2;
4003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For every component in the method descriptor, resolve the class in the
4007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * context of the two classes and compare the results.
4008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For best results, the "superclass" class should be first.
4010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if the classes match, "false" otherwise.
4012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool checkMethodDescriptorClasses(const Method* meth,
4014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz1, const ClassObject* clazz2)
4015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexParameterIterator iterator;
4017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor;
4018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* walk through the list of parameters */
4020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexParameterIteratorInit(&iterator, &meth->prototype);
4021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
4022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        descriptor = dexParameterIteratorNextDescriptor(&iterator);
4023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor == NULL)
4025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
4026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (descriptor[0] == 'L' || descriptor[0] == '[') {
4028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* non-primitive type */
4029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
4031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* check the return type */
4035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    descriptor = dexProtoGetReturnType(&meth->prototype);
4036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (descriptor[0] == 'L' || descriptor[0] == '[') {
4037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
4038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
4039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
4041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Validate the descriptors in the superclass and interfaces.
4045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * What we need to do is ensure that the classes named in the method
4047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptors in our ancestors and ourselves resolve to the same class
4048cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * objects.  We can get conflicts when the classes come from different
4049cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * class loaders, and the resolver comes up with different results for
4050cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * the same class name in different contexts.
4051cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4052cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * An easy way to cause the problem is to declare a base class that uses
4053cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * class Foo in a method signature (e.g. as the return type).  Then,
4054cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * define a subclass and a different version of Foo, and load them from a
4055cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * different class loader.  If the subclass overrides the method, it will
4056cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * have a different concept of what Foo is than its parent does, so even
4057cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * though the method signature strings are identical, they actually mean
4058cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * different things.
4059cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4060cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * A call to the method through a base-class reference would be treated
4061cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * differently than a call to the method through a subclass reference, which
4062cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * isn't the way polymorphism works, so we have to reject the subclass.
4063cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * If the subclass doesn't override the base method, then there's no
4064cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * problem, because calls through base-class references and subclass
4065cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * references end up in the same place.
4066cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden *
4067cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * We don't need to check to see if an interface's methods match with its
4068cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * superinterface's methods, because you can't instantiate an interface
4069cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and do something inappropriate with it.  If interface I1 extends I2
4070cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and is implemented by C, and I1 and I2 are in separate class loaders
4071cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * and have conflicting views of other classes, we will catch the conflict
4072cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * when we process C.  Anything that implements I1 is doomed to failure,
4073cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden * but we don't need to catch that while processing I1.
4074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, throws an exception and returns "false".
4076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool validateSuperDescriptors(const ClassObject* clazz)
4078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsInterfaceClass(clazz))
4082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
4083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Start with the superclass-declared methods.
4086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL &&
4088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->classLoader != clazz->super->classLoader)
4089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
4090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4091cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * Walk through every overridden method and compare resolved
4092cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * descriptor components.  We pull the Method structs out of
4093cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * the vtable.  It doesn't matter whether we get the struct from
4094cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * the parent or child, since we just need the UTF-8 descriptor,
4095cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden         * which must match.
4096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
4097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to do this even for the stuff inherited from Object,
4098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * because it's possible that the new class loader has redefined
4099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * a basic class like String.
4100e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         *
4101e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         * We don't need to check stuff defined in a superclass because
4102e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden         * it was checked when the superclass was loaded.
4103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* meth;
4105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //printf("Checking %s %p vs %s %p\n",
4107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->descriptor, clazz->classLoader,
4108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //    clazz->super->descriptor, clazz->super->classLoader);
4109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
4110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            meth = clazz->vtable[i];
4111cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden            if (meth != clazz->super->vtable[i] &&
4112cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden                !checkMethodDescriptorClasses(meth, clazz->super, clazz))
4113cab8be0c6e1e9a683402d5a71b037723a6b15bb2Andy McFadden            {
4114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
4115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    meth->name, clazz->descriptor, clazz->classLoader,
4116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    clazz->super->descriptor, clazz->super->classLoader);
4117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmThrowException("Ljava/lang/LinkageError;",
4118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Classes resolve differently in superclass");
4119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
4120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4125e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * Check the methods defined by this class against the interfaces it
4126e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * implements.  If we inherited the implementation from a superclass,
4127e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * we have to check it against the superclass (which might be in a
4128e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * different class loader).  If the superclass also implements the
4129e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * interface, we could skip the check since by definition it was
4130e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden     * performed when the class was loaded.
4131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->iftableCount; i++) {
4133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const InterfaceEntry* iftable = &clazz->iftable[i];
4134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->classLoader != iftable->clazz->classLoader) {
4136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ClassObject* iface = iftable->clazz;
4137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
4138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (j = 0; j < iface->virtualMethodCount; j++) {
4140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const Method* meth;
4141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int vtableIndex;
4142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                vtableIndex = iftable->methodIndexArray[j];
4144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                meth = clazz->vtable[vtableIndex];
4145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4146e7b30940e1459c50b003edb3909eeeb919cab3d5Andy McFadden                if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
4147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Method mismatch: %s in %s (cl=%p) and "
4148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "iface %s (cl=%p)\n",
4149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        meth->name, clazz->descriptor, clazz->classLoader,
4150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        iface->descriptor, iface->classLoader);
4151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmThrowException("Ljava/lang/LinkageError;",
4152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Classes resolve differently in interface");
4153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
4154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
4155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
4160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the class is being initialized by us (which means that
4164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calling dvmInitClass will return immediately after fiddling with locks).
416510cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * Returns false if it's not being initialized, or if it's being
416610cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * initialized by another thread.
4167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
416810cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * The value for initThreadId is always set to "self->threadId", by the
416910cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * thread doing the initializing.  If it was done by the current thread,
417010cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * we are guaranteed to see "initializing" and our thread ID, even on SMP.
417110cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * If it was done by another thread, the only bad situation is one in
417210cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * which we see "initializing" and a stale copy of our own thread ID
417310cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * while another thread is actually handling init.
417410cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden *
417510cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * The initThreadId field is used during class linking, so it *is*
417610cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * possible to have a stale value floating around.  We need to ensure
417710cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden * that memory accesses happen in the correct order.
4178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsClassInitializing(const ClassObject* clazz)
4180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
418110cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    ClassStatus status;
418210cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden
418310cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    status = android_atomic_acquire_load((ClassStatus*) &clazz->status);
418410cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    return (status == CLASS_INITIALIZING &&
4185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->initThreadId == dvmThreadSelf()->threadId);
4186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If a class has not been initialized, do so by executing the code in
4190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <clinit>.  The sequence is described in the VM spec v2 2.17.5.
4191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible for multiple threads to arrive here simultaneously, so
4193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we need to lock the class while we check stuff.  We know that no
4194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code has access to the class yet, so we can use the class's
4195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * monitor lock.
4196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We will often be called recursively, e.g. when the <clinit> code resolves
4198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of its fields, the field resolution will try to initialize the class.
419977514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * In that case we will return "true" even though the class isn't actually
420077514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * ready to go.  The ambiguity can be resolved with dvmIsClassInitializing().
420177514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * (TODO: consider having this return an enum to avoid the extra call --
420277514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * return -1 on failure, 0 on success, 1 on still-initializing.  Looks like
420377514abeade6960daf67f5fec3a865df29ea0256Andy McFadden * dvmIsClassInitializing() is always paired with *Initialized())
4204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can get very interesting if a class has a static field initialized
4206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to a new instance of itself.  <clinit> will end up calling <init> on
4207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the members it is initializing, which is fine unless it uses the contents
4208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of static fields to initialize instance fields.  This will leave the
4209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * static-referenced objects in a partially initialized state.  This is
4210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reasonably rare and can sometimes be cured with proper field ordering.
4211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On failure, returns "false" with an exception raised.
4213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -----
4215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is possible to cause a deadlock by having a situation like this:
4217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class A { static { sleep(10000); new B(); } }
4218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   class B { static { sleep(10000); new A(); } }
4219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new A(); } }.start();
4220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   new Thread() { public void run() { new B(); } }.start();
4221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This appears to be expected under the spec.
4222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The interesting question is what to do if somebody calls Thread.interrupt()
4224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on one of the deadlocked threads.  According to the VM spec, they're both
4225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sitting in "wait".  Should the interrupt code quietly raise the
4226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "interrupted" flag, or should the "wait" return immediately with an
4227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception raised?
4228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This gets a little murky.  The VM spec says we call "wait", and the
4230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec for Thread.interrupt says Object.wait is interruptible.  So it
4231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * seems that, if we get unlucky and interrupt class initialization, we
4232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are expected to throw (which gets converted to ExceptionInInitializerError
4233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * since InterruptedException is checked).
4234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are a couple of problems here.  First, all threads are expected to
4236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * present a consistent view of class initialization, so we can't have it
4237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fail in one thread and succeed in another.  Second, once a class fails
4238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to initialize, it must *always* fail.  This means that a stray interrupt()
4239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call could render a class unusable for the lifetime of the VM.
4240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In most cases -- the deadlock example above being a counter-example --
4242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interrupting thread can't tell whether the target thread handled
4243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization itself or had to wait while another thread did the
4244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work.  Refusing to interrupt class initialization is, in most cases,
4245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not something that a program can reliably detect.
4246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * On the assumption that interrupting class initialization is highly
4248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * undesirable in most circumstances, and that failing to do so does not
4249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * deviate from the spec in a meaningful way, we don't allow class init
4250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to be interrupted by Thread.interrupt().
4251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitClass(ClassObject* clazz)
4253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool initializedByUs = false;
4256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
4259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* method;
4260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockObject(self, (Object*) clazz);
4262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the class hasn't been verified yet, do so now.
4266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status < CLASS_VERIFIED) {
4268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we're in an "erroneous" state, throw an exception and bail.
4270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwEarlierClassFailure(clazz);
4273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_RESOLVED);
4277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             clazz->classLoader == NULL))
4282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
4283d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            /* advance to "verified" state */
4284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("+++ not verifying class %s (cl=%p)\n",
4285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor, clazz->classLoader);
4286d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden            clazz->status = CLASS_VERIFIED;
4287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto noverify;
4288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!gDvm.optimizing)
4291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("+++ late verify on %s\n", clazz->descriptor);
4292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're not supposed to optimize an unverified class, but during
4295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * development this mode was useful.  We can't verify an optimized
4296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * class because the optimization process discards information.
4297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Class '%s' was optimized without verification; "
4300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 "not verifying now\n",
4301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("  ('rm /data/dalvik-cache/*' and restart to fix this)");
4303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto verify_failed;
4304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFYING;
4307228a6b01918304f2cd1213c722e028a6e25252bbAndy McFadden        if (!dvmVerifyClass(clazz)) {
4308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectverify_failed:
4309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4311fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden            dvmSetFieldObject((Object*) clazz,
4312fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden                offsetof(ClassObject, verifyErrorClass),
4313fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden                (Object*) dvmGetException(self)->clazz);
4314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_VERIFIED;
4319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectnoverify:
4321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4322fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    /*
4323fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * We need to ensure that certain instructions, notably accesses to
4324fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * volatile fields, are replaced before any code is executed.  This
4325fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     * must happen even if DEX optimizations are disabled.
4326ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     *
4327ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * The only exception to this rule is that we don't want to do this
4328ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * during dexopt.  We don't generally initialize classes at all
4329ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * during dexopt, but because we're loading classes we need Class and
4330ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * Object (and possibly some Throwable stuff if a class isn't found).
4331ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * If optimizations are disabled, we don't want to output optimized
4332ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * instructions at this time.  This means we will be executing <clinit>
4333ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * code with un-fixed volatiles, but we're only doing it for a few
4334ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden     * system classes, and dexopt runs single-threaded.
4335fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden     */
4336ef22d6fa4d6e574a00669a0d2058c2d7cfa463b1Andy McFadden    if (!IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED) && !gDvm.optimizing) {
4337fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden        LOGV("+++ late optimize on %s (pv=%d)\n",
4338fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden            clazz->descriptor, IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4339fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden        dvmOptimizeClass(clazz, true);
4340fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden        SET_CLASS_FLAG(clazz, CLASS_ISOPTIMIZED);
4341fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    }
4342fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden
4343fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden    /* update instruction stream now that verification + optimization is done */
4344d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden    dvmFlushBreakpoints(clazz);
4345d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden
4346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_INITIALIZED)
4347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (clazz->status == CLASS_INITIALIZING) {
4350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* we caught somebody else in the act; was it us? */
4351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->initThreadId == self->threadId) {
4352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGV("HEY: found a recursive <clinit>\n");
4353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
4357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("GLITCH: exception pending at start of class init\n");
4358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
4359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Wait for the other thread to finish initialization.  We pass
4363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "false" for the "interruptShouldThrow" arg so it doesn't throw
4364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception on interrupt.
4365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * When we wake up, repeat the test for init-in-progress.  If there's
4370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * an exception pending (only possible if "interruptShouldThrow"
4371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * was set), bail out.
4372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
4373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self)) {
4374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Class init of '%s' failing with wait() exception\n",
4375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->descriptor);
4376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: this is bogus, because it means the two threads have a
4378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different idea of the class status.  We need to flag the
4379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class as bad and ensure that the initializer thread respects
4380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * our notice.  If we get lucky and wake up after the class has
4381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * finished initialization but before being woken, we have to
4382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * swallow the exception, perhaps raising thread->interrupted
4383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * to preserve semantics.
4384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
4385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Since we're not currently allowing interrupts, this should
4386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * never happen and we don't need to fix this.
4387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(false);
4389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwClinitError();
4390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_unlock;
4392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_INITIALIZING) {
4394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Waiting again for class init\n");
4395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
4396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(clazz->status == CLASS_INITIALIZED ||
4398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               clazz->status == CLASS_ERROR);
4399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz->status == CLASS_ERROR) {
4400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
4401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The caller wants an exception, but it was thrown in a
4402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * different thread.  Synthesize one here.
4403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
4404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "(<clinit> failed, see exception in other thread)");
4406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* see if we failed previously */
4411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->status == CLASS_ERROR) {
4412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // might be wise to unlock before throwing; depends on which class
4413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // it is that we have locked
4414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockObject(self, (Object*) clazz);
4415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwEarlierClassFailure(clazz);
4416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
4417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4419e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden    u8 startWhen = 0;
4420e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden    if (gDvm.allocProf.enabled) {
4421e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        startWhen = dvmGetRelativeTimeNsec();
4422e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden    }
4423e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden
4424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're ready to go, and have exclusive access to the class.
4426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Before we start initialization, we need to do one extra bit of
4428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * validation: make sure that the methods declared here match up
4429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with our superclass and interfaces.  We know that the UTF-8
4430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * descriptors match, but classes from different class loaders can
4431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have the same name.
4432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We do this now, rather than at load/link time, for the same reason
4434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that we defer verification.
4435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's unfortunate that we need to do this at all, but we risk
4437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * mixing reference types with identical names (see Dalvik test 068).
4438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateSuperDescriptors(clazz)) {
4440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(dvmCheckException(self));
4441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail_unlock;
4443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Let's initialize this thing.
4447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We unlock the object so that other threads can politely sleep on
4449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our mutex with Object.wait(), instead of hanging or spinning trying
4450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to grab our mutex.
4451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(clazz->status < CLASS_INITIALIZING);
4453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // We started initializing.
4456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    logClassLoad('+', clazz);
4457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initializedByUs = true;
4458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446010cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    /* order matters here, esp. interaction with dvmIsClassInitializing */
4461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz->initThreadId = self->threadId;
446210cac709fe47e458cad9a6657a4a89637bac99faAndy McFadden    android_atomic_release_store(CLASS_INITIALIZING, &clazz->status);
4463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init our superclass */
4466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!dvmIsInterfaceClass(clazz));
4468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInitClass(clazz->super)) {
4469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(self));
4470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->status = CLASS_ERROR;
4471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* wake up anybody who started waiting while we were unlocked */
4472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLockObject(self, (Object*) clazz);
4473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail_notify;
4474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Initialize any static fields whose values are
4478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stored in the Dex file.  This should include all of the
4479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * simple "final static" fields, which are required to
4480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * More-complicated final static fields should be set
4482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the beginning of <clinit>;  all we can do is trust
4483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that the compiler did the right thing.
4484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    initSFields(clazz);
4486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Execute any static initialization code.
4488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method == NULL) {
4491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
4495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, method, NULL, &unused);
4496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
4499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
4500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We've had an exception thrown during static initialization.  We
4501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * need to throw an ExceptionInInitializerError, but we want to
4502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * tuck the original exception into the "cause" field.
4503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
450422680eee4aa012c839568d83a132b2b20ff39525Elliott Hughes        LOGW("Exception %s thrown while initializing %s\n",
4505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throwClinitError();
4507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGW("+++ replaced\n");
4508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_ERROR;
4511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* success! */
4513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLockObject(self, (Object*) clazz);
4514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->status = CLASS_INITIALIZED;
4515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("Initialized class: %s\n", clazz->descriptor);
4516e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden
4517e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        /*
4518e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden         * Update alloc counters.  TODO: guard with mutex.
4519e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden         */
4520e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        if (gDvm.allocProf.enabled && startWhen != 0) {
4521e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            u8 initDuration = dvmGetRelativeTimeNsec() - startWhen;
4522e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            gDvm.allocProf.classInitTime += initDuration;
4523e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            self->allocProf.classInitTime += initDuration;
4524e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            gDvm.allocProf.classInitCount++;
4525e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden            self->allocProf.classInitCount++;
4526e15a8eb2653da80c1c3816ddce8186746b57b4a3Andy McFadden        }
4527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_notify:
4530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
4531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Notify anybody waiting on the object.
4532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmObjectNotifyAll(self, (Object*) clazz);
4534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail_unlock:
4536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if LOG_CLASS_LOADING
4538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initializedByUs) {
4539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // We finished initializing.
4540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logClassLoad('-', clazz);
4541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockObject(self, (Object*) clazz);
4545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (clazz->status != CLASS_ERROR);
4547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Replace method->nativeFunc and method->insns with new values.  This is
45511e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * commonly performed after successful resolution of a native method.
45521e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45531e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * There are three basic states:
45541e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (1) (initial) nativeFunc = dvmResolveNativeMethod, insns = NULL
45551e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (2) (internal native) nativeFunc = <impl>, insns = NULL
45561e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *  (3) (JNI) nativeFunc = JNI call bridge, insns = <impl>
45571e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45581e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * nativeFunc must never be NULL for a native method.
45591e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45601e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * The most common transitions are (1)->(2) and (1)->(3).  The former is
45611e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * atomic, since only one field is updated; the latter is not, but since
45621e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * dvmResolveNativeMethod ignores the "insns" field we just need to make
45631e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * sure the update happens in the correct order.
45641e83b4d026199073c057edcb7836d06ae0716390Andy McFadden *
45651e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * A transition from (2)->(1) would work fine, but (3)->(1) will not,
45661e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * because both fields change.  If we did this while a thread was executing
45671e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * in the call bridge, we could null out the "insns" field right before
45681e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * the bridge tried to call through it.  So, once "insns" is set, we do
45691e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * not allow it to be cleared.  A NULL value for the "insns" argument is
45701e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * treated as "do not change existing value".
4571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
45721e83b4d026199073c057edcb7836d06ae0716390Andy McFaddenvoid dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
4573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns)
4574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45771e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    assert(func != NULL);
45781e83b4d026199073c057edcb7836d06ae0716390Andy McFadden
4579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* just open up both; easier that way */
4580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45831e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    if (insns != NULL) {
45841e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        /* update both, ensuring that "insns" is observed first */
45851e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        method->insns = insns;
45861e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        android_atomic_release_store((int32_t) func,
4587fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            (volatile int32_t*)(void*) &method->nativeFunc);
45881e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    } else {
45891e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        /* only update nativeFunc */
45901e83b4d026199073c057edcb7836d06ae0716390Andy McFadden        method->nativeFunc = func;
45911e83b4d026199073c057edcb7836d06ae0716390Andy McFadden    }
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 * Add a RegisterMap to a Method.  This is done when we verify the class
459999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and compute the register maps at class initialization time (i.e. when
460099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * we don't have a pre-generated map).  This means "pMap" is on the heap
460199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and should be freed when the Method is discarded.
4602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = method->clazz;
4606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (method->registerMap != NULL) {
4608d45a88794c6470d96e2139cbe803002d9d5d3a6cAndy McFadden        /* unexpected during class loading, okay on first use (uncompress) */
46099faa9e6a7df9a5b9ef7c8e9d5c07d2a050c319d3Andy McFadden        LOGV("NOTE: registerMap already set for %s.%s\n",
4610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            method->clazz->descriptor, method->name);
4611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* keep going */
4612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
461399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
4614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* might be virtual or direct */
4616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    method->registerMap = pMap;
4620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmHashForeach callback.  A nonzero return value causes foreach to
4627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * bail out.
4628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findClassCallback(void* vclazz, void* arg)
4630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4631fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    ClassObject* clazz = (ClassObject*)vclazz;
4632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor = (const char*) arg;
4633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (strcmp(clazz->descriptor, descriptor) == 0)
4635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (int) clazz;
4636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a loaded class by descriptor. Returns the first one found.
4641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because there can be more than one if class loaders are involved,
4642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this is not an especially good API. (Currently only used by the
4643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * debugger and "checking" JNI.)
4644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "descriptor" should have the form "Ljava/lang/Class;" or
4646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class name.
4648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmFindLoadedClass(const char* descriptor)
4650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
4652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (void*) descriptor);
4656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ClassObject*) result;
4659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Retrieve the system (a/k/a application) class loader.
466350cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden *
466450cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden * The caller must call dvmReleaseTrackedAlloc on the result.
4665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmGetSystemClassLoader(void)
4667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
466850cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    Thread* self = dvmThreadSelf();
4669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz;
4670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* getSysMeth;
4671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader;
4672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL)
4675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
4676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        "()Ljava/lang/ClassLoader;");
4679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (getSysMeth == NULL)
4680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
4681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue result;
468350cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmCallMethod(self, getSysMeth, NULL, &result);
4684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    loader = (Object*)result.l;
468550cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(loader, self);
4686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return loader;
4687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a dvmHashForeach callback.
4692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpClass(void* vclazz, void* varg)
4694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
4696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* super;
4697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int flags = (int) varg;
4698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* desc;
4699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
4702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("dumpClass: ignoring request to dump null class\n");
4703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & kDumpClassFullDetail) == 0) {
4707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showInit = (flags & kDumpClassInitialized) != 0;
4708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool showLoader = (flags & kDumpClassClassLoader) != 0;
4709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* initStr;
4710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (showInit && showLoader)
4714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showInit)
4716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %s\n", clazz->descriptor, initStr);
4717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (showLoader)
4718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
4720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s\n", clazz->descriptor);
4721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
4723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* clazz->super briefly holds the superclass index during class prep */
4726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = clazz->super;
4728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
4729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super = NULL;
4730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmIsInterfaceClass(clazz) ? "interface" : "class",
4733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("  objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super != NULL ? (int) super->objectSize : -1);
4736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("  access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz->accessFlags & JAVA_FLAGS_MASK);
4738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (super != NULL)
4739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmIsArrayClass(clazz)) {
4741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  dimensions=%d elementClass=%s\n",
4742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            clazz->arrayDim, clazz->elementClass->descriptor);
4743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->iftableCount > 0) {
4745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  interfaces (%d):\n", clazz->iftableCount);
4746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->iftableCount; i++) {
4747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InterfaceEntry* ent = &clazz->iftable[i];
4748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int j;
4749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %s (cl=%p)\n",
4751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                i, ent->clazz->descriptor, ent->clazz->classLoader);
4752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* enable when needed */
4754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (false && ent->methodIndexArray != NULL) {
4755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGI("      %2d: %d %s %s\n",
4757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        j, ent->methodIndexArray[j],
4758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        ent->clazz->virtualMethods[j].name,
4759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        clazz->vtable[ent->methodIndexArray[j]]->name);
4760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
4761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsInterfaceClass(clazz)) {
4764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  vtable (%d entries, %d in super):\n", clazz->vtableCount,
4765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super != NULL ? super->vtableCount : 0);
4766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->vtableCount; i++) {
4767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %s%2d: %p %20s %s\n",
4769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->vtable[i]->name, desc);
4772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  direct methods (%d entries):\n", clazz->directMethodCount);
4775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->directMethodCount; i++) {
4776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->directMethods[i].prototype);
4778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->directMethods[i].name,
4779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
4783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  interface methods (%d):\n", clazz->virtualMethodCount);
4784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->virtualMethodCount; i++) {
4785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(
4786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    &clazz->virtualMethods[i].prototype);
4787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %2d %20s %s\n", i,
4788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (u4) clazz->virtualMethods[i].methodIndex,
4789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->virtualMethods[i].name,
4790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                desc);
4791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);
4792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->sfieldCount > 0) {
4795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  static fields (%d entries):\n", clazz->sfieldCount);
4796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->sfieldCount; i++) {
4797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->sfields[i].field.signature);
4799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz->ifieldCount > 0) {
4802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("  instance fields (%d entries):\n", clazz->ifieldCount);
4803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < clazz->ifieldCount; i++) {
4804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("    %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                clazz->ifields[i].field.signature);
4806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a single class.
4813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpClass(const ClassObject* clazz, int flags)
4817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpClass((void*) clazz, (void*) flags);
4819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of all classes.
4823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpAllClasses(int flags)
4825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the number of loaded classes
4833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmGetNumLoadedClasses()
4835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count;
4837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = dvmHashTableNumEntries(gDvm.loadedClasses);
4839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
4841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write some statistics to the log file.
4845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpLoaderStats(const char* msg)
4847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef COUNT_PRECISE_METHODS
4853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("GC precise methods: %d\n",
4854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmPointerSetGetCount(gDvm.preciseMethods));
4855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef PROFILE_FIELD_ACCESS
4859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the field access counts for all fields in this method.
4861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpAccessCounts(void* vclazz, void* varg)
4863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject* clazz = (const ClassObject*) vclazz;
4865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
4866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->ifieldCount; i++) {
4868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Field* field = &clazz->ifields[i].field;
4869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->gets != 0)
4871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("GI %d %s.%s\n", field->gets,
4872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->puts != 0)
4874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("PI %d %s.%s\n", field->puts,
4875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < clazz->sfieldCount; i++) {
4878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Field* field = &clazz->sfields[i].field;
4879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->gets != 0)
4881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("GS %d %s.%s\n", field->gets,
4882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (field->puts != 0)
4884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("PS %d %s.%s\n", field->puts,
4885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                field->clazz->descriptor, field->name);
4886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
4889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the field access counts for all loaded classes.
4893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpFieldAccessCounts(void)
4895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.loadedClasses);
4897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.loadedClasses);
4899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
4901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Method Prototypes and Descriptors
4905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
4906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(). The
4910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name is considered the "major" order and the prototype the "minor"
4911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * order. The prototypes are compared as if by dvmCompareMethodProtos().
4912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndProtos(const Method* method1,
4914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodProtos(method1, method2);
4923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare the two method names and prototypes, a la strcmp(), ignoring
4927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the return value. The name is considered the "major" order and the
4928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * prototype the "minor" order. The prototypes are compared as if by
4929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmCompareMethodArgProtos().
4930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method2)
4933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(method1->name, method2->name);
4935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareMethodParameterProtos(method1, method2);
4941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, prototype) pair with the (name, prototype) of
4945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameProtoAndMethod(const char* name,
4950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexProto* proto, const Method* method)
4951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dexProtoCompare(proto, &method->prototype);
4959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compare a (name, method descriptor) pair with the (name, prototype) of
4963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a method, a la strcmp(). The name is considered the "major" order and
4964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the prototype the "minor" order. The descriptor and prototype are
4965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compared as if by dvmCompareDescriptorAndMethodProto().
4966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
4967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmCompareNameDescriptorAndMethod(const char* name,
4968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* descriptor, const Method* method)
4969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = strcmp(name, method->name);
4971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result != 0) {
4973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
4974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
4975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmCompareDescriptorAndMethodProto(descriptor, method);
4977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
4978