summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/rop/code/InsnList.java
blob: 88abd725695002f2fd3ad8757af1656a11b7ee38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.rop.code;

import com.android.dx.util.FixedSizeList;

/**
 * List of {@link Insn} instances.
 */
public final class InsnList
        extends FixedSizeList {
    /**
     * Constructs an instance. All indices initially contain {@code null}.
     *
     * @param size the size of the list
     */
    public InsnList(int size) {
        super(size);
    }

    /**
     * Gets the element at the given index. It is an error to call
     * this with the index for an element which was never set; if you
     * do that, this will throw {@code NullPointerException}.
     *
     * @param n {@code >= 0, < size();} which index
     * @return {@code non-null;} element at that index
     */
    public Insn get(int n) {
        return (Insn) get0(n);
    }

    /**
     * Sets the instruction at the given index.
     *
     * @param n {@code >= 0, < size();} which index
     * @param insn {@code non-null;} the instruction to set at {@code n}
     */
    public void set(int n, Insn insn) {
        set0(n, insn);
    }

    /**
     * Gets the last instruction. This is just a convenient shorthand for
     * {@code get(size() - 1)}.
     *
     * @return {@code non-null;} the last instruction
     */
    public Insn getLast() {
        return get(size() - 1);
    }

    /**
     * Visits each instruction in the list, in order.
     *
     * @param visitor {@code non-null;} visitor to use
     */
    public void forEach(Insn.Visitor visitor) {
        int sz = size();

        for (int i = 0; i < sz; i++) {
            get(i).accept(visitor);
        }
    }

    /**
     * Compares the contents of this {@code InsnList} with another.
     * The blocks must have the same number of insns, and each Insn must
     * also return true to {@code Insn.contentEquals()}.
     *
     * @param b to compare
     * @return true in the case described above.
     */
    public boolean contentEquals(InsnList b) {
        if (b == null) return false;

        int sz = size();

        if (sz != b.size()) return false;

        for (int i = 0; i < sz; i++) {
            if (!get(i).contentEquals(b.get(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * Returns an instance that is identical to this one, except that
     * the registers in each instruction are offset by the given
     * amount. Mutability of the result is inherited from the
     * original.
     *
     * @param delta the amount to offset register numbers by
     * @return {@code non-null;} an appropriately-constructed instance
     */
    public InsnList withRegisterOffset(int delta) {
        int sz = size();
        InsnList result = new InsnList(sz);

        for (int i = 0; i < sz; i++) {
            Insn one = (Insn) get0(i);
            if (one != null) {
                result.set0(i, one.withRegisterOffset(delta));
            }
        }

        if (isImmutable()) {
            result.setImmutable();
        }

        return result;
    }
}