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