0
|
1 /*
|
|
2 * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 *
|
|
5 * This code is free software; you can redistribute it and/or modify it
|
|
6 * under the terms of the GNU General Public License version 2 only, as
|
|
7 * published by the Free Software Foundation.
|
|
8 *
|
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 * version 2 for more details (a copy is included in the LICENSE file that
|
|
13 * accompanied this code).
|
|
14 *
|
|
15 * You should have received a copy of the GNU General Public License version
|
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 *
|
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.jdi;
|
|
26 import com.sun.jdi.*;
|
|
27
|
|
28 public class LocalVariableImpl extends MirrorImpl
|
|
29 implements LocalVariable, ValueContainer
|
|
30 {
|
|
31 private final Method method;
|
|
32 private final int slot;
|
|
33 private final Location scopeStart;
|
|
34 private final Location scopeEnd;
|
|
35 private final String name;
|
|
36 private final String signature;
|
|
37 private final String genericSignature;
|
|
38
|
|
39 LocalVariableImpl(VirtualMachine vm, Method method,
|
|
40 int slot, Location scopeStart, Location scopeEnd,
|
|
41 String name, String signature, String genericSignature) {
|
|
42 super(vm);
|
|
43 this.method = method;
|
|
44 this.slot = slot;
|
|
45 this.scopeStart = scopeStart;
|
|
46 this.scopeEnd = scopeEnd;
|
|
47 this.name = name;
|
|
48 this.signature = signature;
|
|
49 this.genericSignature = genericSignature;
|
|
50 }
|
|
51
|
|
52 public boolean equals(Object obj) {
|
|
53 if ((obj != null) && (obj instanceof LocalVariableImpl)) {
|
|
54 LocalVariableImpl other = (LocalVariableImpl)obj;
|
|
55 return (method.equals(other.method) &&
|
|
56 slot() == other.slot() &&
|
|
57 super.equals(obj));
|
|
58 } else {
|
|
59 return false;
|
|
60 }
|
|
61 }
|
|
62
|
|
63 public int hashCode() {
|
|
64 /*
|
|
65 * TO DO: Better hash code
|
|
66 */
|
|
67 return (int)method.hashCode() + slot();
|
|
68 }
|
|
69
|
|
70 public int compareTo(Object object) {
|
|
71 LocalVariableImpl other = (LocalVariableImpl)object;
|
|
72 int rc = method.compareTo(other.method);
|
|
73 if (rc == 0) {
|
|
74 rc = slot() - other.slot();
|
|
75 }
|
|
76 return rc;
|
|
77 }
|
|
78
|
|
79 public String name() {
|
|
80 return name;
|
|
81 }
|
|
82
|
|
83 /**
|
|
84 * @return a text representation of the declared type
|
|
85 * of this variable.
|
|
86 */
|
|
87 public String typeName() {
|
|
88 JNITypeParser parser = new JNITypeParser(signature);
|
|
89 return parser.typeName();
|
|
90 }
|
|
91
|
|
92 public Type type() throws ClassNotLoadedException {
|
|
93 return findType(signature());
|
|
94 }
|
|
95
|
|
96 public Type findType(String signature) throws ClassNotLoadedException {
|
|
97 ReferenceTypeImpl enclosing = (ReferenceTypeImpl)method.declaringType();
|
|
98 return enclosing.findType(signature);
|
|
99 }
|
|
100
|
|
101 public String signature() {
|
|
102 return signature;
|
|
103 }
|
|
104
|
|
105 public String genericSignature() {
|
|
106 return genericSignature;
|
|
107 }
|
|
108
|
|
109 public boolean isVisible(StackFrame frame) {
|
|
110 //validateMirror(frame);
|
|
111 Method frameMethod = frame.location().method();
|
|
112
|
|
113 if (!frameMethod.equals(method)) {
|
|
114 throw new IllegalArgumentException(
|
|
115 "frame method different than variable's method");
|
|
116 }
|
|
117
|
|
118 // this is here to cover the possibility that we will
|
|
119 // allow LocalVariables for native methods. If we do
|
|
120 // so we will have to re-examinine this.
|
|
121 if (frameMethod.isNative()) {
|
|
122 return false;
|
|
123 }
|
|
124
|
|
125 return ((scopeStart.compareTo(frame.location()) <= 0)
|
|
126 && (scopeEnd.compareTo(frame.location()) >= 0));
|
|
127 }
|
|
128
|
|
129 public boolean isArgument() {
|
|
130 try {
|
|
131 MethodImpl method = (MethodImpl)scopeStart.method();
|
|
132 return (slot < method.argSlotCount());
|
|
133 } catch (AbsentInformationException e) {
|
|
134 // If this variable object exists, there shouldn't be absent info
|
|
135 throw (InternalException) new InternalException().initCause(e);
|
|
136 }
|
|
137 }
|
|
138
|
|
139 int slot() {
|
|
140 return slot;
|
|
141 }
|
|
142
|
|
143 /*
|
|
144 * Compilers/VMs can have byte code ranges for variables of the
|
|
145 * same names that overlap. This is because the byte code ranges
|
|
146 * aren't necessarily scopes; they may have more to do with the
|
|
147 * lifetime of the variable's slot, depending on implementation.
|
|
148 *
|
|
149 * This method determines whether this variable hides an
|
|
150 * identically named variable; ie, their byte code ranges overlap
|
|
151 * this one starts after the given one. If it returns true this
|
|
152 * variable should be preferred when looking for a single variable
|
|
153 * with its name when both variables are visible.
|
|
154 */
|
|
155 boolean hides(LocalVariable other) {
|
|
156 LocalVariableImpl otherImpl = (LocalVariableImpl)other;
|
|
157 if (!method.equals(otherImpl.method) ||
|
|
158 !name.equals(otherImpl.name)) {
|
|
159 return false;
|
|
160 } else {
|
|
161 return (scopeStart.compareTo(otherImpl.scopeStart) > 0);
|
|
162 }
|
|
163 }
|
|
164
|
|
165 public String toString() {
|
|
166 return name() + " in " + method.toString() +
|
|
167 "@" + scopeStart.toString();
|
|
168 }
|
|
169 }
|