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 
28 import com.sun.jdi.*;
29 
30 import java.util.*;
31 
32 public class LocationImpl extends MirrorImpl implements Location {
33     private final ReferenceTypeImpl declaringType;
34     private Method method;
35     private long methodRef;
36     private long codeIndex;
37     private LineInfo baseLineInfo = null;
38     private LineInfo otherLineInfo = null;
39 
LocationImpl(VirtualMachine vm, Method method, long codeIndex)40     LocationImpl(VirtualMachine vm,
41                  Method method, long codeIndex) {
42         super(vm);
43 
44         this.method = method;
45         this.codeIndex = method.isNative()? -1 : codeIndex;
46         this.declaringType = (ReferenceTypeImpl)method.declaringType();
47     }
48 
49     /*
50      * This constructor allows lazy creation of the method mirror. This
51      * can be a performance savings if the method mirror does not yet
52      * exist.
53      */
LocationImpl(VirtualMachine vm, ReferenceTypeImpl declaringType, long methodRef, long codeIndex)54     LocationImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
55                  long methodRef, long codeIndex) {
56         super(vm);
57 
58         this.method = null;
59         this.codeIndex = codeIndex;
60         this.declaringType = declaringType;
61         this.methodRef = methodRef;
62     }
63 
equals(Object obj)64     public boolean equals(Object obj) {
65         if ((obj != null) && (obj instanceof Location)) {
66             Location other = (Location)obj;
67             return (method().equals(other.method())) &&
68                    (codeIndex() == other.codeIndex()) &&
69                    super.equals(obj);
70         } else {
71             return false;
72         }
73     }
74 
hashCode()75     public int hashCode() {
76         /*
77          * TO DO: better hash code?
78          */
79         return method().hashCode() + (int)codeIndex();
80     }
81 
compareTo(Location object)82     public int compareTo(Location object) {
83         LocationImpl other = (LocationImpl)object;
84         int rc = method().compareTo(other.method());
85         if (rc == 0) {
86             long diff = codeIndex() - other.codeIndex();
87             if (diff < 0)
88                 return -1;
89             else if (diff > 0)
90                 return 1;
91             else
92                 return 0;
93         }
94         return rc;
95     }
96 
declaringType()97     public ReferenceType declaringType() {
98         return declaringType;
99     }
100 
method()101     public Method method() {
102         if (method == null) {
103             method = declaringType.getMethodMirror(methodRef);
104             if (method.isNative()) {
105                 codeIndex = -1;
106             }
107         }
108         return method;
109     }
110 
codeIndex()111     public long codeIndex() {
112         method();  // be sure information is up-to-date
113         return codeIndex;
114     }
115 
getBaseLineInfo(SDE.Stratum stratum)116     LineInfo getBaseLineInfo(SDE.Stratum stratum) {
117         LineInfo lineInfo;
118 
119         /* check if there is cached info to use */
120         if (baseLineInfo != null) {
121             return baseLineInfo;
122         }
123 
124         /* compute the line info */
125         MethodImpl methodImpl = (MethodImpl)method();
126         lineInfo = methodImpl.codeIndexToLineInfo(stratum,
127                                                   codeIndex());
128 
129         /* cache it */
130         addBaseLineInfo(lineInfo);
131 
132         return lineInfo;
133     }
134 
getLineInfo(SDE.Stratum stratum)135     LineInfo getLineInfo(SDE.Stratum stratum) {
136         LineInfo lineInfo;
137 
138         /* base stratum is done slighly differently */
139         if (stratum.isJava()) {
140             return getBaseLineInfo(stratum);
141         }
142 
143         /* check if there is cached info to use */
144         lineInfo = otherLineInfo; // copy because of concurrency
145         if (lineInfo != null &&
146                            stratum.id().equals(lineInfo.liStratum())) {
147             return lineInfo;
148         }
149 
150         int baseLineNumber = lineNumber(SDE.BASE_STRATUM_NAME);
151         SDE.LineStratum lineStratum =
152                   stratum.lineStratum(declaringType, baseLineNumber);
153 
154         if (lineStratum != null && lineStratum.lineNumber() != -1) {
155             lineInfo = new StratumLineInfo(stratum.id(),
156                                            lineStratum.lineNumber(),
157                                            lineStratum.sourceName(),
158                                            lineStratum.sourcePath());
159         } else {
160             /* find best match */
161             MethodImpl methodImpl = (MethodImpl)method();
162             lineInfo = methodImpl.codeIndexToLineInfo(stratum,
163                                                       codeIndex());
164         }
165 
166         /* cache it */
167         addStratumLineInfo(lineInfo);
168 
169         return lineInfo;
170     }
171 
addStratumLineInfo(LineInfo lineInfo)172     void addStratumLineInfo(LineInfo lineInfo) {
173         otherLineInfo = lineInfo;
174     }
175 
addBaseLineInfo(LineInfo lineInfo)176     void addBaseLineInfo(LineInfo lineInfo) {
177         baseLineInfo = lineInfo;
178     }
179 
sourceName()180     public String sourceName() throws AbsentInformationException {
181         return sourceName(vm.getDefaultStratum());
182     }
183 
sourceName(String stratumID)184     public String sourceName(String stratumID)
185                                throws AbsentInformationException {
186         return sourceName(declaringType.stratum(stratumID));
187     }
188 
sourceName(SDE.Stratum stratum)189     String sourceName(SDE.Stratum stratum)
190                                throws AbsentInformationException {
191         return getLineInfo(stratum).liSourceName();
192     }
193 
sourcePath()194     public String sourcePath() throws AbsentInformationException {
195         return sourcePath(vm.getDefaultStratum());
196     }
197 
sourcePath(String stratumID)198     public String sourcePath(String stratumID)
199                                throws AbsentInformationException {
200         return sourcePath(declaringType.stratum(stratumID));
201     }
202 
sourcePath(SDE.Stratum stratum)203     String sourcePath(SDE.Stratum stratum)
204                                throws AbsentInformationException {
205         return getLineInfo(stratum).liSourcePath();
206     }
207 
lineNumber()208     public int lineNumber() {
209         return lineNumber(vm.getDefaultStratum());
210     }
211 
lineNumber(String stratumID)212     public int lineNumber(String stratumID) {
213         return lineNumber(declaringType.stratum(stratumID));
214     }
215 
lineNumber(SDE.Stratum stratum)216     int lineNumber(SDE.Stratum stratum) {
217         return getLineInfo(stratum).liLineNumber();
218     }
219 
toString()220     public String toString() {
221         if (lineNumber() == -1) {
222             return method().toString() + "+" + codeIndex();
223         } else {
224             return declaringType().name() + ":" + lineNumber();
225         }
226     }
227 }
228