1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under 4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution, 5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html 6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: InstrVisitor.java,v 1.1.1.1.2.4 2004/07/16 23:32:28 vlad_r Exp $ 8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.instr; 10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException; 12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.ArrayList; 13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Arrays; 14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Comparator; 15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Iterator; 16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.List; 17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.*; 19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.attribute.*; 20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.constant.CONSTANT_Class_info; 21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.constant.CONSTANT_Long_info; 22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.constant.CONSTANT_Methodref_info; 23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.constant.CONSTANT_String_info; 24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.compiler.CodeGen; 25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.lib.Types; 26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.opcodes.IOpcodes; 27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger; 28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.ByteArrayOStream; 29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IConstants; 30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IntIntMap; 31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IntObjectMap; 32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IntSet; 33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert; 34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants; 35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.ClassDescriptor; 36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.CoverageOptions; 37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetadataConstants; 38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.MethodDescriptor; 39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/** 42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003 43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic 45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class InstrVisitor extends AbstractClassDefVisitor 46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project implements IClassDefVisitor, IAttributeVisitor, IOpcodes, IConstants 47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{ 48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // public: ................................................................ 49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: m_instrument is unused 51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static final class InstrResult 53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public boolean m_instrumented; 55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public ClassDescriptor m_descriptor; 56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public InstrVisitor (final CoverageOptions options) 60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_excludeSyntheticMethods = options.excludeSyntheticMethods (); 62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_excludeBridgeMethods = options.excludeBridgeMethods (); 63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_doSUIDCompensation = options.doSUIDCompensation (); 64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log = Logger.getLogger (); 66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Analyzes 'cls' and/or instruments it for coverage: 70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * <ul> 71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * <li> if 'instrument' is true, the class definition is instrumented for 72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * coverage if that is feasible 73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * <li> if 'metadata' is true, the class definition is analysed 74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * to create a {@link ClassDescriptor} for the original class definition 75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * </ul> 76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This method returns null if 'metadata' is 'false' *or* if 'cls' is an 77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * interface [the latter precludes coverage of interface static 78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * initializers and may be removed in the future].<P> 79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * NOTE: if 'instrument' is 'true', the caller should always assume that 'cls' 81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * has been mutated by this method even if it returned null. The caller should 82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * then revert to the original class definition that was created as a 83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * <code>cls.clone()</code> or by retaining the original definition bytes. 84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This part of contract is for efficienty and also simplifies the implementation. 85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void process (final ClassDef cls, 87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean ignoreAlreadyInstrumented, 88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean instrument, final boolean metadata, 89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final InstrResult out) 90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.m_instrumented = false; 92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.m_descriptor = null; 93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! (instrument || metadata)) return; // nothing to do 95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (cls.isInterface ()) 97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; // skip interfaces [may change in the future] 98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project reset (); 101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cls = cls; 103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: handle classes that cannot be instrumented due to bytecode/JVM limitations 105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_instrument = instrument; 106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_metadata = metadata; 107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_ignoreAlreadyInstrumented = ignoreAlreadyInstrumented; 108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: create 'no instrumentation' execution path here 110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project visit ((ClassDef) null, null); // potentially changes m_instrument and m_metadata 112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_metadata) 114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project setClassName (cls.getName ()); 116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.m_descriptor = new ClassDescriptor (m_classPackageName, m_className, m_classSignature, m_classSrcFileName, m_classMethodDescriptors); 118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.m_instrumented = m_instrument; 121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // IClassDefVisitor: 126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final ClassDef ignore, final Object ctx) 128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef cls = m_cls; 130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String clsVMName = cls.getName (); 131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String clsName = Types.vmNameToJavaName (clsVMName); 132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace1 = m_log.atTRACE1 (); 134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) m_log.trace1 ("visit", "class: [" + clsVMName + "]"); 135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // skip synthetic classes if enabled: 138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (SKIP_SYNTHETIC_CLASSES && cls.isSynthetic ()) 139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_instrument = false; 141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_metadata = false; 142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) m_log.trace1 ("visit", "skipping synthetic class"); 144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: ideally, this check should be done in outer scope somewhere 148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! m_warningIssued && clsName.startsWith (IAppConstants.APP_PACKAGE)) 149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_warningIssued = true; 151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning (IAppConstants.APP_NAME + " classes appear to be included on the instrumentation"); 153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("path: this is not a correct way to use " + IAppConstants.APP_NAME); 154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // field uniqueness check done to detect double instrumentation: 157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] existing = cls.getFields (COVERAGE_FIELD_NAME); 159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (existing.length > 0) 160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_instrument = false; 162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_metadata = false; 163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_ignoreAlreadyInstrumented) 165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) m_log.trace1 ("visit", "skipping instrumented class"); 167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: use a app coded exception 172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("class [" + clsName + "] appears to be instrumented already"); 173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IConstantCollection constants = cls.getConstants (); 178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project SyntheticAttribute_info syntheticMarker = null; 180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // cache the location of "Synthetic" string: 182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_syntheticStringIndex = cls.addCONSTANT_Utf8 (Attribute_info.ATTRIBUTE_SYNTHETIC, true); 185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add a Fieldref for the runtime coverage collector field: 188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note: this is a bit premature if the class has no methods that need 190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // instrumentation 191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: the mutated version is easily discardable; however, this case 192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // needs attention at metadata/report generation level 193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int coverageFieldOffset; 195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String fieldDescriptor = "[[Z"; 196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note that post-4019 builds can modify this field outside of <clinit> (although 198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // it can only happen as part of initializing a set of classes); however, it is legal 199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // to declare this field final: 200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int fieldModifiers = IAccessFlags.ACC_PRIVATE | IAccessFlags.ACC_STATIC | IAccessFlags.ACC_FINAL; 202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add declared field: 204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection fieldAttributes = ElementFactory.newAttributeCollection (1); 207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project syntheticMarker = new SyntheticAttribute_info (m_syntheticStringIndex); 209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fieldAttributes.add (syntheticMarker); 210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project coverageFieldOffset = cls.addField (COVERAGE_FIELD_NAME, fieldDescriptor, 212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fieldModifiers, fieldAttributes); 213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project coverageFieldOffset = cls.addField (COVERAGE_FIELD_NAME, fieldDescriptor, 217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fieldModifiers); 218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //add fieldref: 221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFieldrefIndex = cls.addFieldref (coverageFieldOffset); 222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add a Methodref for Runtime.r(): 225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: compute this without loading Runtime Class? 227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String classJVMName = "com/vladium/emma/rt/RT"; 228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int class_index = cls.addClassref (classJVMName); 229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // NOTE: keep this descriptor in sync with the actual signature 231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String methodDescriptor = "([[ZLjava/lang/String;J)V"; 232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int nametype_index = cls.addNameType ("r", methodDescriptor); 233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_registerMethodrefIndex = constants.add (new CONSTANT_Methodref_info (class_index, nametype_index)); 235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // SF FR 971186: split the init logic into a separate method so it could 238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // be called from regular method headers if necessary: 239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add a Methodref for pre-<clinit> method: 241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // NOTE: keep this descriptor in sync with the actual signature 243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String methodDescriptor = "()[[Z"; 244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int nametype_index = cls.addNameType (PRECLINIT_METHOD_NAME, methodDescriptor); 245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_preclinitMethodrefIndex = constants.add (new CONSTANT_Methodref_info (cls.getThisClassIndex (), nametype_index)); 247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add a CONSTANT_String that corresponds to the class name [in JVM format]: 250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classNameConstantIndex = constants.add (new CONSTANT_String_info (cls.getThisClass ().m_name_index)); 252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit method collection: 255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project visit (cls.getMethods (), ctx); 256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if necessary, do SUID compensation [need to be done after method 258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visits when it is known whether a <clinit> was added]: 259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_doSUIDCompensation) 260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // compensation not necessary if the original clsdef already defined <clinit>: 262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean compensate = ((m_clinitStatus & IMetadataConstants.METHOD_ADDED) != 0); 263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int existingSUIDFieldCount = 0; 265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (compensate) 267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // compensation not necessary if the original clsdef already controlled it via 'serialVersionUID': 269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] existing = cls.getFields (SUID_FIELD_NAME); 271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project existingSUIDFieldCount = existing.length; 272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (existingSUIDFieldCount > 0) 274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IFieldCollection fields = cls.getFields (); 276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int f = 0; f < existingSUIDFieldCount; ++ f) 278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Field_info field = fields.get (existing [f]); 280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((field.getAccessFlags () & (IAccessFlags.ACC_STATIC | IAccessFlags.ACC_FINAL)) 281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project == (IAccessFlags.ACC_STATIC | IAccessFlags.ACC_FINAL)) 282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: should also check for presence of a non-zero initializer 284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project compensate = false; 286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // compensation not necessary if we can determine that this class 293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // does not implement java.io.Serializable/Externalizable: 294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (compensate && (cls.getThisClassIndex () == 0)) // no superclasses [this tool can't traverse inheritance chains] 296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean serializable = false; 298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IInterfaceCollection interfaces = cls.getInterfaces (); 300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = 0, iLimit = interfaces.size (); i < iLimit; ++ i) 301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CONSTANT_Class_info ifc = (CONSTANT_Class_info) constants.get (interfaces.get (i)); 303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String ifcName = ifc.getName (cls); 304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (JAVA_IO_SERIALIZABLE_NAME.equals (ifcName) || JAVA_IO_EXTERNALIZABLE_NAME.equals (ifcName)) 305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project serializable = true; 307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! serializable) compensate = false; 312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (compensate) 316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (existingSUIDFieldCount > 0) 318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if we get here, the class declares a 'serialVersionUID' field 320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // that is not both static and final and/or is not initialized 321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // statically: warn that SUID compensation may not work 322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("class [" + clsName + "] declares a 'serialVersionUID'"); 324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("field that is not static and final: this is likely an implementation mistake"); 325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("and can interfere with " + IAppConstants.APP_NAME + "'s SUID compensation"); 326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String fieldDescriptor = "J"; 329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int fieldModifiers = IAccessFlags.ACC_PRIVATE | IAccessFlags.ACC_STATIC | IAccessFlags.ACC_FINAL; 330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection fieldAttributes = ElementFactory.newAttributeCollection (MARK_ADDED_ELEMENTS_SYNTHETIC ? 2 : 1); 331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int nameIndex = cls.addCONSTANT_Utf8 (Attribute_info.ATTRIBUTE_CONSTANT_VALUE, true); 333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int valueIndex = constants.add (new CONSTANT_Long_info (cls.computeSUID (true))); // ignore the added <clinit> 334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ConstantValueAttribute_info initializer = new ConstantValueAttribute_info (nameIndex, valueIndex); 336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fieldAttributes.add (initializer); 337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (syntheticMarker == null) syntheticMarker = new SyntheticAttribute_info (m_syntheticStringIndex); 341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fieldAttributes.add (syntheticMarker); 342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project cls.addField (SUID_FIELD_NAME, fieldDescriptor, fieldModifiers, fieldAttributes); 345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // if (m_doSUIDCompensation) 348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit class attributes [to get src file name, etc]: 350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project visit (cls.getAttributes (), ctx); 351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final IMethodCollection methods, final Object ctx) 357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef cls = m_cls; 359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace2 = m_log.atTRACE2 (); 361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int originalMethodCount = methods.size (); 363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean constructMetadata = m_metadata; 364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create block count map: TODO: is the extra slot really needed? 366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // - create [potentially unused] slot for added <clinit> 367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockCounts = new int [originalMethodCount + 1]; 368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (constructMetadata) 370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // prepare to collect metadata: 372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockMetadata = new int [originalMethodCount + 1] [] []; // same comments as above 373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors = new MethodDescriptor [originalMethodCount]; 375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit each original method: 379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int m = 0; m < originalMethodCount; ++ m) 381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Method_info method = methods.get (m); 383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodName = method.getName (cls); 384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", (method.isSynthetic () ? "synthetic " : "") + "method #" + m + ": [" + m_methodName + "]"); 385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean isClinit = IClassDefConstants.CLINIT_NAME.equals (m_methodName); 387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: research whether synthetic methods add nontrivially to line coverage or not 389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean excluded = false; 391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! isClinit) 393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_excludeSyntheticMethods && method.isSynthetic ()) 395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project excluded = true; 397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "skipped synthetic method"); 398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (m_excludeBridgeMethods && method.isBridge ()) 400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project excluded = true; 402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "skipped bridge method"); 403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (excluded) 407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (constructMetadata) 409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors [m] = new MethodDescriptor (m_methodName, method.getDescriptor (cls), IMetadataConstants.METHOD_EXCLUDED, m_methodBlockSizes, null, 0); 411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((method.getAccessFlags () & (IAccessFlags.ACC_ABSTRACT | IAccessFlags.ACC_NATIVE)) != 0) 416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (constructMetadata) 418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors [m] = new MethodDescriptor (m_methodName, method.getDescriptor (cls), IMetadataConstants.METHOD_ABSTRACT_OR_NATIVE, m_methodBlockSizes, null, 0); 420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "skipped " + (method.isAbstract () ? "abstract" : "native") + " method"); 423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else // this is a regular, non-<clinit> method that has bytecode: 425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // reset first line: 427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodFirstLine = 0; 428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // set current method ID: 430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodID = m; 431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (isClinit) 433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if <clinit> found: note the ID but delay processing until the very end 435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitID = m; 436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "<clinit> method delayed"); 437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit attributes [skip visit (IAttributeCollection) method]: 441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection attributes = method.getAttributes (); 442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int attributeCount = attributes.size (); 443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0; a < attributeCount; ++ a) 444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Attribute_info attribute = attributes.get (a); 446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attribute.accept (this, ctx); 447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (constructMetadata) 450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_classBlockCounts [m_methodID] > 0, "invalid block count for method " + m_methodID + ": " + m_classBlockCounts [m_methodID]); 452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_methodBlockSizes != null && m_methodBlockSizes.length == m_classBlockCounts [m_methodID], "invalid block sizes map for method " + m_methodID); 453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [][] methodBlockMetadata = m_classBlockMetadata [m_methodID]; 455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int status = (methodBlockMetadata == null ? IMetadataConstants.METHOD_NO_LINE_NUMBER_TABLE : 0); 456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors [m] = new MethodDescriptor (m_methodName, method.getDescriptor (cls), status, m_methodBlockSizes, methodBlockMetadata, m_methodFirstLine); 458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add <clinit> (and instrument if needed) [a <clinit> is always needed 465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // even if there are no other instrumented method to act as a load hook]: 466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean instrumentClinit = false; // TODO: make use of this [to limit instrumentation to clinitHeader only], take into account whether we added and whether it is synthetic 468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Method_info clinit; 469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_clinitID >= 0) 471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // <clinit> existed in the original class: needs to be covered 473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // m_clinitStatus = 0; 475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clinit = methods.get (m_clinitID); 476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classInstrMethodCount = originalMethodCount; 478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // there is no <clinit> defined by the original class: add one [and mark it synthetic] 482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitStatus = IMetadataConstants.METHOD_ADDED; // mark as added by us 484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int attribute_name_index = cls.addCONSTANT_Utf8 (Attribute_info.ATTRIBUTE_CODE, true); 486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int name_index = cls.addCONSTANT_Utf8 (IClassDefConstants.CLINIT_NAME, true); 487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int descriptor_index = cls.addCONSTANT_Utf8 ("()V", true); 488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection attributes; 490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes = ElementFactory.newAttributeCollection (2); 493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes = ElementFactory.newAttributeCollection (1); 495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CodeAttribute_info code = new CodeAttribute_info (attribute_name_index, 497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0, 0, 498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project new byte [] {(byte) _return}, 499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project AttributeElementFactory.newExceptionHandlerTable (0), 500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ElementFactory.newAttributeCollection (0)); 501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes.add (code); 503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes.add (new SyntheticAttribute_info (m_syntheticStringIndex)); 507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clinit = new Method_info (IAccessFlags.ACC_STATIC | IAccessFlags.ACC_PRIVATE, name_index, descriptor_index, attributes); 510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitID = cls.addMethod (clinit); 512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "added synthetic <clinit> method"); 514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: this should exclude <clinit> if it were added by us 516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classInstrMethodCount = originalMethodCount + 1; 517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_classInstrMethodCount >= 0, 520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "m_classInstrMethodCount not set"); 521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit <clinit>: 524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodFirstLine = 0; 526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodID = m_clinitID; 527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", (clinit.isSynthetic () ? "synthetic " : "") + "method #" + m_methodID + ": [<clinit>]"); 529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection attributes = clinit.getAttributes (); 531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int attributeCount = attributes.size (); 532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0; a < attributeCount; ++ a) 533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Attribute_info attribute = attributes.get (a); 535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attribute.accept (this, ctx); 536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add pre-<clinit> method: 540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int attribute_name_index = cls.addCONSTANT_Utf8 (Attribute_info.ATTRIBUTE_CODE, true); 543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int name_index = cls.addCONSTANT_Utf8 (PRECLINIT_METHOD_NAME, false); 544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int descriptor_index = cls.addCONSTANT_Utf8 ("()[[Z", false); 545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection attributes; 547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes = ElementFactory.newAttributeCollection (2); 550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes = ElementFactory.newAttributeCollection (1); 552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream buf = new ByteArrayOStream (PRECLINIT_INIT_CAPACITY); 554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] blockCounts = m_classBlockCounts; 556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int instrMethodCount = m_classInstrMethodCount; // actual number of methods to instrument may be less than the size of the block map 557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (blockCounts != null && blockCounts.length >= instrMethodCount, 559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "invalid block count map"); 560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // new and set COVERAGE_FIELD: 562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push first dimension: 564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, instrMethodCount); 565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // new boolean [][]: 569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int type_index = cls.addClassref ("[[Z"); 570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write4 (_multianewarray, 571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project type_index >>> 8, // indexbyte1 572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project type_index, // indexbyte2 573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1); // only one dimension created here 574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clone array ref: 578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write4 (_dup, 579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // store in the static field 583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _putstatic, 584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFieldrefIndex >>> 8, // indexbyte1 585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFieldrefIndex); // indexbyte2 586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int m = 0; m < instrMethodCount; ++ m) 590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int blockCount = blockCounts [m]; 592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (blockCount > 0) 593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clone array ref: 595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write (_dup); 596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push outer dim index: 600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, m); 601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +3] 603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push dim: 605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, blockCount); 606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +4] 608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // newarray boolean []: 610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write3 (_newarray, 611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 4, // "T_BOOLEAN" 612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add subarray to the outer array: 614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _aastore); 615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clone array ref 624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write (_dup); 625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_constant_index (buf, m_classNameConstantIndex); 629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +3] 631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write3 (_ldc2_w, 633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_stampIndex >>> 8, // indexbyte1 634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_stampIndex); // indexbyte2 635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +5] 637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write3 (_invokestatic, 639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_registerMethodrefIndex >>> 8, // indexbyte1 640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_registerMethodrefIndex); // indexbyte2 641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // pop and return extra array ref: 646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write (_areturn); 647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +0] 649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CodeAttribute_info code = new CodeAttribute_info (attribute_name_index, 652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 5, 0, // adjust constants if the bytecode emitted above changes 653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMPTY_BYTE_ARRAY, 654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project AttributeElementFactory.newExceptionHandlerTable (0), 655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ElementFactory.newAttributeCollection (0)); 656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project code.setCode (buf.getByteArray (), buf.size ()); 658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes.add (code); 660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (MARK_ADDED_ELEMENTS_SYNTHETIC) 662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes.add (new SyntheticAttribute_info (m_syntheticStringIndex)); 664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Method_info preclinit = new Method_info (IAccessFlags.ACC_STATIC | IAccessFlags.ACC_PRIVATE, name_index, descriptor_index, attributes); 667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project cls.addMethod (preclinit); 668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "added synthetic pre-<clinit> method"); 670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (constructMetadata) 674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_classBlockCounts [m_methodID] > 0, "invalid block count for method " + m_methodID + " (" + IClassDefConstants.CLINIT_NAME + "): " + m_classBlockCounts [m_methodID]); 676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_methodBlockSizes != null && m_methodBlockSizes.length == m_classBlockCounts [m_methodID], "invalid block sizes map for method " + m_methodID); 677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [][] methodBlockMetadata = m_classBlockMetadata [m_methodID]; 679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitStatus |= (methodBlockMetadata == null ? IMetadataConstants.METHOD_NO_LINE_NUMBER_TABLE : 0); 680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: this still does not process not added/synthetic case 682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_clinitStatus & IMetadataConstants.METHOD_ADDED) == 0) 684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors [m_methodID] = new MethodDescriptor (IClassDefConstants.CLINIT_NAME, clinit.getDescriptor (cls), m_clinitStatus, m_methodBlockSizes, methodBlockMetadata, m_methodFirstLine); 685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final IAttributeCollection attributes, Object ctx) 692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0, aCount = attributes.size (); a < aCount; ++ a) 694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: define a global way to set the mask set of attrs to be visited 696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attributes.get (a).accept (this, ctx); 697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // IAttributeVisitor: 704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final CodeAttribute_info attribute, final Object ctx) 706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace2 = m_log.atTRACE2 (); 708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace3 = m_log.atTRACE3 (); 709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] code = attribute.getCode (); 711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int codeSize = attribute.getCodeSize (); 712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "code attribute for method #" + m_methodID + ": size = " + codeSize); 714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IntSet leaders = new IntSet (); 716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // instructionMap.get(ip) is the number of instructions in code[0-ip) 718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [this map will include a mapping for code length as well] 719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IntIntMap /* int(ip)->instr count */ instructionMap = new IntIntMap (); 720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add first instruction and all exc handler start pcs: 722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (0); 723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IExceptionHandlerTable exceptions = attribute.getExceptionTable (); 725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int exceptionCount = exceptions.size (); 726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int e = 0; e < exceptionCount; ++ e) 727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Exception_info exception = exceptions.get (e); 729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (exception.m_handler_pc); 730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IntObjectMap branches = new IntObjectMap (); 734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // determine block leaders [an O(code length) loop]: 736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean branch = false; 738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean wide = false; 739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int instructionCount = 0; 741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instructionMap.put (0, 0); 742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int ip = 0; ip < codeSize; ) 744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int opcode = 0xFF & code [ip]; 746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int size = 0; // will be set to -<real size> for special cases in the switch below 747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //if (trace3) m_log.trace3 ("parse", MNEMONICS [opcode]); 749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // "visitor.visit (opcode, wide, ip, null)": 750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { // "opcode visit" logic: 752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int iv, ov; 754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (branch) 756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // previous instruction was a branch: this one is a leader 758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (ip); 759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = false; 760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project switch (opcode) 763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifeq: 765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _iflt: 766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifle: 767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifne: 768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifgt: 769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifge: 770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifnull: 771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ifnonnull: 772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmpeq: 773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmpne: 774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmplt: 775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmpgt: 776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmple: 777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_icmpge: 778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_acmpeq: 779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _if_acmpne: 780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //ov = getI2 (code, ip + 1); 782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 1; 783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [scan] << 8) | (0xFF & code [++ scan]); 784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int target = ip + ov; 786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (target); 787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new IFJUMP2 (opcode, target)); 789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _goto: 795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _jsr: 796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //ov = getI2 (code, ip + 1); 798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 1; 799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [scan] << 8) | (0xFF & code [++ scan]); 800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int target = ip + ov; 802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (target); 803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new JUMP2 (opcode, target)); 805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _lookupswitch: 811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 4 - (ip & 3); // eat padding 813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 814f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 815f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (ip + ov); 816f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 817f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //final int npairs = getU4 (code, scan); 818f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //scan += 4; 819f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int npairs = ((0xFF & code [++ scan]) << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 820f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 821f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] keys = new int [npairs]; 822f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] targets = new int [npairs + 1]; 823f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project targets [0] = ip + ov; 824f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 825f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0; p < npairs; ++ p) 826f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 827f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //iv = getI4 (code, scan); 828f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //scan += 4; 829f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project iv = (code [++ scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 830f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project keys [p] = iv; 831f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 832f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 833f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //ov = getI4 (code, scan); 834f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //scan += 4; 835f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [++ scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 836f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project targets [p + 1] = ip + ov; 837f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (ip + ov); 838f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 839f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 840f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new LOOKUPSWITCH (keys, targets)); 841f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 842f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 843f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project size = ip - scan - 1; // special case 844f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 845f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 846f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 847f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 848f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _tableswitch: 849f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 850f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 4 - (ip & 3); // eat padding 851f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 852f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 853f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (ip + ov); 854f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 855f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //final int low = getI4 (code, scan + 4); 856f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int low = (code [++ scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 857f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //final int high = getI4 (code, scan + 8); 858f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //scan += 12; 859f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int high = (code [++ scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 860f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 861f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] targets = new int [high - low + 2]; 862f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project targets [0] = ip + ov; 863f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 864f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int index = low; index <= high; ++ index) 865f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 866f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //ov = getI4 (code, scan); 867f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [++ scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 868f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project targets [index - low + 1] = ip + ov; 869f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (ip + ov); 870f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //scan += 4; 871f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 872f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 873f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new TABLESWITCH (low, high, targets)); 874f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 875f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 876f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project size = ip - scan - 1; // special case 877f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 878f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 879f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 880f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 881f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _goto_w: 882f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _jsr_w: 883f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 884f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 1; 885f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //ov = getI4 (code, ip + 1); 886f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ov = (code [scan] << 24) | ((0xFF & code [++ scan]) << 16) | ((0xFF & code [++ scan]) << 8) | (0xFF & code [++ scan]); 887f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int target = ip + ov; 888f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 889f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.add (target); 890f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 891f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new JUMP4 (opcode, target)); 892f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 893f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 894f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 895f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 896f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 897f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ret: 898f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 899f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int scan = ip + 1; 900f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project iv = wide ? (((0xFF & code [scan]) << 8) | (0xFF & code [++ scan])) : (0xFF & code [scan]); 901f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 902f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new RET (opcode, iv)); 903f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 904f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 905f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 906f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 907f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 908f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _athrow: 909f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _ireturn: 910f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _lreturn: 911f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _freturn: 912f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _dreturn: 913f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _areturn: 914f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case _return: 915f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 916f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branches.put (ip, new TERMINATE (opcode)); 917f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branch = true; 918f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 919f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 920f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 921f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of switch 922f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 923f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of processing the current opcode 924f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 925f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 926f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // shift to the next instruction [this is the only block that adjusts 'ip']: 927f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 928f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (size == 0) 929f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project size = (wide ? WIDE_SIZE : NARROW_SIZE) [opcode]; 930f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 931f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project size = -size; 932f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 933f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ip += size; 934f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project wide = (opcode == _wide); 935f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 936f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instructionMap.put (ip, ++ instructionCount); 937f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 938f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of for 939f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 940f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 941f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // split 'code' into an ordered list of basic blocks [O(block count) loops]: 942f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 943f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int blockCount = leaders.size (); 944f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "method contains " + blockCount + " basic blocks"); 945f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 946f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final BlockList blocks = new BlockList (blockCount); 947f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 948f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] _leaders = new int [blockCount + 1]; // room for end-of-code leader at the end 949f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaders.values (_leaders, 0); 950f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _leaders [blockCount] = codeSize; 951f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 952f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Arrays.sort (_leaders); 953f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 954f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] _branch_locations = branches.keys (); 955f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Arrays.sort (_branch_locations); 956f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 957f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IntIntMap leaderToBlockID = new IntIntMap (_leaders.length); 958f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 959f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_metadata) 960f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 961f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // help construct a MethodDescriptor for the current method: 962f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 963f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodBlockSizes = new int [blockCount]; 964f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodBlockOffsets = _leaders; 965f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 966f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 967f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // compute signature even if metadata is not needed (because the instrumented 968f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // classdef uses it): 969f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project consumeSignatureData (m_methodID, _leaders); 970f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 971f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // pass 1: 972f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 973f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] intHolder = new int [1]; 974f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int instr_count = 0, prev_instr_count; 975f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 976f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int bl = 0, br = 0; bl < blockCount; ++ bl) 977f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 978f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Block block = new Block (); 979f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blocks.m_blocks.add (block); 980f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 981f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int leader = _leaders [bl]; 982f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 983f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_first = leader; // m_first set 984f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaderToBlockID.put (leader, bl); 985f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 986f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int next_leader = _leaders [bl + 1]; 987f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean branchDelimited = false; 988f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 989f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project prev_instr_count = instr_count; 990f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 991f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_branch_locations.length > br) 992f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 993f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int next_branch_location = _branch_locations [br]; 994f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (next_branch_location < next_leader) 995f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 996f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project branchDelimited = true; 997f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 998f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_length = next_branch_location - leader; // m_length set 999f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1000f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 1001f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (instructionMap.get (next_branch_location, intHolder), "no mapping for " + next_branch_location); 1002f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1003f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instructionMap.get (next_branch_location, intHolder); 1004f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1005f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instr_count = intHolder [0] + 1; // [+ 1 for the branch] 1006f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1007f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_branch = (Branch) branches.get (next_branch_location); 1008f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_branch.m_parentBlockID = bl; // m_branch set 1009f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1010f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ br; 1011f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1012f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1013f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1014f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! branchDelimited) 1015f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1016f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_length = next_leader - leader; // m_length set 1017f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1018f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 1019f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (instructionMap.get (next_leader, intHolder), "no mapping for " + next_leader); 1020f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1021f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instructionMap.get (next_leader, intHolder); 1022f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1023f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project instr_count = intHolder [0]; 1024f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1025f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1026f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_instrCount = instr_count - prev_instr_count; // m_instrCount set 1027f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1028f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (block.m_length == 0 || block.m_instrCount > 0, "invalid instr count for block " + bl + ": " + block.m_instrCount); 1029f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_metadata) m_methodBlockSizes [bl] = block.m_instrCount; 1030f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1031f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1032f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // pass 2: 1033f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1034f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Block [] _blocks = (Block []) blocks.m_blocks.toArray (new Block [blockCount]); 1035f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1036f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < blockCount; ++ l) 1037f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1038f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Block block = _blocks [l]; 1039f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1040f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (block.m_branch != null) 1041f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1042f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] targets = block.m_branch.m_targets; 1043f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (targets != null) 1044f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1045f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int t = 0, targetCount = targets.length; t < targetCount; ++ t) 1046f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1047f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: HACK ! convert block absolute offsets to block IDs: 1048f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1049f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 1050f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (leaderToBlockID.get (targets [t], intHolder), "no mapping for " + targets [t]); 1051f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1052f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project leaderToBlockID.get (targets [t], intHolder); 1053f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1054f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project targets [t] = intHolder [0]; 1055f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1056f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1057f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1058f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1059f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1060f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1061f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // update block count map [used later by <clinit> visit]: 1062f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockCounts [m_methodID] = blockCount; 1063f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1064f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // actual basic block instrumentation: 1065f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1066f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "instrumenting... "); 1067f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1068f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // determine the local var index for the var that will alias COVERAGE_FIELD: 1069f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int localVarIndex = attribute.m_max_locals ++; 1070f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1071f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_methodID == m_clinitID) // note: m_clinitID can be -1 if <clinit> has not been visited yet 1072f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1073f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // add a long stamp constant after all the original methods have been visited: 1074f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1075f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_stampIndex = m_cls.getConstants ().add (new CONSTANT_Long_info (m_classSignature)); 1076f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1077f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blocks.m_header = new clinitHeader (this, localVarIndex); 1078f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1079f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1080f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blocks.m_header = new methodHeader (this, localVarIndex); 1081f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1082f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int headerMaxStack = blocks.m_header.maxstack (); 1083f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int methodMaxStack = 0; 1084f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1085f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < blockCount; ++ l) 1086f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1087f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Block block = _blocks [l]; 1088f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1089f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CodeSegment insertion = new BlockSegment (this, localVarIndex, l); 1090f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.m_insertion = insertion; 1091f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1092f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int insertionMaxStack = insertion.maxstack (); 1093f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (insertionMaxStack > methodMaxStack) 1094f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project methodMaxStack = insertionMaxStack; 1095f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1096f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1097f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // update maxstack as needed [it can only grow]: 1098f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1099f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int oldMaxStack = attribute.m_max_stack; 1100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attribute.m_max_stack += methodMaxStack; // this is not precise, but still need to add because the insertion may be happening at the old maxstack point 1102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (headerMaxStack > attribute.m_max_stack) 1104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attribute.m_max_stack = headerMaxStack; 1105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace3) m_log.trace3 ("visit", "increasing maxstack by " + (attribute.m_max_stack - oldMaxStack)); 1107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (blocks.m_header != null, "header not set"); 1110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // assemble all blocks into an instrumented code block: 1114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "assembling... "); 1115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int newcodeCapacity = codeSize << 1; 1117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (newcodeCapacity < EMIT_CTX_MIN_INIT_CAPACITY) newcodeCapacity = EMIT_CTX_MIN_INIT_CAPACITY; 1118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream newcode = new ByteArrayOStream (newcodeCapacity); // TODO: empirical capacity 1120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final EmitCtx emitctx = new EmitCtx (blocks, newcode); 1121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create a jump adjustment map: 1123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] jumpAdjOffsets = new int [blockCount]; // room for initial 0 + (blockCount - 1) 1124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] jumpAdjMap = new int [jumpAdjOffsets.length]; // room for initial 0 + (blockCount - 1) 1125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (jumpAdjOffsets.length == jumpAdjMap.length, 1127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "jumpAdjOffsets and jumpAdjMap length mismatch"); 1128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // header: 1130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blocks.m_header.emit (emitctx); 1131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // jumpAdjOffsets [0] = 0: redundant 1132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpAdjMap [0] = emitctx.m_out.size (); 1133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // rest of blocks: 1135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < blockCount; ++ l) 1136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Block block = _blocks [l]; 1138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (l + 1 < blockCount) 1140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpAdjOffsets [l + 1] = _blocks [l].m_first + _blocks [l].m_length; // implies the insertion goes just before the branch 1142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project block.emit (emitctx, code); 1145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: this breaks if code can shrink: 1147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (l + 1 < blockCount) 1148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpAdjMap [l + 1] = emitctx.m_out.size () - _blocks [l + 1].m_first; 1150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodJumpAdjOffsets = jumpAdjOffsets; 1154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodJumpAdjValues = jumpAdjMap; 1155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace3) 1157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final StringBuffer s = new StringBuffer ("jump adjustment map:" + EOL); 1159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0; a < jumpAdjOffsets.length; ++ a) 1160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project s.append (" " + jumpAdjOffsets [a] + ": +" + jumpAdjMap [a]); 1162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (a < jumpAdjOffsets.length - 1) s.append (EOL); 1163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.trace3 ("visit", s.toString ()); 1166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] _newcode = newcode.getByteArray (); // note: not cloned 1169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int _newcodeSize = newcode.size (); 1170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [all blocks have had their m_first adjusted] 1172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // backpatching pass: 1174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace3) m_log.trace3 ("visit", "backpatching " + emitctx.m_backpatchQueue.size () + " ip(s)"); 1175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (Iterator i = emitctx.m_backpatchQueue.iterator (); i.hasNext (); ) 1177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] patchData = (int []) i.next (); 1179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int ip = patchData [1]; 1180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (patchData != null, "null patch data for ip " + ip); 1182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int jump = _blocks [patchData [3]].m_first - patchData [2]; 1184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (jump > 0, "negative backpatch jump offset " + jump + " for ip " + ip); 1185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project switch (patchData [0]) 1187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case 4: 1189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _newcode [ip ++] = (byte) (jump >>> 24); 1191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _newcode [ip ++] = (byte) (jump >>> 16); 1192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // *FALL THROUGH* 1194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case 2: 1196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _newcode [ip ++] = (byte) (jump >>> 8); 1198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _newcode [ip] = (byte) jump; 1199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project attribute.setCode (_newcode, _newcodeSize); 1204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "method assembled into " + _newcodeSize + " code bytes"); 1205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // adjust bytecode offsets in the exception table: 1208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IExceptionHandlerTable exceptionTable = attribute.getExceptionTable (); 1209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int e = 0; e < exceptionTable.size (); ++ e) 1210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Exception_info exception = exceptionTable.get (e); 1212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int adjSegment = lowbound (jumpAdjOffsets, exception.m_start_pc); 1214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project exception.m_start_pc += jumpAdjMap [adjSegment]; 1215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project adjSegment = lowbound (jumpAdjOffsets, exception.m_end_pc); 1217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project exception.m_end_pc += jumpAdjMap [adjSegment]; 1218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project adjSegment = lowbound (jumpAdjOffsets, exception.m_handler_pc); 1220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project exception.m_handler_pc += jumpAdjMap [adjSegment]; 1221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // visit other nested attributes [LineNumberAttribute, etc]: 1225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IAttributeCollection attributes = attribute.getAttributes (); 1226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int attributeCount = attributes.size (); 1227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0; a < attributeCount; ++ a) 1228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Attribute_info nested = attributes.get (a); 1230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project nested.accept (this, ctx); 1231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final LineNumberTableAttribute_info attribute, final Object ctx) 1238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace2 = m_log.atTRACE2 (); 1240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace3 = m_log.atTRACE3 (); 1241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "attribute: [" + attribute.getName (m_cls) + "]"); 1242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int lineCount = attribute.size (); 1244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_metadata) 1246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) m_log.trace2 ("visit", "processing line number table for metadata..."); 1248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int blockCount = m_classBlockCounts [m_methodID]; 1250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (blockCount > 0, "invalid method block count for method " + m_methodID); 1251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [][] blockLineMap = new int [blockCount][]; 1253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (blockCount + 1 == m_methodBlockOffsets.length, 1255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "invalid m_methodBlockOffsets"); 1256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (lineCount == 0) 1258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int bl = 0; bl < blockCount; ++ bl) 1260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blockLineMap [bl] = EMPTY_INT_ARRAY; 1261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: this code does not work if there are multiple LineNumberTableAttribute attributes for the method 1265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final LineNumber_info [] sortedLines = new LineNumber_info [attribute.size ()]; 1267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < lineCount; ++ l) 1269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final LineNumber_info line = attribute.get (l); 1271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project sortedLines [l] = line; 1272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Arrays.sort (sortedLines, LINE_NUMBER_COMPARATOR); 1275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // construct block->line mapping: TODO: is the loop below the fastest it can be done? 1277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] methodBlockOffsets = m_methodBlockOffsets; 1279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project LineNumber_info line = sortedLines [0]; // never null 1281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project LineNumber_info prev_line = null; 1282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // remember the first line: 1284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodFirstLine = line.m_line_number; 1285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int bl = 0, l = 0; bl < blockCount; ++ bl) 1287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IntSet blockLines = new IntSet (); 1289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((prev_line != null) && (line.m_start_pc > methodBlockOffsets [bl])) 1291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blockLines.add (prev_line.m_line_number); 1293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project while (line.m_start_pc < methodBlockOffsets [bl + 1]) 1296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blockLines.add (line.m_line_number); 1298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (l == lineCount - 1) 1300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 1301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project prev_line = line; 1304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project line = sortedLines [++ l]; // advance to the next line 1305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project blockLineMap [bl] = blockLines.values (); 1309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockMetadata [m_methodID] = blockLineMap; 1313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace3) 1315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project StringBuffer s = new StringBuffer ("block-line map for method #" + m_methodID + ":"); 1317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int bl = 0; bl < blockCount; ++ bl) 1318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project s.append (EOL); 1320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project s.append (" block " + bl + ": "); 1321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] lines = blockLineMap [bl]; 1323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < lines.length; ++ l) 1324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (l != 0) s.append (", "); 1326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project s.append (lines [l]); 1327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.trace3 ("visit", s.toString ()); 1331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int l = 0; l < lineCount; ++ l) 1335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final LineNumber_info line = attribute.get (l); 1337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: make this faster using either table assist or the sorted array in 'sortedLines' 1339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // adjust bytecode offset for line number mapping: 1341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int adjSegment = lowbound (m_methodJumpAdjOffsets, line.m_start_pc); 1342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project line.m_start_pc += m_methodJumpAdjValues [adjSegment]; 1343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: line var table as well 1349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // no-op visits: 1352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final ExceptionsAttribute_info attribute, final Object ctx) 1354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final ConstantValueAttribute_info attribute, final Object ctx) 1359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final SourceFileAttribute_info attribute, final Object ctx) 1364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classSrcFileName = attribute.getSourceFile (m_cls).m_value; 1366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final SyntheticAttribute_info attribute, final Object ctx) 1371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final BridgeAttribute_info attribute, final Object ctx) 1376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final InnerClassesAttribute_info attribute, final Object ctx) 1381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Object visit (final GenericAttribute_info attribute, final Object ctx) 1386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ctx; 1388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // protected: ............................................................. 1391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // package: ............................................................... 1393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // private: ............................................................... 1395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class BlockList 1398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project BlockList () 1400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_blocks = new ArrayList (); 1402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project BlockList (final int capacity) 1405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_blocks = new ArrayList (capacity); 1407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final List /* Block */ m_blocks; // TODO: might as well use an array here? 1410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeSegment m_header; 1411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class Block 1416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int m_first; // inclusive offset of the leader instruction [first instr in the block] 1418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project //int m_last; // exclusive offset of the last non-branch instruction [excludes possible control transfer at the end] 1419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int m_length; // excluding the branch statement [can be 0] 1420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int m_instrCount; // size in instructions, including the [optional] original branch; [m_insertion is not counted] 1421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // NOTE: it is possible that m_first == m_last [the block is empty except for a possible control transfer instr] 1423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// public int maxlength () 1425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// { 1426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// // TODO: cache 1427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// return m_length 1428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//// + (m_insertion != null ? m_insertion.maxlength () : 0) 1429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// + (m_branch != null ? m_branch.maxlength () : 0); 1430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// } 1431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 1433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * When this is called, all previous blocks have been written out and 1434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * their m_first have been updated. 1435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 1436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx, final byte [] code) // TODO: move 'code' into 'ctx' 1437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int first = m_first; 1440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_first = out.size (); // update position to be within new code array 1442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = 0, length = m_length; i < length; ++ i) 1444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (code [first + i]); 1446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_insertion != null) 1449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_insertion.emit (ctx); 1450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_branch != null) 1452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_branch.emit (ctx); 1453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public CodeSegment m_insertion; 1456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public Branch m_branch; // falling through is implied by this being null 1457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class EmitCtx 1462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: profile to check that ByteArrayOStream.write() is not the bottleneck 1464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EmitCtx (final BlockList blocks, final ByteArrayOStream out) 1466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_blocks = blocks; 1468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_out = out; 1469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_backpatchQueue = new ArrayList (); 1471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final BlockList m_blocks; 1474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream m_out; 1475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final List /* int[4] */ m_backpatchQueue; 1476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 1481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * A Branch does not add any maxlocals/maxstack requirements. 1482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 1483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static abstract class Branch 1484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected Branch (final int opcode, final int [] targets) 1486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_opcode = (byte) opcode; 1488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_targets = targets; 1489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 1492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Called when targets are block IDs, before emitting. 1493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 1494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 1; } 1495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project abstract void emit (EmitCtx ctx); 1497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: this method must signal when it is necessary to switch to long jump form 1499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected final void emitJumpOffset2 (final EmitCtx ctx, final int ip, final int targetBlockID) 1500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (targetBlockID <= m_parentBlockID) 1504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // backwards branch: 1506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int jumpOffset = ((Block) ctx.m_blocks.m_blocks.get (targetBlockID)).m_first - ip; 1507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write2 (jumpOffset >>> 8, // targetbyte1 1509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpOffset); // targetbyte2 1510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int jumpOffsetLocation = out.size (); 1514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // else write out zeros and submit for backpatching: 1516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write2 (0, 1517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0); 1518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ctx.m_backpatchQueue.add (new int [] {2, jumpOffsetLocation, ip, targetBlockID}); 1520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected final void emitJumpOffset4 (final EmitCtx ctx, final int ip, final int targetBlockID) 1524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (targetBlockID <= m_parentBlockID) 1528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // backwards branch: 1530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int jumpOffset = ((Block) ctx.m_blocks.m_blocks.get (targetBlockID)).m_first - ip; 1531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (jumpOffset >>> 24, // targetbyte1 1533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpOffset >>> 16, // targetbyte2 1534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpOffset >>> 8, // targetbyte3 1535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project jumpOffset); // targetbyte4 1536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int jumpOffsetLocation = out.size (); 1540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // else write out zeros and submit for backpatching: 1542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (0, 1543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0, 1544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0, 1545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0); 1546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ctx.m_backpatchQueue.add (new int [] {4, jumpOffsetLocation, ip, targetBlockID}); 1548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte m_opcode; 1552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] m_targets; // could be code offsets or block IDs 1553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int m_parentBlockID; 1555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: these could be static instance-pooled 1560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class TERMINATE extends Branch // _[x]return, _athrow 1561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project TERMINATE (final int opcode) 1563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (opcode, null); 1565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int length () { return 1; } 1568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ctx.m_out.write (m_opcode); 1572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class RET extends Branch // [wide] ret 1578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RET (final int opcode, final int varindex) 1580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (opcode, null); 1582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_varindex = varindex; 1583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int length () { return (m_varindex <= 0xFF) ? 2 : 3; } 1586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_varindex <= 0xFF) 1592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write2 (m_opcode, 1594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_varindex); // indexbyte 1595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 1597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (_wide, 1599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_opcode, 1600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_varindex >>> 8, // indexbyte1 1601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_varindex); // indexbyte2 1602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int m_varindex; 1606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class JUMP2 extends Branch // _goto, _jsr 1611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project JUMP2 (final int opcode, final int target) 1613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (opcode, new int [] {target}); 1615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 5; } 1618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int targetBlockID = m_targets [0]; 1623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int ip = out.size (); 1624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: switch to 4-byte long form if jump > 32k 1626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (m_opcode); 1628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset2 (ctx, ip, targetBlockID); 1629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class JUMP4 extends Branch // _goto_w, _jsr_w 1635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project JUMP4 (final int opcode, final int target) 1637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (opcode, new int [] {target}); 1639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 5; } 1642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int targetBlockID = m_targets [0]; 1647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int ip = out.size (); 1648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (m_opcode); 1650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset4 (ctx, ip, targetBlockID); 1651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class IFJUMP2 extends Branch // _ifxxx 1657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IFJUMP2 (final int opcode, final int target) 1659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (opcode, new int [] {target}); 1661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 8; } 1664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int targetBlockID = m_targets [0]; 1669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int ip = out.size (); 1670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: switch to 8-byte long form if jump > 32k 1672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (m_opcode); 1674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset2 (ctx, ip, targetBlockID); 1675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class LOOKUPSWITCH extends Branch 1681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project LOOKUPSWITCH (final int [] keys, final int [] targets /* first one is default */) 1683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (_lookupswitch, targets); 1685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_keys = keys; 1686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 12 + (m_keys.length << 3); } 1689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int ip = out.size (); 1694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (m_opcode); 1696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // padding bytes: 1698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0, padCount = 3 - (ip & 3); p < padCount; ++ p) out.write (0); 1699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // default: 1701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset4 (ctx, ip, m_targets [0]); 1702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // npairs count: 1704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int npairs = m_keys.length; 1705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (npairs >>> 24, // byte1 1706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project npairs >>> 16, // byte2 1707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project npairs >>> 8, // byte3 1708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project npairs); // byte4 1709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // keyed targets: 1711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int t = 1; t < m_targets.length; ++ t) 1712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int key = m_keys [t - 1]; 1714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (key >>> 24, // byte1 1715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project key >>> 16, // byte2 1716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project key >>> 8, // byte3 1717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project key); // byte4 1718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // key target: 1720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset4 (ctx, ip, m_targets [t]); 1721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] m_keys; 1725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class TABLESWITCH extends Branch 1730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project TABLESWITCH (final int low, final int high, final int [] targets /* first one is default */) 1732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (_tableswitch, targets); 1734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_low = low; 1735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_high = high; 1736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxlength () { return 12 + (m_targets.length << 2); } 1739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream out = ctx.m_out; 1743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int ip = out.size (); 1744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: switch to long form for any jump > 32k 1746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (m_opcode); 1748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // padding bytes: 1750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0, padCount = 3 - (ip & 3); p < padCount; ++ p) out.write (0); 1751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // default: 1753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset4 (ctx, ip, m_targets [0]); 1754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // low, high: 1756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int low = m_low; 1757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (low >>> 24, // byte1 1758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project low >>> 16, // byte2 1759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project low >>> 8, // byte3 1760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project low); // byte4 1761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int high = m_high; 1763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write4 (high >>> 24, // byte1 1764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project high >>> 16, // byte2 1765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project high >>> 8, // byte3 1766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project high); // byte4 1767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // targets: 1769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int t = 1; t < m_targets.length; ++ t) 1770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // key target: 1772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project emitJumpOffset4 (ctx, ip, m_targets [t]); 1773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int m_low, m_high; 1777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 1782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * TODO: CodeSegment right now must be 100% position-independent code; 1783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * otherwise it must follow maxlengtt() Branch pattern... 1784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 1785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static abstract class CodeSegment 1786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeSegment (final InstrVisitor visitor) 1788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_visitor = visitor; // TODO: will this field be used? 1790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project abstract int length (); 1793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project abstract int maxstack (); 1794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project abstract void emit (EmitCtx ctx); 1795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final InstrVisitor m_visitor; 1798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class clinitHeader extends CodeSegment 1803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clinitHeader (final InstrVisitor visitor, final int localVarIndex) 1805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (visitor); 1807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream buf = new ByteArrayOStream (CLINIT_HEADER_INIT_CAPACITY); 1808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf = buf; 1809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef cls = visitor.m_cls; 1811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] blockCounts = visitor.m_classBlockCounts; 1813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int instrMethodCount = visitor.m_classInstrMethodCount; // actual number of methods to instrument may be less than the size of the block map 1814f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (blockCounts != null && blockCounts.length >= instrMethodCount, 1815f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "invalid block count map"); 1816f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1817f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int coverageFieldrefIndex = visitor.m_coverageFieldrefIndex; 1818f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int preclinitMethodrefIndex = visitor.m_preclinitMethodrefIndex; 1819f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int classNameConstantIndex = visitor.m_classNameConstantIndex; 1820f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1821f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 1822f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1823f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (coverageFieldrefIndex > 0, "invalid coverageFieldrefIndex"); 1824f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (preclinitMethodrefIndex > 0, "invalid registerMethodrefIndex"); 1825f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (classNameConstantIndex > 0, "invalid classNameConstantIndex"); 1826f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1827f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1828f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // init and load COVERAGE_FIELD: 1829f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write3 (_invokestatic, 1830f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project preclinitMethodrefIndex >>> 8, // indexbyte1 1831f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project preclinitMethodrefIndex); // indexbyte2 1832f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1833f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1834f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1835f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: disable this when there are no real blocks following? 1836f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [in general, use a different template when this method contains a single block] 1837f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1838f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: if this method has been added by us, do not instrument its blocks 1839f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1840f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push int literal equal to 'methodID' [for the parent method]: 1841f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, visitor.m_methodID); 1842f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1843f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 1844f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1845f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push subarray reference: 1846f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write (_aaload); 1847f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1848f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1849f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1850f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // store it in alias var: 1851f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.store_local_object_var (buf, localVarIndex); 1852f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1853f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +0] 1854f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1855f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1856f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int length () { return m_buf.size (); } 1857f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxstack () { return 2; } // note: needs to be updated each time emitted code changes 1858f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1859f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1860f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1861f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: better error handling here? 1862f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 1863f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1864f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf.writeTo (ctx.m_out); 1865f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1866f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 1867f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1868f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (false, ioe.toString ()); 1869f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1870f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1871f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1872f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1873f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final ByteArrayOStream m_buf; 1874f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1875f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int CLINIT_HEADER_INIT_CAPACITY = 32; // covers about 80% of classes (no reallocation) 1876f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1877f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1878f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1879f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1880f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class methodHeader extends CodeSegment 1881f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1882f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project methodHeader (final InstrVisitor visitor, final int localVarIndex) 1883f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1884f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (visitor); 1885f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream buf = new ByteArrayOStream (HEADER_INIT_CAPACITY); 1886f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf = buf; 1887f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1888f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef cls = visitor.m_cls; 1889f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int coverageFieldrefIndex = visitor.m_coverageFieldrefIndex; 1890f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int preclinitMethodrefIndex = visitor.m_preclinitMethodrefIndex; 1891f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1892f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: disable this when there are no real blocks following? 1893f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [in general, use a different template when this method contains a single block] 1894f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1895f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push ref to the static field and dup it: 1896f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write4 (_getstatic, 1897f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project coverageFieldrefIndex >>> 8, // indexbyte1 1898f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project coverageFieldrefIndex, // indexbyte2 1899f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _dup); 1900f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1901f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 1902f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1903f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // SF FR 971186: check if it is null and if so run the field 1904f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // init and class RT register code (only relevant for 1905f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // methods that can be executed ahead of <clinit>) [rare] 1906f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1907f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write3 (_ifnonnull, // skip over pre-<clinit> method call 1908f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 0, 1909f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 3 + /* size of the block below */ 4); 1910f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1911f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1912f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1913f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // block: call pre-<clinit> method 1914f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1915f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write4 (_pop, 1916f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _invokestatic, 1917f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project preclinitMethodrefIndex >>> 8, // indexbyte1 1918f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project preclinitMethodrefIndex); // indexbyte2 1919f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1920f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1921f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1922f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1923f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push int literal equal to 'methodID': 1924f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, visitor.m_methodID); 1925f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1926f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 1927f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1928f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push subarray reference: 1929f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write (_aaload); 1930f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1931f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1932f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1933f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // store it in alias var: 1934f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.store_local_object_var (buf, localVarIndex); 1935f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1936f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +0] 1937f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1938f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1939f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int length () { return m_buf.size (); } 1940f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxstack () { return 2; } // note: needs to be updated each time emitted code changes 1941f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1942f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1943f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1944f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: better error handling here? 1945f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 1946f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1947f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf.writeTo (ctx.m_out); 1948f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1949f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 1950f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1951f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (false, ioe.toString ()); 1952f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1953f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1954f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1955f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1956f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final ByteArrayOStream m_buf; 1957f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1958f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int HEADER_INIT_CAPACITY = 16; 1959f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1960f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 1961f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1962f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1963f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static final class BlockSegment extends CodeSegment 1964f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1965f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public BlockSegment (final InstrVisitor visitor, final int localVarIndex, final int blockID) 1966f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1967f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (visitor); 1968f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ByteArrayOStream buf = new ByteArrayOStream (BLOCK_INIT_CAPACITY); 1969f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf = buf; 1970f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1971f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef cls = visitor.m_cls; 1972f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1973f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push alias var: 1974f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.load_local_object_var (buf, localVarIndex); 1975f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1976f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +1] 1977f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1978f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push int value equal to 'blockID': 1979f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project CodeGen.push_int_value (buf, cls, blockID); 1980f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1981f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +2] 1982f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1983f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // push boolean 'true': 1984f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.write2 (_iconst_1, 1985f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1986f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +3] 1987f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1988f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // store it in the array: 1989f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _bastore); 1990f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1991f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [stack +0] 1992f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1993f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1994f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int length () { return m_buf.size (); } 1995f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int maxstack () { return 3; } // note: needs to be updated each time emitted code changes 1996f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1997f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project void emit (final EmitCtx ctx) 1998f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1999f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: better error handling here? 2000f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 2001f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2002f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_buf.writeTo (ctx.m_out); 2003f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2004f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 2005f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2006f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (false, ioe.toString ()); 2007f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2008f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2009f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2010f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2011f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final ByteArrayOStream m_buf; 2012f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2013f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int BLOCK_INIT_CAPACITY = 16; 2014f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2015f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 2016f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2017f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2018f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class LineNumberComparator implements Comparator 2019f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2020f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final int compare (final Object o1, final Object o2) 2021f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2022f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return ((LineNumber_info) o1).m_start_pc - ((LineNumber_info) o2).m_start_pc; 2023f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2024f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2025f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 2026f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2027f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2028f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2029f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void setClassName (final String fullName) 2030f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2031f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (fullName != null && fullName.length () > 0, 2032f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "null or empty input: fullName"); 2033f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2034f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int lastSlash = fullName.lastIndexOf ('/'); 2035f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (lastSlash < 0) 2036f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2037f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classPackageName = ""; 2038f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_className = fullName; 2039f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2040f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 2041f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2042f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (lastSlash < fullName.length () - 1, 2043f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project "malformed class name [" + fullName + "]"); 2044f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2045f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classPackageName = fullName.substring (0, lastSlash); 2046f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_className = fullName.substring (lastSlash + 1); 2047f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2048f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2049f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2050f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void consumeSignatureData (final int methodID, final int [] basicBlockOffsets) 2051f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2052f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note: by itself, this is not a very good checksum for a class def; 2053f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // however, it is fast to compute and since it will be used along with 2054f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // a class name it should be good at detecting structural changes that 2055f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // matter to us (method and basic block ordering/sizes) 2056f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2057f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int temp1 = basicBlockOffsets.length; 2058f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long temp2 = NBEAST * m_classSignature + (methodID + 1) * temp1; 2059f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2060f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = 1; i < temp1; ++ i) // skip the initial 0 offset 2061f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2062f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project temp2 = NBEAST * temp2 + basicBlockOffsets [i]; 2063f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2064f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2065f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classSignature = temp2; 2066f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2067f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2068f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: use a compilation flag to use table assist here instead of binary search 2069f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // BETTER YET: use binsearch for online mode and table assist for offline [when memory is not an issue] 2070f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2071f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 2072f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Returns the maximum index 'i' such that (values[i] <= x). values[] 2073f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * contains distinct non-negative integers in increasing order. values[0] is 0, 2074f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 'x' is non-negative. 2075f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 2076f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Edge case: 2077f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * returns values.length-1 if values [values.length - 1] < x 2078f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 2079f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static int lowbound (final int [] values, final int x) 2080f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2081f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int low = 0, high = values.length - 1; 2082f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2083f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // assertion: lb is in [low, high] 2084f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2085f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project while (low <= high) 2086f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2087f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int m = (low + high) >> 1; 2088f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int v = values [m]; 2089f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2090f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (v == x) 2091f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m; 2092f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (v < x) 2093f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project low = m + 1; 2094f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else // v > x 2095f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project high = m - 1; 2096f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2097f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2098f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return high; 2099f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void reset () 2102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 2103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: check that all state is reset 2104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_instrument = false; 2106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_metadata = false; 2107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_ignoreAlreadyInstrumented = false; 2108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cls = null; 2110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classPackageName = null; 2111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_className = null; 2112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classSrcFileName = null; 2113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockMetadata = null; 2114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classMethodDescriptors = null; 2115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_syntheticStringIndex = -1; 2117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFieldrefIndex = -1; 2118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_registerMethodrefIndex = -1; 2119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_preclinitMethodrefIndex = -1; 2120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classNameConstantIndex = -1; 2121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitID = -1; 2122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_clinitStatus = 0; 2123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classInstrMethodCount = -1; 2124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classBlockCounts = null; 2125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_classSignature = 0; 2126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodID = -1; 2128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodName = null; 2129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodFirstLine = 0; 2130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodBlockOffsets = null; 2131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodJumpAdjOffsets = null; 2132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_methodJumpAdjValues = null; 2133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 2134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final boolean m_excludeSyntheticMethods; 2137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final boolean m_excludeBridgeMethods; 2138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final boolean m_doSUIDCompensation; 2139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Logger m_log; // instr visitor logging context is latched at construction time 2141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // non-resettable state: 2143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_warningIssued; 2145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // resettable state: 2148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_instrument; 2150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_metadata; 2151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_ignoreAlreadyInstrumented; 2152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ ClassDef m_cls; 2154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String m_classPackageName; // in JVM format [com/vladium/...]; empty string for default package 2155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String m_className; // in JVM format [<init>, <clinit>, etc], relative to 'm_classPackageName' 2156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String m_classSrcFileName; 2157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int [][][] m_classBlockMetadata; // methodID->(blockID->line) map [valid only if 'm_constructMetadata' is true; null if the method has not line number table] 2158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private MethodDescriptor [] m_classMethodDescriptors; 2159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // current class scope: 2161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_syntheticStringIndex; // index of CONSTANT_Utf8 String that reads "Synthetic" 2162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int m_coverageFieldrefIndex; // index of the Fieldref for COVERAGE_FIELD 2163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_registerMethodrefIndex; // index of Methodref for RT.r() 2164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int m_preclinitMethodrefIndex; // index of Methodref for pre-<clinit> method 2165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int m_classNameConstantIndex; // index of CONSTANT_String that is the class name [in JVM format] 2166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_stampIndex; // index of CONSTANT_Long that is the class instr stamp 2167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_clinitID; // offset of <clinit> method [-1 if not determined yet] 2168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_clinitStatus; 2169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int m_classInstrMethodCount; // the number of slots in 'm_classBlockCounts' corresponding to methods to be instrumented for coverage 2170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int [] m_classBlockCounts; // basic block counts for all methods [only valid just before <clinit> is processed] 2171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private long m_classSignature; 2172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // current method scope: 2174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /*private*/ int m_methodID; // offset of current method being instrumented 2175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String m_methodName; 2176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_methodFirstLine; 2177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int [] m_methodBlockOffsets; // [unadjusted] basic block boundaries [length = m_classBlockCounts[m_methodID]+1; the last slot is method bytecode length] 2178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int [] m_methodBlockSizes; 2179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int [] m_methodJumpAdjOffsets; // TODO: length ? 2180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int [] m_methodJumpAdjValues; // TODO: length ? 2181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final long NBEAST = 16661; // prime 2184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String COVERAGE_FIELD_NAME = "$VR" + "c"; 2186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String SUID_FIELD_NAME = "serialVersionUID"; 2187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String PRECLINIT_METHOD_NAME = "$VR" + "i"; 2188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String JAVA_IO_SERIALIZABLE_NAME = "java/io/Serializable"; 2190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String JAVA_IO_EXTERNALIZABLE_NAME = "java/io/Externalizable"; 2191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int EMIT_CTX_MIN_INIT_CAPACITY = 64; // good value determined empirically 2193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int PRECLINIT_INIT_CAPACITY = 128; // covers about 80% of classes (no reallocation) 2194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean MARK_ADDED_ELEMENTS_SYNTHETIC = true; 2195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* It appears that nested classes and interfaces ought to be marked 2197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * as Synthetic; however, neither Sun nor IBM compilers seem to do this. 2198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 2199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * (As a side note, implied no-arg constructors ought to be marked as 2200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * synthetic as well, but Sun's javac is not consistent about that either) 2201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 2202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean SKIP_SYNTHETIC_CLASSES = false; 2203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final LineNumberComparator LINE_NUMBER_COMPARATOR = new LineNumberComparator (); 2205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final byte [] EMPTY_BYTE_ARRAY = new byte [0]; 2207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 2208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class 2209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------