Home | History | Annotate | Download | only in code
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.dex.code;
     18 
     19 import com.android.dx.rop.cst.Constant;
     20 import com.android.dx.rop.type.Type;
     21 
     22 import java.util.HashSet;
     23 
     24 /**
     25  * Container for all the pieces of a concrete method. Each instance
     26  * corresponds to a {@code code} structure in a {@code .dex} file.
     27  */
     28 public final class DalvCode {
     29     /**
     30      * how much position info to preserve; one of the static
     31      * constants in {@link PositionList}
     32      */
     33     private final int positionInfo;
     34 
     35     /**
     36      * {@code null-ok;} the instruction list, ready for final processing;
     37      * nulled out in {@link #finishProcessingIfNecessary}
     38      */
     39     private OutputFinisher unprocessedInsns;
     40 
     41     /**
     42      * {@code non-null;} unprocessed catch table;
     43      * nulled out in {@link #finishProcessingIfNecessary}
     44      */
     45     private CatchBuilder unprocessedCatches;
     46 
     47     /**
     48      * {@code null-ok;} catch table; set in
     49      * {@link #finishProcessingIfNecessary}
     50      */
     51     private CatchTable catches;
     52 
     53     /**
     54      * {@code null-ok;} source positions list; set in
     55      * {@link #finishProcessingIfNecessary}
     56      */
     57     private PositionList positions;
     58 
     59     /**
     60      * {@code null-ok;} local variable list; set in
     61      * {@link #finishProcessingIfNecessary}
     62      */
     63     private LocalList locals;
     64 
     65     /**
     66      * {@code null-ok;} the processed instruction list; set in
     67      * {@link #finishProcessingIfNecessary}
     68      */
     69     private DalvInsnList insns;
     70 
     71     /**
     72      * Constructs an instance.
     73      *
     74      * @param positionInfo how much position info to preserve; one of the
     75      * static constants in {@link PositionList}
     76      * @param unprocessedInsns {@code non-null;} the instruction list, ready
     77      * for final processing
     78      * @param unprocessedCatches {@code non-null;} unprocessed catch
     79      * (exception handler) table
     80      */
     81     public DalvCode(int positionInfo, OutputFinisher unprocessedInsns,
     82             CatchBuilder unprocessedCatches) {
     83         if (unprocessedInsns == null) {
     84             throw new NullPointerException("unprocessedInsns == null");
     85         }
     86 
     87         if (unprocessedCatches == null) {
     88             throw new NullPointerException("unprocessedCatches == null");
     89         }
     90 
     91         this.positionInfo = positionInfo;
     92         this.unprocessedInsns = unprocessedInsns;
     93         this.unprocessedCatches = unprocessedCatches;
     94         this.catches = null;
     95         this.positions = null;
     96         this.locals = null;
     97         this.insns = null;
     98     }
     99 
    100     /**
    101      * Finish up processing of the method.
    102      */
    103     private void finishProcessingIfNecessary() {
    104         if (insns != null) {
    105             return;
    106         }
    107 
    108         insns = unprocessedInsns.finishProcessingAndGetList();
    109         positions = PositionList.make(insns, positionInfo);
    110         locals = LocalList.make(insns);
    111         catches = unprocessedCatches.build();
    112 
    113         // Let them be gc'ed.
    114         unprocessedInsns = null;
    115         unprocessedCatches = null;
    116     }
    117 
    118     /**
    119      * Assign indices in all instructions that need them, using the
    120      * given callback to perform lookups. This must be called before
    121      * {@link #getInsns}.
    122      *
    123      * @param callback {@code non-null;} callback object
    124      */
    125     public void assignIndices(AssignIndicesCallback callback) {
    126         unprocessedInsns.assignIndices(callback);
    127     }
    128 
    129     /**
    130      * Gets whether this instance has any position data to represent.
    131      *
    132      * @return {@code true} iff this instance has any position
    133      * data to represent
    134      */
    135     public boolean hasPositions() {
    136         return (positionInfo != PositionList.NONE)
    137             && unprocessedInsns.hasAnyPositionInfo();
    138     }
    139 
    140     /**
    141      * Gets whether this instance has any local variable data to represent.
    142      *
    143      * @return {@code true} iff this instance has any local variable
    144      * data to represent
    145      */
    146     public boolean hasLocals() {
    147         return unprocessedInsns.hasAnyLocalInfo();
    148     }
    149 
    150     /**
    151      * Gets whether this instance has any catches at all (either typed
    152      * or catch-all).
    153      *
    154      * @return whether this instance has any catches at all
    155      */
    156     public boolean hasAnyCatches() {
    157         return unprocessedCatches.hasAnyCatches();
    158     }
    159 
    160     /**
    161      * Gets the set of catch types handled anywhere in the code.
    162      *
    163      * @return {@code non-null;} the set of catch types
    164      */
    165     public HashSet<Type> getCatchTypes() {
    166         return unprocessedCatches.getCatchTypes();
    167     }
    168 
    169     /**
    170      * Gets the set of all constants referred to by instructions in
    171      * the code.
    172      *
    173      * @return {@code non-null;} the set of constants
    174      */
    175     public HashSet<Constant> getInsnConstants() {
    176         return unprocessedInsns.getAllConstants();
    177     }
    178 
    179     /**
    180      * Gets the list of instructions.
    181      *
    182      * @return {@code non-null;} the instruction list
    183      */
    184     public DalvInsnList getInsns() {
    185         finishProcessingIfNecessary();
    186         return insns;
    187     }
    188 
    189     /**
    190      * Gets the catch (exception handler) table.
    191      *
    192      * @return {@code non-null;} the catch table
    193      */
    194     public CatchTable getCatches() {
    195         finishProcessingIfNecessary();
    196         return catches;
    197     }
    198 
    199     /**
    200      * Gets the source positions list.
    201      *
    202      * @return {@code non-null;} the source positions list
    203      */
    204     public PositionList getPositions() {
    205         finishProcessingIfNecessary();
    206         return positions;
    207     }
    208 
    209     /**
    210      * Gets the source positions list.
    211      *
    212      * @return {@code non-null;} the source positions list
    213      */
    214     public LocalList getLocals() {
    215         finishProcessingIfNecessary();
    216         return locals;
    217     }
    218 
    219     /**
    220      * Class used as a callback for {@link #assignIndices}.
    221      */
    222     public static interface AssignIndicesCallback {
    223         /**
    224          * Gets the index for the given constant.
    225          *
    226          * @param cst {@code non-null;} the constant
    227          * @return {@code >= -1;} the index or {@code -1} if the constant
    228          * shouldn't actually be reified with an index
    229          */
    230         public int getIndex(Constant cst);
    231     }
    232 }
    233