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