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// ----------------------------------------------------------------------------