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