Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java')
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java1487
1 files changed, 1487 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
new file mode 100644
index 000000000..833a1f933
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
@@ -0,0 +1,1487 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.internal.tcf.debug.ui.model;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.memory.IMemoryRenderingSite;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.tm.internal.tcf.debug.model.TCFContextState;
+import org.eclipse.tm.internal.tcf.debug.model.TCFFunctionRef;
+import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef;
+import org.eclipse.tm.internal.tcf.debug.ui.ImageCache;
+import org.eclipse.tm.tcf.protocol.IErrorReport;
+import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.protocol.JSON;
+import org.eclipse.tm.tcf.protocol.Protocol;
+import org.eclipse.tm.tcf.services.ILineNumbers;
+import org.eclipse.tm.tcf.services.IMemory;
+import org.eclipse.tm.tcf.services.IMemoryMap;
+import org.eclipse.tm.tcf.services.IProcesses;
+import org.eclipse.tm.tcf.services.IRunControl;
+import org.eclipse.tm.tcf.services.ISymbols;
+import org.eclipse.tm.tcf.util.TCFDataCache;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class TCFNodeExecContext extends TCFNode implements ISymbolOwner {
+
+ private final TCFChildrenExecContext children_exec;
+ private final TCFChildrenStackTrace children_stack;
+ private final TCFChildrenRegisters children_regs;
+ private final TCFChildrenExpressions children_exps;
+ private final TCFChildrenHoverExpressions children_hover_exps;
+ private final TCFChildrenLogExpressions children_log_exps;
+ private final TCFChildrenModules children_modules;
+
+ private final TCFData<IMemory.MemoryContext> mem_context;
+ private final TCFData<IRunControl.RunControlContext> run_context;
+ private final TCFData<MemoryRegion[]> memory_map;
+ private final TCFData<IProcesses.ProcessContext> prs_context;
+ private final TCFData<TCFContextState> state;
+ private final TCFData<BigInteger> address; // Current PC as BigInteger
+ private final TCFData<Collection<Map<String,Object>>> signal_list;
+ private final TCFData<SignalMask[]> signal_mask;
+ private final TCFData<TCFNodeExecContext> memory_node;
+ private final TCFData<TCFNodeExecContext> symbols_node;
+ private final TCFData<String> full_name;
+
+ private LinkedHashMap<BigInteger,TCFDataCache<TCFSourceRef>> line_info_lookup_cache;
+ private LinkedHashMap<BigInteger,TCFDataCache<TCFFunctionRef>> func_info_lookup_cache;
+ private LookupCacheTimer lookup_cache_timer;
+
+ private int mem_seq_no;
+ private int exe_seq_no;
+
+ /*
+ * LookupCacheTimer is executed periodically to dispose least-recently
+ * accessed entries in line_info_lookup_cache and func_info_lookup_cache.
+ * The timer disposes itself when both caches become empty.
+ */
+ private class LookupCacheTimer implements Runnable {
+
+ LookupCacheTimer() {
+ Protocol.invokeLater(4000, this);
+ }
+
+ public void run() {
+ if (isDisposed()) return;
+ if (line_info_lookup_cache != null) {
+ BigInteger addr = line_info_lookup_cache.keySet().iterator().next();
+ TCFDataCache<TCFSourceRef> cache = line_info_lookup_cache.get(addr);
+ if (!cache.isPending()) {
+ line_info_lookup_cache.remove(addr).dispose();
+ if (line_info_lookup_cache.size() == 0) line_info_lookup_cache = null;
+ }
+ }
+ if (func_info_lookup_cache != null) {
+ BigInteger addr = func_info_lookup_cache.keySet().iterator().next();
+ TCFDataCache<TCFFunctionRef> cache = func_info_lookup_cache.get(addr);
+ if (!cache.isPending()) {
+ func_info_lookup_cache.remove(addr).dispose();
+ if (func_info_lookup_cache.size() == 0) func_info_lookup_cache = null;
+ }
+ }
+ if (line_info_lookup_cache == null && func_info_lookup_cache == null) {
+ lookup_cache_timer = null;
+ }
+ else {
+ Protocol.invokeLater(2500, this);
+ }
+ }
+ }
+
+ public static class ChildrenStateInfo {
+ public boolean running;
+ public boolean suspended;
+ public boolean not_active;
+ public boolean breakpoint;
+ }
+
+ private final Map<String,TCFNodeSymbol> symbols = new HashMap<String,TCFNodeSymbol>();
+
+ private int resumed_cnt;
+ private boolean resume_pending;
+ private boolean resumed_by_action;
+ private TCFNode[] last_stack_trace;
+ private TCFNode[] last_children_list;
+ private String last_label;
+ private ImageDescriptor last_image;
+ private ChildrenStateInfo last_children_state_info;
+ private boolean delayed_children_list_delta;
+
+ private String hover_expression;
+
+ /**
+ * Wrapper class for IMemoryMap.MemoryRegion.
+ * The class help to search memory region by address by
+ * providing contains() method.
+ */
+ public static class MemoryRegion {
+
+ private final BigInteger addr_start;
+ private final BigInteger addr_end;
+
+ public final IMemoryMap.MemoryRegion region;
+
+ private MemoryRegion(IMemoryMap.MemoryRegion region) {
+ this.region = region;
+ Number addr = region.getAddress();
+ Number size = region.getSize();
+ if (addr == null || size == null) {
+ addr_start = null;
+ addr_end = null;
+ }
+ else {
+ addr_start = JSON.toBigInteger(addr);
+ addr_end = addr_start.add(JSON.toBigInteger(size));
+ }
+ }
+
+ public boolean contains(BigInteger addr) {
+ return
+ addr_start != null && addr_end != null &&
+ addr_start.compareTo(addr) <= 0 &&
+ addr_end.compareTo(addr) > 0;
+ }
+
+ @Override
+ public String toString() {
+ return region.getProperties().toString();
+ }
+ }
+
+ public static class SignalMask {
+
+ protected Map<String,Object> props;
+ protected boolean dont_stop;
+ protected boolean dont_pass;
+ protected boolean pending;
+
+ public Number getIndex() {
+ return (Number)props.get(IProcesses.SIG_INDEX);
+ }
+
+ public Number getCode() {
+ return (Number)props.get(IProcesses.SIG_CODE);
+ }
+
+ public Map<String,Object> getProperties() {
+ return props;
+ }
+
+ public boolean isDontStop() {
+ return dont_stop;
+ }
+
+ public boolean isDontPass() {
+ return dont_pass;
+ }
+
+ public boolean isPending() {
+ return pending;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer bf = new StringBuffer();
+ bf.append("[attrs=");
+ bf.append(props.toString());
+ if (dont_stop) bf.append(",don't stop");
+ if (dont_pass) bf.append(",don't pass");
+ if (pending) bf.append(",pending");
+ bf.append(']');
+ return bf.toString();
+ }
+ }
+
+ TCFNodeExecContext(TCFNode parent, final String id) {
+ super(parent, id);
+ children_exec = new TCFChildrenExecContext(this);
+ children_stack = new TCFChildrenStackTrace(this);
+ children_regs = new TCFChildrenRegisters(this);
+ children_exps = new TCFChildrenExpressions(this);
+ children_hover_exps = new TCFChildrenHoverExpressions(this);
+ children_log_exps = new TCFChildrenLogExpressions(this);
+ children_modules = new TCFChildrenModules(this);
+ mem_context = new TCFData<IMemory.MemoryContext>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ IMemory mem = launch.getService(IMemory.class);
+ if (mem == null) {
+ set(null, null, null);
+ return true;
+ }
+ command = mem.getContext(id, new IMemory.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, IMemory.MemoryContext context) {
+ set(token, error, context);
+ }
+ });
+ return false;
+ }
+ };
+ run_context = new TCFData<IRunControl.RunControlContext>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ IRunControl run = launch.getService(IRunControl.class);
+ if (run == null) {
+ set(null, null, null);
+ return true;
+ }
+ command = run.getContext(id, new IRunControl.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, IRunControl.RunControlContext context) {
+ if (context != null) model.updateContextMap(id, context);
+ set(token, error, context);
+ }
+ });
+ return false;
+ }
+ };
+ prs_context = new TCFData<IProcesses.ProcessContext>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ IProcesses prs = launch.getService(IProcesses.class);
+ if (prs == null) {
+ set(null, null, null);
+ return true;
+ }
+ command = prs.getContext(id, new IProcesses.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, IProcesses.ProcessContext context) {
+ set(token, error, context);
+ }
+ });
+ return false;
+ }
+ };
+ memory_map = new TCFData<MemoryRegion[]>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ IMemoryMap mmap = launch.getService(IMemoryMap.class);
+ if (mmap == null) {
+ set(null, null, null);
+ return true;
+ }
+ command = mmap.get(id, new IMemoryMap.DoneGet() {
+ public void doneGet(IToken token, Exception error, IMemoryMap.MemoryRegion[] map) {
+ MemoryRegion[] arr = null;
+ if (map != null) {
+ int i = 0;
+ arr = new MemoryRegion[map.length];
+ for (IMemoryMap.MemoryRegion r : map) arr[i++] = new MemoryRegion(r);
+ }
+ set(token, error, arr);
+ }
+ });
+ return false;
+ }
+ };
+ state = new TCFData<TCFContextState>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ assert command == null;
+ if (!run_context.validate(this)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx == null || !ctx.hasState()) {
+ set(null, null, null);
+ return true;
+ }
+ command = ctx.getState(new IRunControl.DoneGetState() {
+ public void doneGetState(IToken token, Exception error, boolean suspended, String pc, String reason, Map<String,Object> params) {
+ TCFContextState s = new TCFContextState();
+ s.is_suspended = suspended;
+ s.suspend_pc = pc;
+ s.suspend_reason = reason;
+ s.suspend_params = params;
+ set(token, error, s);
+ }
+ });
+ return false;
+ }
+ };
+ address = new TCFData<BigInteger>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!run_context.validate(this)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx == null || !ctx.hasState()) {
+ set(null, run_context.getError(), null);
+ return true;
+ }
+ if (!state.validate(this)) return false;
+ TCFContextState s = state.getData();
+ if (s == null) {
+ set(null, state.getError(), null);
+ return true;
+ }
+ if (s.suspend_pc == null) {
+ set(null, null, null);
+ return true;
+ }
+ set(null, null, new BigInteger(s.suspend_pc));
+ return true;
+ }
+ };
+ signal_list = new TCFData<Collection<Map<String,Object>>>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ IProcesses prs = channel.getRemoteService(IProcesses.class);
+ if (prs == null) {
+ set(null, null, null);
+ return true;
+ }
+ command = prs.getSignalList(id, new IProcesses.DoneGetSignalList() {
+ public void doneGetSignalList(IToken token, Exception error, Collection<Map<String, Object>> list) {
+ set(token, error, list);
+ }
+ });
+ return false;
+ }
+ };
+ signal_mask = new TCFData<SignalMask[]>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!signal_list.validate(this)) return false;
+ IProcesses prs = channel.getRemoteService(IProcesses.class);
+ final Collection<Map<String,Object>> sigs = signal_list.getData();
+ if (prs == null || sigs == null) {
+ set(null, signal_list.getError(), null);
+ return true;
+ }
+ command = prs.getSignalMask(id, new IProcesses.DoneGetSignalMask() {
+ public void doneGetSignalMask(IToken token, Exception error, int dont_stop, int dont_pass, int pending) {
+ int n = 0;
+ SignalMask[] list = new SignalMask[sigs.size()];
+ for (Map<String,Object> m : sigs) {
+ SignalMask s = list[n++] = new SignalMask();
+ s.props = m;
+ int mask = 1 << s.getIndex().intValue();
+ s.dont_stop = (dont_stop & mask) != 0;
+ s.dont_pass = (dont_pass & mask) != 0;
+ s.pending = (pending & mask) != 0;
+ }
+ set(token, error, list);
+ }
+ });
+ return false;
+ }
+ };
+ memory_node = new TCFData<TCFNodeExecContext>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ String mem_id = null;
+ if (!run_context.validate(this)) return false;
+ Throwable err = run_context.getError();
+ if (err == null) {
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null) mem_id = ctx.getProcessID();
+ }
+ if (err != null) {
+ set(null, err, null);
+ }
+ else if (mem_id == null) {
+ set(null, new Exception("Context does not provide memory access"), null);
+ }
+ else {
+ if (!model.createNode(mem_id, this)) return false;
+ if (!isValid()) set(null, null, (TCFNodeExecContext)model.getNode(mem_id));
+ }
+ return true;
+ }
+ };
+ symbols_node = new TCFData<TCFNodeExecContext>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ String syms_id = null;
+ if (!run_context.validate(this)) return false;
+ Throwable err = run_context.getError();
+ if (err == null) {
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null) {
+ syms_id = ctx.getSymbolsGroup();
+ if (syms_id == null) syms_id = ctx.getProcessID();
+ }
+ }
+ if (err != null) {
+ set(null, err, null);
+ }
+ else if (syms_id == null) {
+ set(null, new Exception("Context does not support symbol groups"), null);
+ }
+ else {
+ if (!model.createNode(syms_id, this)) return false;
+ if (!isValid()) set(null, null, (TCFNodeExecContext)model.getNode(syms_id));
+ }
+ return true;
+ }
+ };
+ full_name = new TCFData<String>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!run_context.validate(this)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ String res = null;
+ if (ctx != null) {
+ res = ctx.getName();
+ if (res == null) {
+ res = ctx.getID();
+ }
+ else {
+ // Add ancestor names
+ TCFNodeExecContext p = TCFNodeExecContext.this;
+ ArrayList<String> lst = new ArrayList<String>();
+ lst.add(res);
+ while (p.parent instanceof TCFNodeExecContext) {
+ p = (TCFNodeExecContext)p.parent;
+ TCFDataCache<IRunControl.RunControlContext> run_ctx_cache = p.run_context;
+ if (!run_ctx_cache.validate(this)) return false;
+ IRunControl.RunControlContext run_ctx_data = run_ctx_cache.getData();
+ String name = null;
+ if (run_ctx_data != null) name = run_ctx_data.getName();
+ if (name == null) name = "";
+ lst.add(name);
+ }
+ StringBuffer bf = new StringBuffer();
+ for (int i = lst.size(); i > 0; i--) {
+ bf.append('/');
+ bf.append(lst.get(i - 1));
+ }
+ res = bf.toString();
+ }
+ }
+ set(null, null, res);
+ return true;
+ }
+ };
+ }
+
+ @Override
+ void dispose() {
+ assert !isDisposed();
+ ArrayList<TCFNodeSymbol> l = new ArrayList<TCFNodeSymbol>(symbols.values());
+ for (TCFNodeSymbol s : l) s.dispose();
+ assert symbols.size() == 0;
+ super.dispose();
+ }
+
+ void setMemSeqNo(int no) {
+ mem_seq_no = no;
+ }
+
+ void setExeSeqNo(int no) {
+ exe_seq_no = no;
+ }
+
+ TCFChildren getHoverExpressionCache(String expression) {
+ if (expression != hover_expression && (expression == null || !expression.equals(hover_expression))) {
+ hover_expression = expression;
+ children_hover_exps.cancel();
+ }
+ return children_hover_exps;
+ }
+
+ String getHoverExpression() {
+ return hover_expression;
+ }
+
+ public TCFChildrenLogExpressions getLogExpressionCache() {
+ return children_log_exps;
+ }
+
+ void setRunContext(IRunControl.RunControlContext ctx) {
+ run_context.reset(ctx);
+ }
+
+ void setProcessContext(IProcesses.ProcessContext ctx) {
+ prs_context.reset(ctx);
+ }
+
+ void setMemoryContext(IMemory.MemoryContext ctx) {
+ mem_context.reset(ctx);
+ }
+
+ public TCFDataCache<TCFNodeExecContext> getSymbolsNode() {
+ return symbols_node;
+ }
+
+ public TCFDataCache<TCFNodeExecContext> getMemoryNode() {
+ return memory_node;
+ }
+
+ public TCFDataCache<MemoryRegion[]> getMemoryMap() {
+ return memory_map;
+ }
+
+ public TCFDataCache<Collection<Map<String,Object>>> getSignalList() {
+ return signal_list;
+ }
+
+ public TCFDataCache<SignalMask[]> getSignalMask() {
+ return signal_mask;
+ }
+
+ public TCFDataCache<TCFSourceRef> getLineInfo(final BigInteger addr) {
+ if (isDisposed()) return null;
+ TCFDataCache<TCFSourceRef> ref_cache;
+ if (line_info_lookup_cache != null) {
+ ref_cache = line_info_lookup_cache.get(addr);
+ if (ref_cache != null) return ref_cache;
+ }
+ final ILineNumbers ln = launch.getService(ILineNumbers.class);
+ if (ln == null) return null;
+ final BigInteger n0 = addr;
+ final BigInteger n1 = n0.add(BigInteger.valueOf(1));
+ if (line_info_lookup_cache == null) {
+ line_info_lookup_cache = new LinkedHashMap<BigInteger,TCFDataCache<TCFSourceRef>>(11, 0.75f, true);
+ if (lookup_cache_timer == null) lookup_cache_timer = new LookupCacheTimer();
+ }
+ line_info_lookup_cache.put(addr, ref_cache = new TCFData<TCFSourceRef>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!memory_node.validate(this)) return false;
+ IMemory.MemoryContext mem_data = null;
+ TCFNodeExecContext mem = memory_node.getData();
+ if (mem != null) {
+ TCFDataCache<IMemory.MemoryContext> mem_cache = mem.mem_context;
+ if (!mem_cache.validate(this)) return false;
+ mem_data = mem_cache.getData();
+ }
+ final TCFSourceRef ref_data = new TCFSourceRef();
+ if (mem_data != null) {
+ ref_data.context_id = mem_data.getID();
+ ref_data.address_size = mem_data.getAddressSize();
+ }
+ command = ln.mapToSource(id, n0, n1, new ILineNumbers.DoneMapToSource() {
+ public void doneMapToSource(IToken token, Exception error, ILineNumbers.CodeArea[] areas) {
+ ref_data.address = addr;
+ if (error == null && areas != null && areas.length > 0) {
+ for (ILineNumbers.CodeArea area : areas) {
+ BigInteger a0 = JSON.toBigInteger(area.start_address);
+ BigInteger a1 = JSON.toBigInteger(area.end_address);
+ if (n0.compareTo(a0) >= 0 && n0.compareTo(a1) < 0) {
+ if (ref_data.area == null || area.start_line < ref_data.area.start_line) {
+ if (area.start_address != a0 || area.end_address != a1) {
+ area = new ILineNumbers.CodeArea(area.directory, area.file,
+ area.start_line, area.start_column,
+ area.end_line, area.end_column,
+ a0, a1, area.isa,
+ area.is_statement, area.basic_block,
+ area.prologue_end, area.epilogue_begin);
+ }
+ ref_data.area = area;
+ }
+ }
+ }
+ }
+ ref_data.error = error;
+ set(token, null, ref_data);
+ }
+ });
+ return false;
+ }
+ });
+ return ref_cache;
+ }
+
+ public TCFDataCache<TCFFunctionRef> getFuncInfo(final BigInteger addr) {
+ if (isDisposed()) return null;
+ TCFDataCache<TCFFunctionRef> ref_cache;
+ if (func_info_lookup_cache != null) {
+ ref_cache = func_info_lookup_cache.get(addr);
+ if (ref_cache != null) return ref_cache;
+ }
+ final ISymbols syms = launch.getService(ISymbols.class);
+ if (syms == null) return null;
+ if (func_info_lookup_cache == null) {
+ func_info_lookup_cache = new LinkedHashMap<BigInteger,TCFDataCache<TCFFunctionRef>>(11, 0.75f, true);
+ if (lookup_cache_timer == null) lookup_cache_timer = new LookupCacheTimer();
+ }
+ func_info_lookup_cache.put(addr, ref_cache = new TCFData<TCFFunctionRef>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!memory_node.validate(this)) return false;
+ IMemory.MemoryContext mem_data = null;
+ TCFNodeExecContext mem = memory_node.getData();
+ if (mem != null) {
+ TCFDataCache<IMemory.MemoryContext> mem_cache = mem.mem_context;
+ if (!mem_cache.validate(this)) return false;
+ mem_data = mem_cache.getData();
+ }
+ final TCFFunctionRef ref_data = new TCFFunctionRef();
+ if (mem_data != null) {
+ ref_data.context_id = mem_data.getID();
+ ref_data.address_size = mem_data.getAddressSize();
+ }
+ command = syms.findByAddr(id, addr, new ISymbols.DoneFind() {
+ public void doneFind(IToken token, Exception error, String symbol_id) {
+ ref_data.address = addr;
+ ref_data.error = error;
+ ref_data.symbol_id = symbol_id;
+ set(token, null, ref_data);
+ }
+ });
+ return false;
+ }
+ });
+ return ref_cache;
+ }
+
+ private void clearLookupCaches() {
+ if (line_info_lookup_cache != null) {
+ Iterator<TCFDataCache<TCFSourceRef>> i = line_info_lookup_cache.values().iterator();
+ while (i.hasNext()) {
+ TCFDataCache<TCFSourceRef> cache = i.next();
+ if (cache.isPending()) continue;
+ cache.dispose();
+ i.remove();
+ }
+ if (line_info_lookup_cache.size() == 0) line_info_lookup_cache = null;
+ }
+ if (func_info_lookup_cache != null) {
+ Iterator<TCFDataCache<TCFFunctionRef>> i = func_info_lookup_cache.values().iterator();
+ while (i.hasNext()) {
+ TCFDataCache<TCFFunctionRef> cache = i.next();
+ if (cache.isPending()) continue;
+ cache.dispose();
+ i.remove();
+ }
+ if (func_info_lookup_cache.size() == 0) func_info_lookup_cache = null;
+ }
+ }
+
+ @Override
+ public TCFNode getParent(IPresentationContext ctx) {
+ assert Protocol.isDispatchThread();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(ctx.getId())) {
+ Set<String> ids = launch.getContextFilter();
+ if (ids != null) {
+ if (ids.contains(id)) return model.getRootNode();
+ if (parent instanceof TCFNodeLaunch) return null;
+ }
+ }
+ return parent;
+ }
+
+ public TCFDataCache<IRunControl.RunControlContext> getRunContext() {
+ return run_context;
+ }
+
+ public TCFDataCache<IProcesses.ProcessContext> getProcessContext() {
+ return prs_context;
+ }
+
+ public TCFDataCache<IMemory.MemoryContext> getMemoryContext() {
+ return mem_context;
+ }
+
+ public TCFDataCache<BigInteger> getAddress() {
+ return address;
+ }
+
+ public TCFDataCache<TCFContextState> getState() {
+ return state;
+ }
+
+ public TCFChildrenStackTrace getStackTrace() {
+ return children_stack;
+ }
+
+ public TCFChildren getRegisters() {
+ return children_regs;
+ }
+
+ public TCFChildren getModules() {
+ return children_modules;
+ }
+
+ public TCFChildren getChildren() {
+ return children_exec;
+ }
+
+ public TCFNodeStackFrame getLastTopFrame() {
+ if (!resume_pending) return null;
+ if (last_stack_trace == null || last_stack_trace.length == 0) return null;
+ return (TCFNodeStackFrame)last_stack_trace[0];
+ }
+
+ public TCFNodeStackFrame getViewBottomFrame() {
+ if (last_stack_trace == null || last_stack_trace.length == 0) return null;
+ return (TCFNodeStackFrame)last_stack_trace[last_stack_trace.length - 1];
+ }
+
+ /**
+ * Get context full name - including all ancestor names.
+ * Return context ID if the context does not have a name.
+ * @return cache item with the context full name.
+ */
+ public TCFDataCache<String> getFullName() {
+ return full_name;
+ }
+
+ public void addSymbol(TCFNodeSymbol s) {
+ assert symbols.get(s.id) == null;
+ symbols.put(s.id, s);
+ }
+
+ public void removeSymbol(TCFNodeSymbol s) {
+ assert symbols.get(s.id) == s;
+ symbols.remove(s.id);
+ }
+
+ /**
+ * Return true if this context cannot be accessed because it is not active.
+ * Not active means the target is suspended but this context is not one that is
+ * currently scheduled to run on a target CPU.
+ * Some debuggers don't support access to register values and other properties of such contexts.
+ */
+ public boolean isNotActive() {
+ TCFContextState state_data = state.getData();
+ if (state_data != null && state_data.suspend_params != null) {
+ @SuppressWarnings("unchecked")
+ Map<String,Object> attrs = (Map<String,Object>)state_data.suspend_params.get(IRunControl.STATE_PC_ERROR);
+ if (attrs != null) {
+ Number n = (Number)attrs.get(IErrorReport.ERROR_CODE);
+ if (n != null) return n.intValue() == IErrorReport.TCF_ERROR_NOT_ACTIVE;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getData(IChildrenCountUpdate result, Runnable done) {
+ TCFChildren children = null;
+ String view_id = result.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) {
+ if (resume_pending && last_stack_trace != null) {
+ result.setChildCount(last_stack_trace.length);
+ return true;
+ }
+ if (!state.validate(done)) return false;
+ if (isNotActive()) {
+ last_stack_trace = new TCFNode[0];
+ result.setChildCount(0);
+ return true;
+ }
+ TCFContextState state_data = state.getData();
+ if (state_data != null && !state_data.is_suspended) {
+ result.setChildCount(0);
+ return true;
+ }
+ children = children_stack;
+ }
+ else {
+ if (!model.getAutoChildrenListUpdates() && last_children_list != null) {
+ result.setChildCount(last_children_list.length);
+ return true;
+ }
+ children = children_exec;
+ }
+ }
+ else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_regs;
+ }
+ else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_exps;
+ }
+ else if (TCFModel.ID_EXPRESSION_HOVER.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_hover_exps;
+ }
+ else if (IDebugUIConstants.ID_MODULE_VIEW.equals(view_id)) {
+ if (!mem_context.validate(done)) return false;
+ IMemory.MemoryContext ctx = mem_context.getData();
+ if (ctx != null) children = children_modules;
+ }
+ if (children != null) {
+ if (!children.validate(done)) return false;
+ if (children == children_stack) last_stack_trace = children_stack.toArray();
+ if (children == children_exec) last_children_list = children_exec.toArray();
+ result.setChildCount(children.size());
+ }
+ else {
+ result.setChildCount(0);
+ }
+ return true;
+ }
+
+ private void setResultChildren(IChildrenUpdate result, TCFNode[] arr) {
+ int offset = 0;
+ int r_offset = result.getOffset();
+ int r_length = result.getLength();
+ for (TCFNode n : arr) {
+ if (offset >= r_offset && offset < r_offset + r_length) {
+ result.setChild(n, offset);
+ }
+ offset++;
+ }
+ }
+
+ @Override
+ protected boolean getData(IChildrenUpdate result, Runnable done) {
+ TCFChildren children = null;
+ String view_id = result.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) {
+ if (resume_pending && last_stack_trace != null) {
+ setResultChildren(result, last_stack_trace);
+ return true;
+ }
+ if (!state.validate(done)) return false;
+ if (isNotActive()) {
+ last_stack_trace = new TCFNode[0];
+ return true;
+ }
+ TCFContextState state_data = state.getData();
+ if (state_data != null && !state_data.is_suspended) {
+ return true;
+ }
+ children = children_stack;
+ }
+ else {
+ if (!model.getAutoChildrenListUpdates() && last_children_list != null) {
+ setResultChildren(result, last_children_list);
+ return true;
+ }
+ children = children_exec;
+ }
+ }
+ else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_regs;
+ }
+ else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_exps;
+ }
+ else if (TCFModel.ID_EXPRESSION_HOVER.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_hover_exps;
+ }
+ else if (IDebugUIConstants.ID_MODULE_VIEW.equals(view_id)) {
+ if (!mem_context.validate(done)) return false;
+ IMemory.MemoryContext ctx = mem_context.getData();
+ if (ctx != null) children = children_modules;
+ }
+ if (children == null) return true;
+ if (children == children_stack) {
+ if (!children.validate(done)) return false;
+ last_stack_trace = children_stack.toArray();
+ }
+ if (children == children_exec) {
+ if (!children.validate(done)) return false;
+ last_children_list = children_exec.toArray();
+ }
+ return children.getData(result, done);
+ }
+
+ @Override
+ protected boolean getData(IHasChildrenUpdate result, Runnable done) {
+ TCFChildren children = null;
+ String view_id = result.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) {
+ if (resume_pending && last_stack_trace != null) {
+ result.setHasChilren(last_stack_trace.length > 0);
+ return true;
+ }
+ if (!state.validate(done)) return false;
+ if (isNotActive()) {
+ last_stack_trace = new TCFNode[0];
+ result.setHasChilren(false);
+ return true;
+ }
+ TCFContextState state_data = state.getData();
+ if (state_data != null) {
+ result.setHasChilren(state_data.is_suspended);
+ return true;
+ }
+ children = children_stack;
+ }
+ else {
+ if (!model.getAutoChildrenListUpdates() && last_children_list != null) {
+ result.setHasChilren(last_children_list.length > 0);
+ return true;
+ }
+ children = children_exec;
+ }
+ }
+ else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_regs;
+ }
+ else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_exps;
+ }
+ else if (TCFModel.ID_EXPRESSION_HOVER.equals(view_id)) {
+ if (!run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && ctx.hasState()) children = children_hover_exps;
+ }
+ else if (IDebugUIConstants.ID_MODULE_VIEW.equals(view_id)) {
+ if (!mem_context.validate(done)) return false;
+ IMemory.MemoryContext ctx = mem_context.getData();
+ if (ctx != null) children = children_modules;
+ }
+ if (children != null) {
+ if (!children.validate(done)) return false;
+ if (children == children_stack) last_stack_trace = children_stack.toArray();
+ if (children == children_exec) last_children_list = children_exec.toArray();
+ result.setHasChilren(children.size() > 0);
+ }
+ else {
+ result.setHasChilren(false);
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean getData(ILabelUpdate result, Runnable done) {
+ result.getViewerInput();
+ if (!run_context.validate(done)) return false;
+ String image_name = null;
+ boolean suspended_by_bp = false;
+ StringBuffer label = new StringBuffer();
+ Throwable error = run_context.getError();
+ if (error != null) {
+ result.setForeground(new RGB(255, 0, 0), 0);
+ label.append(id);
+ label.append(": ");
+ label.append(TCFModel.getErrorMessage(error, false));
+ }
+ else {
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx == null) {
+ label.append(id);
+ }
+ else {
+ String nm = ctx.getName();
+ if (nm == null && !ctx.hasState()) {
+ String prs = ctx.getProcessID();
+ if (prs != null) {
+ if (!prs_context.validate(done)) return false;
+ IProcesses.ProcessContext pctx = prs_context.getData();
+ if (pctx != null) nm = pctx.getName();
+ }
+ }
+ label.append(nm != null ? nm : id);
+ if (ctx.hasState() && !TCFModel.ID_PINNED_VIEW.equals(result.getPresentationContext().getId())) {
+ // Thread
+ if (resume_pending && resumed_by_action || model.getActiveAction(id) != null) {
+ image_name = ImageCache.IMG_THREAD_RUNNNIG;
+ if (resume_pending && last_label != null) {
+ result.setImageDescriptor(ImageCache.getImageDescriptor(image_name), 0);
+ result.setLabel(last_label, 0);
+ return true;
+ }
+ label.append(" (Running)");
+ }
+ else if (resume_pending && last_label != null && last_image != null) {
+ result.setImageDescriptor(last_image, 0);
+ result.setLabel(last_label, 0);
+ return true;
+ }
+ else {
+ if (!state.validate(done)) return false;
+ TCFContextState state_data = state.getData();
+ if (isNotActive()) {
+ image_name = ImageCache.IMG_THREAD_NOT_ACTIVE;
+ label.append(" (Not active)");
+ if (state_data.suspend_reason != null && !state_data.suspend_reason.equals(IRunControl.REASON_USER_REQUEST)) {
+ label.append(" - ");
+ label.append(state_data.suspend_reason);
+ }
+ }
+ else {
+ if (state_data == null) image_name = ImageCache.IMG_THREAD_UNKNOWN_STATE;
+ else if (state_data.is_suspended) image_name = ImageCache.IMG_THREAD_SUSPENDED;
+ else image_name = ImageCache.IMG_THREAD_RUNNNIG;
+ if (state_data != null) {
+ if (!state_data.is_suspended) {
+ label.append(" (Running)");
+ }
+ else {
+ String s = null;
+ String r = model.getContextActionResult(id);
+ if (r == null) {
+ r = state_data.suspend_reason;
+ if (state_data.suspend_params != null) {
+ s = (String)state_data.suspend_params.get(IRunControl.STATE_SIGNAL_DESCRIPTION);
+ if (s == null) s = (String)state_data.suspend_params.get(IRunControl.STATE_SIGNAL_NAME);
+ }
+ }
+ suspended_by_bp = IRunControl.REASON_BREAKPOINT.equals(r);
+ if (r == null) r = "Suspended";
+ if (s != null) r += ": " + s;
+ label.append(" (");
+ label.append(r);
+ if (state_data.suspend_params != null) {
+ String prs = (String)state_data.suspend_params.get("Context");
+ if (prs != null) {
+ label.append(", ");
+ label.append(prs);
+ }
+ String cpu = (String)state_data.suspend_params.get("CPU");
+ if (cpu != null) {
+ label.append(", ");
+ label.append(cpu);
+ }
+ }
+ label.append(")");
+ }
+ }
+ }
+ }
+ last_children_state_info = null;
+ }
+ else {
+ // Thread container (process)
+ ChildrenStateInfo i = new ChildrenStateInfo();
+ if (!hasSuspendedChildren(i, done)) return false;
+ if (i.suspended) image_name = ImageCache.IMG_PROCESS_SUSPENDED;
+ else image_name = ImageCache.IMG_PROCESS_RUNNING;
+ suspended_by_bp = i.breakpoint;
+ last_children_state_info = i;
+ }
+ }
+ }
+ last_image = ImageCache.getImageDescriptor(image_name);
+ if (suspended_by_bp) last_image = ImageCache.addOverlay(last_image, ImageCache.IMG_BREAKPOINT_OVERLAY);
+ result.setImageDescriptor(last_image, 0);
+ result.setLabel(last_label = label.toString(), 0);
+ return true;
+ }
+
+ @Override
+ protected boolean getData(IViewerInputUpdate result, Runnable done) {
+ result.setInputElement(this);
+ String view_id = result.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(view_id)) {
+ if (!children_stack.validate(done)) return false;
+ TCFNodeStackFrame frame = children_stack.getTopFrame();
+ if (frame != null) result.setInputElement(frame);
+ }
+ else if (IDebugUIConstants.ID_MODULE_VIEW.equals(view_id)) {
+ // TODO: need to post view input delta when memory context changes
+ TCFDataCache<TCFNodeExecContext> mem = model.searchMemoryContext(this);
+ if (mem == null) return true;
+ if (!mem.validate(done)) return false;
+ if (mem.getData() == null) return true;
+ result.setInputElement(mem.getData());
+ }
+ return true;
+ }
+
+ @Override
+ public void refresh(IWorkbenchPart part) {
+ if (part instanceof IMemoryRenderingSite) {
+ model.onMemoryChanged(id, false, false);
+ }
+ else {
+ last_children_list = null;
+ last_children_state_info = null;
+ last_stack_trace = null;
+ last_label = null;
+ last_image = null;
+ super.refresh(part);
+ }
+ }
+
+ void postAllChangedDelta() {
+ postContentChangedDelta();
+ postStateChangedDelta();
+ }
+
+ void postContextAddedDelta() {
+ if (parent instanceof TCFNodeExecContext) {
+ TCFNodeExecContext exe = (TCFNodeExecContext)parent;
+ ChildrenStateInfo info = exe.last_children_state_info;
+ if (info != null) {
+ if (!model.getAutoChildrenListUpdates()) {
+ // Manual manual updates.
+ return;
+ }
+ if (!info.suspended && !info.not_active && model.getDelayChildrenListUpdates()) {
+ // Delay content update until a child is suspended.
+ exe.delayed_children_list_delta = true;
+ return;
+ }
+ }
+ }
+ for (TCFModelProxy p : model.getModelProxies()) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ /* Note: should use IModelDelta.INSERTED but it is broken in Eclipse 3.6 */
+ p.addDelta(this, IModelDelta.ADDED);
+ }
+ }
+ }
+
+ private void postContextRemovedDelta() {
+ if (parent instanceof TCFNodeExecContext) {
+ TCFNodeExecContext exe = (TCFNodeExecContext)parent;
+ ChildrenStateInfo info = exe.last_children_state_info;
+ if (info != null) {
+ if (!model.getAutoChildrenListUpdates()) {
+ // Manual manual updates.
+ return;
+ }
+ if (!info.suspended && !info.not_active && model.getDelayChildrenListUpdates()) {
+ // Delay content update until a child is suspended.
+ exe.delayed_children_list_delta = true;
+ return;
+ }
+ }
+ }
+ for (TCFModelProxy p : model.getModelProxies()) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ p.addDelta(this, IModelDelta.REMOVED);
+ }
+ }
+ }
+
+ private void postContentChangedDelta() {
+ delayed_children_list_delta = false;
+ for (TCFModelProxy p : model.getModelProxies()) {
+ int flags = 0;
+ String view_id = p.getPresentationContext().getId();
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(view_id) &&
+ (launch.getContextActionsCount(id) == 0 ||
+ !model.getDelayStackUpdateUtilLastStep())) {
+ flags |= IModelDelta.CONTENT;
+ }
+ if (IDebugUIConstants.ID_REGISTER_VIEW.equals(view_id) ||
+ IDebugUIConstants.ID_EXPRESSION_VIEW.equals(view_id) ||
+ TCFModel.ID_EXPRESSION_HOVER.equals(view_id)) {
+ if (p.getInput() == this) flags |= IModelDelta.CONTENT;
+ }
+ if (flags == 0) continue;
+ p.addDelta(this, flags);
+ }
+ }
+
+ private void postAllAndParentsChangedDelta() {
+ postContentChangedDelta();
+ TCFNode n = this;
+ while (n instanceof TCFNodeExecContext) {
+ TCFNodeExecContext e = (TCFNodeExecContext)n;
+ if (e.delayed_children_list_delta) e.postContentChangedDelta();
+ e.postStateChangedDelta();
+ n = n.parent;
+ }
+ }
+
+ public void postStateChangedDelta() {
+ for (TCFModelProxy p : model.getModelProxies()) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ p.addDelta(this, IModelDelta.STATE);
+ }
+ }
+ }
+
+ private void postModulesChangedDelta() {
+ for (TCFModelProxy p : model.getModelProxies()) {
+ if (IDebugUIConstants.ID_MODULE_VIEW.equals(p.getPresentationContext().getId())) {
+ p.addDelta(this, IModelDelta.CONTENT);
+ }
+ }
+ }
+
+ private void postStackChangedDelta() {
+ for (TCFModelProxy p : model.getModelProxies()) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getPresentationContext().getId())) {
+ p.addDelta(this, IModelDelta.CONTENT);
+ }
+ }
+ }
+
+ void onContextAdded(IRunControl.RunControlContext context) {
+ children_exec.onContextAdded(context);
+ }
+
+ void onContextChanged(IRunControl.RunControlContext context) {
+ assert !isDisposed();
+ full_name.reset();
+ run_context.reset(context);
+ symbols_node.reset();
+ memory_node.reset();
+ signal_mask.reset();
+ if (state.isValid()) {
+ TCFContextState s = state.getData();
+ if (s == null || s.is_suspended) state.reset();
+ }
+ children_stack.reset();
+ children_stack.onSourceMappingChange();
+ children_regs.reset();
+ children_exec.onAncestorContextChanged();
+ for (TCFNodeSymbol s : symbols.values()) s.onMemoryMapChanged();
+ postAllChangedDelta();
+ }
+
+ void onAncestorContextChanged() {
+ full_name.reset();
+ }
+
+ void onContextAdded(IMemory.MemoryContext context) {
+ children_exec.onContextAdded(context);
+ }
+
+ void onContextChanged(IMemory.MemoryContext context) {
+ assert !isDisposed();
+ clearLookupCaches();
+ mem_context.reset(context);
+ for (TCFNodeSymbol s : symbols.values()) s.onMemoryMapChanged();
+ postAllChangedDelta();
+ }
+
+ void onContextRemoved() {
+ assert !isDisposed();
+ resumed_cnt++;
+ resume_pending = false;
+ resumed_by_action = false;
+ dispose();
+ postContextRemovedDelta();
+ launch.removeContextActions(id);
+ }
+
+ void onExpressionAddedOrRemoved() {
+ children_exps.cancel();
+ children_stack.onExpressionAddedOrRemoved();
+ }
+
+ void onContainerSuspended() {
+ assert !isDisposed();
+ if (run_context.isValid()) {
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && !ctx.hasState()) return;
+ }
+ onContextSuspended(null, null, null);
+ }
+
+ void onContainerResumed() {
+ assert !isDisposed();
+ if (run_context.isValid()) {
+ IRunControl.RunControlContext ctx = run_context.getData();
+ if (ctx != null && !ctx.hasState()) return;
+ }
+ onContextResumed();
+ }
+
+ void onContextSuspended(String pc, String reason, Map<String,Object> params) {
+ assert !isDisposed();
+ if (pc != null) {
+ TCFContextState s = new TCFContextState();
+ s.is_suspended = true;
+ s.suspend_pc = pc;
+ s.suspend_reason = reason;
+ s.suspend_params = params;
+ state.reset(s);
+ }
+ else {
+ state.reset();
+ }
+ address.reset();
+ signal_mask.reset();
+ children_stack.onSuspended();
+ children_regs.onSuspended();
+ children_exps.onSuspended();
+ children_hover_exps.onSuspended();
+ children_log_exps.onSuspended();
+ for (TCFNodeSymbol s : symbols.values()) s.onExeStateChange();
+ if (model.getActiveAction(id) == null) {
+ boolean update_now = pc != null || resumed_by_action;
+ resumed_cnt++;
+ resume_pending = false;
+ resumed_by_action = false;
+ if (update_now) {
+ children_stack.postAllChangedDelta();
+ postAllAndParentsChangedDelta();
+ }
+ else {
+ final int cnt = ++resumed_cnt;
+ Protocol.invokeLater(500, new Runnable() {
+ public void run() {
+ if (cnt != resumed_cnt) return;
+ if (isDisposed()) return;
+ children_stack.postAllChangedDelta();
+ postAllAndParentsChangedDelta();
+ }
+ });
+ }
+ }
+ }
+
+ void onContextResumed() {
+ assert !isDisposed();
+ state.reset(new TCFContextState());
+ if (!resume_pending) {
+ final int cnt = ++resumed_cnt;
+ resume_pending = true;
+ resumed_by_action = model.getActiveAction(id) != null;
+ if (resumed_by_action) postAllChangedDelta();
+ Protocol.invokeLater(400, new Runnable() {
+ public void run() {
+ if (cnt != resumed_cnt) return;
+ if (isDisposed()) return;
+ children_stack.onResumed();
+ resume_pending = false;
+ postAllAndParentsChangedDelta();
+ model.onContextRunning();
+ }
+ });
+ }
+ }
+
+ void onContextActionDone() {
+ if (!state.isValid() || state.getData() == null || state.getData().is_suspended) {
+ resumed_cnt++;
+ resume_pending = false;
+ resumed_by_action = false;
+ }
+ postAllChangedDelta();
+ children_stack.postAllChangedDelta();
+ }
+
+ void onContextException(String msg) {
+ }
+
+ void onMemoryChanged(Number[] addr, long[] size) {
+ assert !isDisposed();
+ children_stack.onMemoryChanged();
+ children_exps.onMemoryChanged();
+ children_hover_exps.onMemoryChanged();
+ children_log_exps.onMemoryChanged();
+ postContentChangedDelta();
+ }
+
+ void onMemoryMapChanged() {
+ clearLookupCaches();
+ memory_map.reset();
+ children_modules.onMemoryMapChanged();
+ children_stack.onMemoryMapChanged();
+ children_exps.onMemoryMapChanged();
+ children_hover_exps.onMemoryMapChanged();
+ children_log_exps.onMemoryMapChanged();
+ postModulesChangedDelta();
+ }
+
+ void onRegistersChanged() {
+ children_stack.onRegistersChanged();
+ postContentChangedDelta();
+ }
+
+ void onRegisterValueChanged() {
+ if (state.isValid()) {
+ TCFContextState s = state.getData();
+ if (s == null || s.is_suspended) state.reset();
+ }
+ address.reset();
+ children_stack.onRegisterValueChanged();
+ children_exps.onRegisterValueChanged();
+ children_hover_exps.onRegisterValueChanged();
+ children_log_exps.onRegisterValueChanged();
+ postContentChangedDelta();
+ }
+
+ void onPreferencesChanged() {
+ if (delayed_children_list_delta && !model.getDelayChildrenListUpdates() ||
+ model.getAutoChildrenListUpdates()) postContentChangedDelta();
+ children_stack.onPreferencesChanged();
+ postStackChangedDelta();
+ }
+
+ void riseTraceLimit() {
+ children_stack.riseTraceLimit();
+ postStackChangedDelta();
+ }
+
+ public boolean hasSuspendedChildren(ChildrenStateInfo info, Runnable done) {
+ if (!children_exec.validate(done)) return false;
+ Map<String,TCFNode> m = children_exec.getData();
+ if (m == null || m.size() == 0) return true;
+ for (TCFNode n : m.values()) {
+ if (!(n instanceof TCFNodeExecContext)) continue;
+ TCFNodeExecContext e = (TCFNodeExecContext)n;
+ if (!e.run_context.validate(done)) return false;
+ IRunControl.RunControlContext ctx = e.run_context.getData();
+ if (ctx != null && ctx.hasState()) {
+ TCFDataCache<TCFContextState> state_cache = e.getState();
+ if (!state_cache.validate(done)) return false;
+ TCFContextState state_data = state_cache.getData();
+ if (state_data != null) {
+ if (!state_data.is_suspended) {
+ info.running = true;
+ }
+ else if (e.isNotActive()) {
+ info.not_active = true;
+ }
+ else {
+ info.suspended = true;
+ String r = model.getContextActionResult(e.id);
+ if (r == null) r = state_data.suspend_reason;
+ if (IRunControl.REASON_BREAKPOINT.equals(r)) info.breakpoint = true;
+ }
+ }
+ }
+ else {
+ if (!e.hasSuspendedChildren(info, done)) return false;
+ }
+ if (info.breakpoint && info.running) break;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(TCFNode n) {
+ if (n instanceof TCFNodeExecContext) {
+ TCFNodeExecContext f = (TCFNodeExecContext)n;
+ if (mem_seq_no < f.mem_seq_no) return -1;
+ if (mem_seq_no > f.mem_seq_no) return +1;
+ if (exe_seq_no < f.exe_seq_no) return -1;
+ if (exe_seq_no > f.exe_seq_no) return +1;
+ }
+ return id.compareTo(n.id);
+ }
+}

Back to the top