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