1 /* 2 * Copyright (c) 1998, 2017, 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 28 import com.sun.jdi.AbsentInformationException; 29 import com.sun.jdi.ClassNotLoadedException; 30 import com.sun.jdi.InternalException; 31 import com.sun.jdi.LocalVariable; 32 import com.sun.jdi.Location; 33 import com.sun.jdi.Method; 34 import com.sun.jdi.StackFrame; 35 import com.sun.jdi.Type; 36 import com.sun.jdi.VirtualMachine; 37 38 public class LocalVariableImpl extends MirrorImpl 39 implements LocalVariable, ValueContainer 40 { 41 private final Method method; 42 private final int slot; 43 private final Location scopeStart; 44 private final Location scopeEnd; 45 private final String name; 46 private final String signature; 47 private String genericSignature = null; 48 LocalVariableImpl(VirtualMachine vm, Method method, int slot, Location scopeStart, Location scopeEnd, String name, String signature, String genericSignature)49 LocalVariableImpl(VirtualMachine vm, Method method, 50 int slot, Location scopeStart, Location scopeEnd, 51 String name, String signature, 52 String genericSignature) { 53 super(vm); 54 this.method = method; 55 this.slot = slot; 56 this.scopeStart = scopeStart; 57 this.scopeEnd = scopeEnd; 58 this.name = name; 59 this.signature = signature; 60 if (genericSignature != null && genericSignature.length() > 0) { 61 this.genericSignature = genericSignature; 62 } else { 63 // The Spec says to return null for non-generic types 64 this.genericSignature = null; 65 } 66 } 67 equals(Object obj)68 public boolean equals(Object obj) { 69 if ((obj != null) && (obj instanceof LocalVariableImpl)) { 70 LocalVariableImpl other = (LocalVariableImpl)obj; 71 return ((slot() == other.slot()) && 72 (scopeStart != null) && 73 (scopeStart.equals(other.scopeStart)) && 74 (super.equals(obj))); 75 } else { 76 return false; 77 } 78 } 79 hashCode()80 public int hashCode() { 81 /* 82 * TO DO: Better hash code 83 */ 84 return ((scopeStart.hashCode() << 4) + slot()); 85 } 86 compareTo(LocalVariable object)87 public int compareTo(LocalVariable object) { 88 LocalVariableImpl other = (LocalVariableImpl)object; 89 90 int rc = scopeStart.compareTo(other.scopeStart); 91 if (rc == 0) { 92 rc = slot() - other.slot(); 93 } 94 return rc; 95 } 96 name()97 public String name() { 98 return name; 99 } 100 101 /** 102 * @return a text representation of the declared type 103 * of this variable. 104 */ typeName()105 public String typeName() { 106 JNITypeParser parser = new JNITypeParser(signature); 107 return parser.typeName(); 108 } 109 type()110 public Type type() throws ClassNotLoadedException { 111 return findType(signature()); 112 } 113 findType(String signature)114 public Type findType(String signature) throws ClassNotLoadedException { 115 ReferenceTypeImpl enclosing = (ReferenceTypeImpl)method.declaringType(); 116 return enclosing.findType(signature); 117 } 118 signature()119 public String signature() { 120 return signature; 121 } 122 genericSignature()123 public String genericSignature() { 124 return genericSignature; 125 } 126 isVisible(StackFrame frame)127 public boolean isVisible(StackFrame frame) { 128 validateMirror(frame); 129 Method frameMethod = frame.location().method(); 130 131 if (!frameMethod.equals(method)) { 132 throw new IllegalArgumentException( 133 "frame method different than variable's method"); 134 } 135 136 // this is here to cover the possibility that we will 137 // allow LocalVariables for native methods. If we do 138 // so we will have to re-examinine this. 139 if (frameMethod.isNative()) { 140 return false; 141 } 142 143 return ((scopeStart.compareTo(frame.location()) <= 0) 144 && (scopeEnd.compareTo(frame.location()) >= 0)); 145 } 146 isArgument()147 public boolean isArgument() { 148 try { 149 MethodImpl method = (MethodImpl)scopeStart.method(); 150 return (slot < method.argSlotCount()); 151 } catch (AbsentInformationException e) { 152 // If this variable object exists, there shouldn't be absent info 153 throw new InternalException(); 154 } 155 } 156 slot()157 int slot() { 158 return slot; 159 } 160 161 /* 162 * Compilers/VMs can have byte code ranges for variables of the 163 * same names that overlap. This is because the byte code ranges 164 * aren't necessarily scopes; they may have more to do with the 165 * lifetime of the variable's slot, depending on implementation. 166 * 167 * This method determines whether this variable hides an 168 * identically named variable; ie, their byte code ranges overlap 169 * this one starts after the given one. If it returns true this 170 * variable should be preferred when looking for a single variable 171 * with its name when both variables are visible. 172 */ hides(LocalVariable other)173 boolean hides(LocalVariable other) { 174 LocalVariableImpl otherImpl = (LocalVariableImpl)other; 175 if (!method.equals(otherImpl.method) || 176 !name.equals(otherImpl.name)) { 177 return false; 178 } else { 179 return (scopeStart.compareTo(otherImpl.scopeStart) > 0); 180 } 181 } 182 toString()183 public String toString() { 184 return name() + " in " + method.toString() + 185 "@" + scopeStart.toString(); 186 } 187 } 188