History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/jdi/StackFrameImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/jdi/StackFrameImpl.java+404−0
@@ -0,0 +1,404 @@
1+/*
2+ * Copyright (c) 1998, 2008, 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.List;
31+import java.util.Map;
32+import java.util.ArrayList;
33+import java.util.Arrays;
34+import java.util.HashMap;
35+import java.util.Iterator;
36+import java.util.Collections;
37+
38+public class StackFrameImpl extends MirrorImpl
39+ implements StackFrame, ThreadListener
40+{
41+ /* Once false, frame should not be used.
42+ * access synchronized on (vm.state())
43+ */
44+ private boolean isValid = true;
45+
46+ private final ThreadReferenceImpl thread;
47+ private final long id;
48+ private final Location location;
49+ private Map<String, LocalVariable> visibleVariables = null;
50+ private ObjectReference thisObject = null;
51+
52+ StackFrameImpl(VirtualMachine vm, ThreadReferenceImpl thread,
53+ long id, Location location) {
54+ super(vm);
55+ this.thread = thread;
56+ this.id = id;
57+ this.location = location;
58+ thread.addListener(this);
59+ }
60+
61+ /*
62+ * ThreadListener implementation
63+ * Must be synchronized since we must protect against
64+ * sending defunct (isValid == false) stack ids to the back-end.
65+ */
66+ public boolean threadResumable(ThreadAction action) {
67+ synchronized (vm.state()) {
68+ if (isValid) {
69+ isValid = false;
70+ return false; /* remove this stack frame as a listener */
71+ } else {
72+ throw new InternalException(
73+ "Invalid stack frame thread listener");
74+ }
75+ }
76+ }
77+
78+ void validateStackFrame() {
79+ if (!isValid) {
80+ throw new InvalidStackFrameException("Thread has been resumed");
81+ }
82+ }
83+
84+ /**
85+ * Return the frame location.
86+ * Need not be synchronized since it cannot be provably stale.
87+ */
88+ public Location location() {
89+ validateStackFrame();
90+ return location;
91+ }
92+
93+ /**
94+ * Return the thread holding the frame.
95+ * Need not be synchronized since it cannot be provably stale.
96+ */
97+ public ThreadReference thread() {
98+ validateStackFrame();
99+ return thread;
100+ }
101+
102+ public boolean equals(Object obj) {
103+ if ((obj != null) && (obj instanceof StackFrameImpl)) {
104+ StackFrameImpl other = (StackFrameImpl)obj;
105+ return (id == other.id) &&
106+ (thread().equals(other.thread())) &&
107+ (location().equals(other.location())) &&
108+ super.equals(obj);
109+ } else {
110+ return false;
111+ }
112+ }
113+
114+ public int hashCode() {
115+ return (thread().hashCode() << 4) + ((int)id);
116+ }
117+
118+ public ObjectReference thisObject() {
119+ validateStackFrame();
120+ MethodImpl currentMethod = (MethodImpl)location.method();
121+ if (currentMethod.isStatic() || currentMethod.isNative()) {
122+ return null;
123+ } else {
124+ if (thisObject == null) {
125+ PacketStream ps;
126+
127+ /* protect against defunct frame id */
128+ synchronized (vm.state()) {
129+ validateStackFrame();
130+ ps = JDWP.StackFrame.ThisObject.
131+ enqueueCommand(vm, thread, id);
132+ }
133+
134+ /* actually get it, now that order is guaranteed */
135+ try {
136+ thisObject = JDWP.StackFrame.ThisObject.
137+ waitForReply(vm, ps).objectThis;
138+ } catch (JDWPException exc) {
139+ switch (exc.errorCode()) {
140+ case JDWP.Error.INVALID_FRAMEID:
141+ case JDWP.Error.THREAD_NOT_SUSPENDED:
142+ case JDWP.Error.INVALID_THREAD:
143+ throw new InvalidStackFrameException();
144+ default:
145+ throw exc.toJDIException();
146+ }
147+ }
148+ }
149+ }
150+ return thisObject;
151+ }
152+
153+ /**
154+ * Build the visible variable map.
155+ * Need not be synchronized since it cannot be provably stale.
156+ */
157+ private void createVisibleVariables() throws AbsentInformationException {
158+ if (visibleVariables == null) {
159+ List<LocalVariable> allVariables = location.method().variables();
160+ Map<String, LocalVariable> map = new HashMap<String, LocalVariable>(allVariables.size());
161+
162+ for (LocalVariable variable : allVariables) {
163+ String name = variable.name();
164+ if (variable.isVisible(this)) {
165+ LocalVariable existing = map.get(name);
166+ if ((existing == null) ||
167+ ((LocalVariableImpl)variable).hides(existing)) {
168+ map.put(name, variable);
169+ }
170+ }
171+ }
172+ visibleVariables = map;
173+ }
174+ }
175+
176+ /**
177+ * Return the list of visible variable in the frame.
178+ * Need not be synchronized since it cannot be provably stale.
179+ */
180+ public List<LocalVariable> visibleVariables() throws AbsentInformationException {
181+ validateStackFrame();
182+ createVisibleVariables();
183+ List<LocalVariable> mapAsList = new ArrayList<LocalVariable>(visibleVariables.values());
184+ Collections.sort(mapAsList);
185+ return mapAsList;
186+ }
187+
188+ /**
189+ * Return a particular variable in the frame.
190+ * Need not be synchronized since it cannot be provably stale.
191+ */
192+ public LocalVariable visibleVariableByName(String name) throws AbsentInformationException {
193+ validateStackFrame();
194+ createVisibleVariables();
195+ return visibleVariables.get(name);
196+ }
197+
198+ public Value getValue(LocalVariable variable) {
199+ List<LocalVariable> list = new ArrayList<LocalVariable>(1);
200+ list.add(variable);
201+ return getValues(list).get(variable);
202+ }
203+
204+ public Map<LocalVariable, Value> getValues(List<? extends LocalVariable> variables) {
205+ validateStackFrame();
206+ validateMirrors(variables);
207+
208+ int count = variables.size();
209+ JDWP.StackFrame.GetValues.SlotInfo[] slots =
210+ new JDWP.StackFrame.GetValues.SlotInfo[count];
211+
212+ for (int i=0; i<count; ++i) {
213+ LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
214+ if (!variable.isVisible(this)) {
215+ throw new IllegalArgumentException(variable.name() +
216+ " is not valid at this frame location");
217+ }
218+ slots[i] = new JDWP.StackFrame.GetValues.SlotInfo(variable.slot(),
219+ (byte)variable.signature().charAt(0));
220+ }
221+
222+ PacketStream ps;
223+
224+ /* protect against defunct frame id */
225+ synchronized (vm.state()) {
226+ validateStackFrame();
227+ ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
228+ }
229+
230+ /* actually get it, now that order is guaranteed */
231+ ValueImpl[] values;
232+ try {
233+ values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
234+ } catch (JDWPException exc) {
235+ switch (exc.errorCode()) {
236+ case JDWP.Error.INVALID_FRAMEID:
237+ case JDWP.Error.THREAD_NOT_SUSPENDED:
238+ case JDWP.Error.INVALID_THREAD:
239+ throw new InvalidStackFrameException();
240+ default:
241+ throw exc.toJDIException();
242+ }
243+ }
244+
245+ if (count != values.length) {
246+ throw new InternalException(
247+ "Wrong number of values returned from target VM");
248+ }
249+ Map<LocalVariable, Value> map = new HashMap<LocalVariable, Value>(count);
250+ for (int i=0; i<count; ++i) {
251+ LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
252+ map.put(variable, values[i]);
253+ }
254+ return map;
255+ }
256+
257+ public void setValue(LocalVariable variableIntf, Value valueIntf)
258+ throws InvalidTypeException, ClassNotLoadedException {
259+
260+ validateStackFrame();
261+ validateMirror(variableIntf);
262+ validateMirrorOrNull(valueIntf);
263+
264+ LocalVariableImpl variable = (LocalVariableImpl)variableIntf;
265+ ValueImpl value = (ValueImpl)valueIntf;
266+
267+ if (!variable.isVisible(this)) {
268+ throw new IllegalArgumentException(variable.name() +
269+ " is not valid at this frame location");
270+ }
271+
272+ try {
273+ // Validate and convert value if necessary
274+ value = ValueImpl.prepareForAssignment(value, variable);
275+
276+ JDWP.StackFrame.SetValues.SlotInfo[] slotVals =
277+ new JDWP.StackFrame.SetValues.SlotInfo[1];
278+ slotVals[0] = new JDWP.StackFrame.SetValues.
279+ SlotInfo(variable.slot(), value);
280+
281+ PacketStream ps;
282+
283+ /* protect against defunct frame id */
284+ synchronized (vm.state()) {
285+ validateStackFrame();
286+ ps = JDWP.StackFrame.SetValues.
287+ enqueueCommand(vm, thread, id, slotVals);
288+ }
289+
290+ /* actually set it, now that order is guaranteed */
291+ try {
292+ JDWP.StackFrame.SetValues.waitForReply(vm, ps);
293+ } catch (JDWPException exc) {
294+ switch (exc.errorCode()) {
295+ case JDWP.Error.INVALID_FRAMEID:
296+ case JDWP.Error.THREAD_NOT_SUSPENDED:
297+ case JDWP.Error.INVALID_THREAD:
298+ throw new InvalidStackFrameException();
299+ default:
300+ throw exc.toJDIException();
301+ }
302+ }
303+ } catch (ClassNotLoadedException e) {
304+ /*
305+ * Since we got this exception,
306+ * the variable type must be a reference type. The value
307+ * we're trying to set is null, but if the variable's
308+ * class has not yet been loaded through the enclosing
309+ * class loader, then setting to null is essentially a
310+ * no-op, and we should allow it without an exception.
311+ */
312+ if (value != null) {
313+ throw e;
314+ }
315+ }
316+ }
317+
318+ public List<Value> getArgumentValues() {
319+ validateStackFrame();
320+ MethodImpl mmm = (MethodImpl)location.method();
321+ List<String> argSigs = mmm.argumentSignatures();
322+ int count = argSigs.size();
323+ JDWP.StackFrame.GetValues.SlotInfo[] slots =
324+ new JDWP.StackFrame.GetValues.SlotInfo[count];
325+
326+ int slot;
327+ if (mmm.isStatic()) {
328+ slot = 0;
329+ } else {
330+ slot = 1;
331+ }
332+ for (int ii = 0; ii < count; ++ii) {
333+ char sigChar = argSigs.get(ii).charAt(0);
334+ slots[ii] = new JDWP.StackFrame.GetValues.SlotInfo(slot++,(byte)sigChar);
335+ if (sigChar == 'J' || sigChar == 'D') {
336+ slot++;
337+ }
338+ }
339+
340+ PacketStream ps;
341+
342+ /* protect against defunct frame id */
343+ synchronized (vm.state()) {
344+ validateStackFrame();
345+ ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
346+ }
347+
348+ ValueImpl[] values;
349+ try {
350+ values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
351+ } catch (JDWPException exc) {
352+ switch (exc.errorCode()) {
353+ case JDWP.Error.INVALID_FRAMEID:
354+ case JDWP.Error.THREAD_NOT_SUSPENDED:
355+ case JDWP.Error.INVALID_THREAD:
356+ throw new InvalidStackFrameException();
357+ default:
358+ throw exc.toJDIException();
359+ }
360+ }
361+
362+ if (count != values.length) {
363+ throw new InternalException(
364+ "Wrong number of values returned from target VM");
365+ }
366+ return Arrays.asList((Value[])values);
367+ }
368+
369+ void pop() throws IncompatibleThreadStateException {
370+ validateStackFrame();
371+ // flush caches and disable caching until command completion
372+ CommandSender sender =
373+ new CommandSender() {
374+ public PacketStream send() {
375+ return JDWP.StackFrame.PopFrames.enqueueCommand(vm,
376+ thread, id);
377+ }
378+ };
379+ try {
380+ PacketStream stream = thread.sendResumingCommand(sender);
381+ JDWP.StackFrame.PopFrames.waitForReply(vm, stream);
382+ } catch (JDWPException exc) {
383+ switch (exc.errorCode()) {
384+ case JDWP.Error.THREAD_NOT_SUSPENDED:
385+ throw new IncompatibleThreadStateException(
386+ "Thread not current or suspended");
387+ case JDWP.Error.INVALID_THREAD: /* zombie */
388+ throw new IncompatibleThreadStateException("zombie");
389+ case JDWP.Error.NO_MORE_FRAMES:
390+ throw new InvalidStackFrameException(
391+ "No more frames on the stack");
392+ default:
393+ throw exc.toJDIException();
394+ }
395+ }
396+
397+ // enable caching - suspended again
398+ vm.state().freeze();
399+ }
400+
401+ public String toString() {
402+ return location.toString() + " in thread " + thread.toString();
403+ }
404+}