summaryrefslogtreecommitdiff
path: root/src/fjbg/ch/epfl/lamp/fjbg/JMethod.java
blob: 804b4314f26f6f2d6408af03b8366db9c47c08f6 (plain) (blame)
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
131
132
package ch.epfl.lamp.fjbg;

import java.util.LinkedList;
import java.util.Iterator;
import java.io.DataInputStream;
import java.io.IOException;

/**
 * Representation of a Java method.
 *
 * @version 1.0
 * @author Michel Schinz
 */

public class JMethod extends JFieldOrMethod {
    public final static String CLASS_CONSTRUCTOR_NAME = "<clinit>";
    public final static String INSTANCE_CONSTRUCTOR_NAME = "<init>";

    protected final JCode code;
    protected final String[] argNames;

    protected final LinkedList/*<JLocalVariable>*/ localVariables =
        new LinkedList();
    protected int localVariableIndex = 0;

    protected JMethod(FJBGContext context,
                      JClass owner,
                      int accessFlags,
                      String name,
                      JType returnType,
                      JType[] argTypes,
                      String[] argNames) {
        super(context,
              owner,
              accessFlags,
              name,
              new JMethodType(returnType, argTypes));
        this.argNames = argNames;

        assert argTypes.length == argNames.length;

        if (isAbstract() || isNative()) {
            code = null;
        } else {
            JConstantPool pool = owner.getConstantPool();
            code = context.JCode(owner, this);
            addAttribute(context.JCodeAttribute(owner, this));

            if (!isStatic())
                addNewLocalVariable(owner.getType(), "this");

            for (int i = 0; i < argTypes.length; ++i)
                addNewLocalVariable(argTypes[i], argNames[i]);
        }
    }

    protected JMethod(FJBGContext context,
                      JClass owner,
                      DataInputStream stream)
        throws IOException {
        super(context, owner, stream);

        // Fetch code from the attributes.
        setCode: {
            Iterator attrIt = attributes.iterator();
            while (attrIt.hasNext()) {
                Object attr = attrIt.next();
                if (attr instanceof JCodeAttribute) {
                    code = ((JCodeAttribute)attr).code;
                    break setCode;
                }
            }
            code = null;
        }
        argNames = null;        // TODO get from attribute
    }

    public void freeze() throws JCode.OffsetTooBigException {
        if (code != null) code.freeze();
        super.freeze();
    }

    public JType getReturnType() {
        return ((JMethodType)type).getReturnType();
    }

    public JType[] getArgumentTypes() {
        return ((JMethodType)type).getArgumentTypes();
    }

    public String[] getArgumentNames() {
        return argNames;
    }

    public JCode getCode() {
        assert !isAbstract();
        return code;
    }

    public JCodeIterator codeIterator() {
        return new JCodeIterator(code);
    }

    // Local variables
    // FIXME : find a better management method for local variables
    public JLocalVariable addNewLocalVariable(JType type, String name) {
        assert !frozen;
        JLocalVariable var =
            context.JLocalVariable(this, type, name, localVariableIndex);
        localVariableIndex += type.getSize();
        localVariables.add(var);
        return var;
    }

    public JLocalVariable getLocalVariable(int index) {
        for (int i = 0; i < localVariables.size(); i++) {
            if (((JLocalVariable)localVariables.get(i)).index == index)
                return (JLocalVariable)localVariables.get(i);
        }
        return null;
    }

    public JLocalVariable[] getLocalVariables() {
        return (JLocalVariable[])localVariables
            .toArray(new JLocalVariable[localVariables.size()]);
    }

    public int getMaxLocals() {
        return localVariableIndex;
    }
}