flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ftho...@apache.org
Subject [13/15] FLEX-34291: Merge the donated FDB with the current one.
Date Wed, 30 Apr 2014 09:59:02 GMT
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/379cb609/modules/debugger/src/java/flash/tools/debugger/concrete/DManager.java
----------------------------------------------------------------------
diff --git a/modules/debugger/src/java/flash/tools/debugger/concrete/DManager.java b/modules/debugger/src/java/flash/tools/debugger/concrete/DManager.java
index a290b14..a8b1c8a 100644
--- a/modules/debugger/src/java/flash/tools/debugger/concrete/DManager.java
+++ b/modules/debugger/src/java/flash/tools/debugger/concrete/DManager.java
@@ -1,34 +1,37 @@
 /*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 package flash.tools.debugger.concrete;
 
 import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import flash.tools.debugger.Isolate;
 import flash.tools.debugger.SourceLocator;
 import flash.tools.debugger.SuspendReason;
+import flash.tools.debugger.SwfInfo;
 import flash.tools.debugger.Value;
 import flash.tools.debugger.VariableAttribute;
 import flash.tools.debugger.VariableType;
@@ -39,9 +42,9 @@ import flash.tools.debugger.events.DivideByZeroFault;
 import flash.tools.debugger.events.ExceptionFault;
 import flash.tools.debugger.events.FaultEvent;
 import flash.tools.debugger.events.FileListModifiedEvent;
-import flash.tools.debugger.events.InvalidTargetFault;
-import flash.tools.debugger.events.InvalidURLFault;
 import flash.tools.debugger.events.InvalidWithFault;
+import flash.tools.debugger.events.IsolateCreateEvent;
+import flash.tools.debugger.events.IsolateExitEvent;
 import flash.tools.debugger.events.ProtoLimitFault;
 import flash.tools.debugger.events.RecursionLimitFault;
 import flash.tools.debugger.events.ScriptTimeoutFault;
@@ -52,262 +55,374 @@ import flash.tools.debugger.events.TraceEvent;
 import flash.util.Trace;
 
 /**
- * Implements the receiving and updating of debug state from the socket connection
- * of the Flash Player.
+ * Implements the receiving and updating of debug state from the socket
+ * connection of the Flash Player.
  */
-public class DManager implements DProtocolNotifierIF, SourceLocator
-{
-	private final HashMap<String, String>	m_parms;
-	private final Map<Integer,DModule>		m_source;	   /* WARNING: accessed from multiple threads */
-	private final ArrayList<DLocation>		m_breakpoints; /* WARNING: accessed from multiple threads */
-	private final ArrayList<DSwfInfo>		m_swfInfo;     /* WARNING: accessed from multiple threads */
-	private final ArrayList<DWatch>			m_watchpoints; /* WARNING: accessed from multiple threads */
+public class DManager implements DProtocolNotifierIF, SourceLocator {
+	private final HashMap<String, String> m_parms;
 
-	/**
-	 * The currently active stack frames.
-	 */
-	private ArrayList<DStackContext>		m_frames;
+	private final HashMap<Integer, DIsolate> m_isolates; /*
+														 * WARNING: accessed
+														 * from multiple threads
+														 */
 
 	/**
-	 * The stack frames that were active the last time the player was suspended.
+	 * The currently active isolate or worker
 	 */
-	private ArrayList<DStackContext>		m_previousFrames;
+	private Isolate m_activeIsolate = DEFAULT_ISOLATE;
+
+	private LinkedList<DebugEvent> m_event; /*
+											 * our event queue; WARNING:
+											 * accessed from multiple threads
+											 */
+	private SourceLocator m_sourceLocator;
+
+
+	private boolean m_squelchEnabled; /*
+									 * true if we are talking to a squelch
+									 * enabled debug player
+									 */
+	private int m_playerVersion; /*
+								 * player version number obtained from InVersion
+								 * message; e.g. 9 for Flash Player 9.0
+								 */
+
+	private boolean m_sourceListModified; /*
+										 * deprecated; indicates m_source has
+										 * changed since last call to
+										 * getSource(). WARNING: lock with
+										 * synchronized (m_source) { ... }
+										 */
+	private byte[] m_actions; /* deprecated */
+	private String[] m_lastConstantPool; /* deprecated */
 
-	/**
-	 * A list of all known variables in the player.  Stored as a mapping
-	 * from an object's id to its DValue.
-	 */
-	private Map<Long,DValue>				m_values;
+	// SWF/SWD fetching and parsing
+	private String m_uri;
+	private byte[] m_swf; // latest swf obtained from get swf
+	private byte[] m_swd; // latest swd obtained from get swd
+
+	private Map<String, String> m_options = new HashMap<String, String>(); // Player
+																			// options
+																			// that
+																			// have
+																			// been
+																			// queried
+																			// by
+																			// OutGetOption,
+																			// and
+																			// come
+																			// back
+																			// via
+																			// InOption
 
-	/**
-	 * A list of all known variables in the player from the previous time
-	 * the player was suspended.  Stored as a mapping from an object's id
-	 * to its DValue.
-	 */
-	private Map<Long,DValue>				m_previousValues;
-
-	private LinkedList<DebugEvent> m_event;	/* our event queue; WARNING: accessed from multiple threads */
-	private DSuspendInfo	m_suspendInfo;	/* info for when we are stopped */
-	private SourceLocator	m_sourceLocator;
-
-	private DSwfInfo	m_lastSwfInfo;		/* hack for syncing swfinfo records with incoming InScript messages */
-	private DVariable	m_lastInGetVariable;/* hack for getVariable call to work with getters */
-	private boolean		m_attachChildren;	/* hack for getVariable call to work with getters */
-	private DVariable	m_lastInCallFunction; /* hack for callFunction to work */
-	private DVariable	m_lastInBinaryOp;
-	private boolean		m_squelchEnabled;	/* true if we are talking to a squelch enabled debug player */
-	private int			m_playerVersion;	/* player version number obtained from InVersion message; e.g. 9 for Flash Player 9.0 */
-
-	private boolean		m_sourceListModified;	/* deprecated; indicates m_source has changed since last
-												 * call to getSource().
-												 * WARNING: lock with synchronized (m_source) { ... }
-												 */
-	private byte[]		m_actions;				/* deprecated */
-	private String[]	m_lastConstantPool;		/* deprecated */
+	public static final String ARGUMENTS_MARKER = "$arguments"; //$NON-NLS-1$
+	public static final String SCOPE_CHAIN_MARKER = "$scopechain"; //$NON-NLS-1$
+	
+	private static final DIsolate DEFAULT_ISOLATE = DIsolate.DEFAULT_ISOLATE;
+	private Isolate m_inIsolate = DEFAULT_ISOLATE;
+	private final Object m_inIsolateLock;
+	private final Object m_activeIsolateLock;
+	private boolean m_wideLines;
+	private DManagerIsolateState m_mainState;
+	private HashMap<Integer, DManagerIsolateState> m_isolateState;
+
+
+	class DManagerIsolateState {
+		public DSuspendInfo m_suspendInfo;
+		public DSwfInfo m_lastSwfInfo; /*
+										 * hack for syncing swfinfo records with
+										 * incoming InScript messages
+										 */
+		public DVariable m_lastInGetVariable;/*
+											 * hack for getVariable call to work
+											 * with getters
+											 */
+		public boolean m_attachChildren; /*
+										 * hack for getVariable call to work
+										 * with getters
+										 */
+		public DVariable m_lastInCallFunction; /* hack for callFunction to work */
+		public DVariable m_lastInBinaryOp;
+		private boolean m_executingPlayerCode;
+		private FaultEvent m_faultEventDuringPlayerCodeExecution;
+
+		public final ArrayList<DLocation> m_breakpoints; /*
+														 * WARNING: accessed
+														 * from multiple threads
+														 */
+		public final Map<Integer, DModule> m_source; /*
+													 * WARNING: accessed from
+													 * multiple threads
+													 */
+		private final ArrayList<DSwfInfo> m_swfInfo; /*
+													 * WARNING: accessed from
+													 * multiple threads
+													 */
+		private final ArrayList<DWatch> m_watchpoints; /*
+														 * WARNING: accessed
+														 * from multiple threads
+														 */
 
-	// SWF/SWD fetching and parsing
-	private String		m_uri;
-	private byte[]		m_swf;					// latest swf obtained from get swf
-	private byte[]		m_swd;					// latest swd obtained from get swd
+		/**
+		 * The currently active stack frames.
+		 */
+		public ArrayList<DStackContext> m_frames;
+
+		/**
+		 * The stack frames that were active the last time the player was
+		 * suspended.
+		 */
+		public ArrayList<DStackContext> m_previousFrames;
 
-	private boolean		m_executingPlayerCode;
-	private FaultEvent	m_faultEventDuringPlayerCodeExecution;
+		/**
+		 * A list of all known variables in the player. Stored as a mapping from
+		 * an object's id to its DValue.
+		 */
+		public Map<Long, DValue> m_values;
 
-	private Map<String, String>	m_options = new HashMap<String, String>();	// Player options that have been queried by OutGetOption, and come back via InOption
+		/**
+		 * A list of all known variables in the player from the previous time
+		 * the player was suspended. Stored as a mapping from an object's id to
+		 * its DValue.
+		 */
+		public Map<Long, DValue> m_previousValues;
+
+		public DManagerIsolateState() {
+			m_source = new HashMap<Integer, DModule>();
+			m_values = new HashMap<Long, DValue>();
+			m_previousValues = new HashMap<Long, DValue>();
+			m_frames = new ArrayList<DStackContext>();
+			m_previousFrames = new ArrayList<DStackContext>();
+			m_suspendInfo = null;
+			m_lastInCallFunction = null;
+			m_breakpoints = new ArrayList<DLocation>();
+			m_swfInfo = new ArrayList<DSwfInfo>();
+			m_watchpoints = new ArrayList<DWatch>();
+			m_suspendInfo = null;
+			m_lastInGetVariable = null;
+			m_attachChildren = true;
+			m_lastInCallFunction = null;
 
-	public static final String ARGUMENTS_MARKER = "$arguments"; //$NON-NLS-1$
-	public static final String SCOPE_CHAIN_MARKER = "$scopechain"; //$NON-NLS-1$
+		}
+	}
+
+	private DManagerIsolateState getIsolateState(int isolateId) {
+		if (isolateId == Isolate.DEFAULT_ID)
+			return m_mainState;
+		
+		DManagerIsolateState isolateState = null;
+		if (!m_isolateState.containsKey(isolateId)) {
+			isolateState = new DManagerIsolateState();
+			m_isolateState.put(isolateId, isolateState);
+		} else
+			isolateState = m_isolateState.get(isolateId);
+		return isolateState;
+	}
 
-	public DManager()
-	{
+	public DManager() {
 		m_parms = new HashMap<String, String>();
-		m_source = new HashMap<Integer, DModule>();
-		m_breakpoints = new ArrayList<DLocation>();
-		m_values = new HashMap<Long, DValue>();
-		m_previousValues = new HashMap<Long, DValue>();
-		m_frames = new ArrayList<DStackContext>();
-		m_previousFrames = new ArrayList<DStackContext>();
-		m_swfInfo = new ArrayList<DSwfInfo>();
-		m_watchpoints = new ArrayList<DWatch>();
+		
+		m_isolates = new HashMap<Integer, DIsolate>();
+		m_isolates.put(Isolate.DEFAULT_ID, DEFAULT_ISOLATE);
 		m_event = new LinkedList<DebugEvent>();
-		m_suspendInfo = null;
 		m_sourceLocator = null;
-
-		m_lastInGetVariable = null;
-		m_attachChildren = true;
-		m_lastInCallFunction = null;
 		m_squelchEnabled = false;
 		m_lastConstantPool = null;
-        m_playerVersion = -1; // -1 => unknown
+		m_playerVersion = -1; // -1 => unknown
+		m_isolateState = new HashMap<Integer, DManagerIsolateState>();
+		m_mainState = new DManagerIsolateState();
+		m_isolateState.put(Isolate.DEFAULT_ID, m_mainState);
+		m_inIsolateLock = new Object();
+		m_activeIsolateLock = new Object();
+		m_wideLines = false;
+	}
+
+	public void setWideLines(boolean value) {
+		m_wideLines = value;
+	}
+	
+	public String getURI() {
+		return m_uri;
+	}
+
+	public byte[] getSWF() {
+		return m_swf;
+	}
+
+	public byte[] getSWD() {
+		return m_swd;
+	}
+
+	public byte[] getActions() {
+		return m_actions;
 	}
 
-	public String getURI()		{ return m_uri; }
-    public byte[] getSWF()		{ return m_swf; }
-    public byte[] getSWD()		{ return m_swd; }
-    public byte[] getActions()	{ return m_actions; }
-    
-    /** Returns the Flash Player version number; e.g. 9 for Flash Player 9.0 */
-    public int    getVersion()  { return m_playerVersion; }
-    
-	public SourceLocator getSourceLocator() { return m_sourceLocator; }
-	public void setSourceLocator(SourceLocator sl) { m_sourceLocator = sl; }
+	/** Returns the Flash Player version number; e.g. 9 for Flash Player 9.0 */
+	public int getVersion() {
+		return m_playerVersion;
+	}
+
+	public SourceLocator getSourceLocator() {
+		return m_sourceLocator;
+	}
+
+	public void setSourceLocator(SourceLocator sl) {
+		m_sourceLocator = sl;
+	}
 
 	/**
-	 * If this feature is enabled then we do not attempt to attach
-	 * child variables to parents.
+	 * If this feature is enabled then we do not attempt to attach child
+	 * variables to parents.
 	 */
-	public void enableChildAttach(boolean enable) { m_attachChildren = enable; }
+	public void enableChildAttach(boolean enable, int isolateId) {
+		getIsolateState(isolateId).m_attachChildren = enable;
+	}
 
 	// return/clear the last variable seen from an InGetVariable message
-	public DVariable	lastVariable()			{ return m_lastInGetVariable; }
-	public void			clearLastVariable()		{ m_lastInGetVariable = null; }
+	public DVariable lastVariable(int isolateId) {
+		return getIsolateState(isolateId).m_lastInGetVariable;
+	}
+
+	public void clearLastVariable(int isolateId) {
+		getIsolateState(isolateId).m_lastInGetVariable = null;
+	}
 
 	// return/clear the last variable seen from an InCallFunction message
-	public DVariable	lastFunctionCall()		{ return m_lastInCallFunction; }
-	public void			clearLastFunctionCall()	{ m_lastInCallFunction = null; }
+	public DVariable lastFunctionCall(int isolateId) {
+		return getIsolateState(isolateId).m_lastInCallFunction;
+	}
+
+	public void clearLastFunctionCall(int isolateId) {
+		getIsolateState(isolateId).m_lastInCallFunction = null;
+	}
 
 	// return/clear the last binary op result seen from an InBinaryOp message
-	public DVariable	lastBinaryOp()			{ return m_lastInBinaryOp; }
-	public void			clearLastBinaryOp()		{ m_lastInBinaryOp = null; }
+	public DVariable lastBinaryOp(int isolateId) {
+		return getIsolateState(isolateId).m_lastInBinaryOp;
+	}
+
+	public void clearLastBinaryOp(int isolateId) {
+		getIsolateState(isolateId).m_lastInBinaryOp = null;
+	}
 
 	/*
 	 * Frees up any information we have kept about
 	 */
-	void freeCaches()
-	{
-		clearFrames();
-		freeValueCache();
+	void freeCaches(int isolateId) {
+		clearFrames(isolateId);
+		freeValueCache(isolateId);
 	}
 
-	void freeValueCache()
-	{
-		m_previousValues = m_values;
-		m_values = new HashMap<Long, DValue>();
+	void freeValueCache(int isolateId) {
+		DManagerIsolateState state = getIsolateState(isolateId);
+		state.m_previousValues = state.m_values;
+		state.m_values = new HashMap<Long, DValue>();
 
-		// mark all frames as stale
-		int size = getFrameCount();
-		for(int i=0; i<size; i++)
-			getFrame(i).markStale();
+		int size = getFrameCount(isolateId);
+		for (int i = 0; i < size; i++)
+			getFrame(i, isolateId).markStale();
 	}
 
 	// continuing our execution
-	void continuing()
-	{
-		freeCaches();
-		m_suspendInfo = null;
+	void continuing(int isolateId) {
+		freeCaches(isolateId);
+		getIsolateState(isolateId).m_suspendInfo = null;
 	}
 
 	/**
 	 * Variables
 	 */
-	DValue getOrCreateValue(long id)
-	{
-		DValue v = getValue(id);
-		if (v == null)
-		{
-			v = new DValue(id);
-			putValue(id, v);
+	DValue getOrCreateValue(long id, int isolateId) {
+		DValue v = getValue(id, isolateId);
+		if (v == null) {
+			v = new DValue(id, isolateId);
+			putValue(id, v, isolateId);
 		}
 		return v;
 	}
 
-	// Simple DSwfInfo getters
-	public DSwfInfo[] getSwfInfos()
-	{
-		synchronized (m_swfInfo)
-		{
-			return m_swfInfo.toArray( new DSwfInfo[m_swfInfo.size()] );
+	public DSwfInfo[] getSwfInfos(int isolateId) {
+		ArrayList<DSwfInfo> swfInfos = getIsolateState(isolateId).m_swfInfo;
+		synchronized (swfInfos) {
+			return swfInfos.toArray(new DSwfInfo[swfInfos.size()]);
 		}
 	}
 
-	public DSwfInfo getSwfInfo(int at)
-	{
-		synchronized (m_swfInfo)
-		{
-			return m_swfInfo.get(at);
+	public DSwfInfo getSwfInfo(int at, int isolateId) {
+		ArrayList<DSwfInfo> swfInfos = getIsolateState(isolateId).m_swfInfo;
+		synchronized (swfInfos) {
+			return swfInfos.get(at);
 		}
 	}
 
-	public int getSwfInfoCount()
-	{
-		synchronized (m_swfInfo)
-		{
-			return m_swfInfo.size();
+	public int getSwfInfoCount(int isolateId) {
+		ArrayList<DSwfInfo> swfInfos = getIsolateState(isolateId).m_swfInfo;
+		synchronized (swfInfos) {
+			return swfInfos.size();
 		}
 	}
 
 	/**
-	 * Obtains a SwfInfo object at the given index or if one
-	 * doesn't yet exist at that location, creates a new empty
-	 * one there and returns it.
+	 * Obtains a SwfInfo object at the given index or if one doesn't yet exist
+	 * at that location, creates a new empty one there and returns it.
 	 */
-	DSwfInfo getOrCreateSwfInfo(int at)
-	{
-		synchronized (m_swfInfo)
-		{
-			DSwfInfo i = (at > -1 && at < getSwfInfoCount()) ? getSwfInfo(at) : null;
-			if (i == null)
-			{
+	DSwfInfo getOrCreateSwfInfo(int at, int isolateId) {
+		ArrayList<DSwfInfo> swfInfos = getIsolateState(isolateId).m_swfInfo;
+		synchronized (swfInfos) {
+			DSwfInfo i = (at > -1 && at < getSwfInfoCount(isolateId)) ? getSwfInfo(
+					at, isolateId) : null;
+			if (i == null) {
 				// are we above water
 				at = (at < 0) ? 0 : at;
 
 				// fill all the gaps with null; really shouldn't be any...
-				while(at > m_swfInfo.size())
-					m_swfInfo.add(null);
+				while (at >= swfInfos.size())
+					swfInfos.add(null);
 
-				i = new DSwfInfo(at);
-				m_swfInfo.add(at, i);
+				i = new DSwfInfo(at, isolateId);
+				swfInfos.set(at, i);
 			}
 			return i;
 		}
 	}
 
 	/**
-	 * Get the most recently active swfInfo object.
-	 * We define active as the most recently seen swfInfo
+	 * Get the most recently active swfInfo object. We define active as the most
+	 * recently seen swfInfo
 	 */
-	DSwfInfo getActiveSwfInfo()
-	{
-		int count = getSwfInfoCount();
+	DSwfInfo getActiveSwfInfo(int isolateId) {
+		int count = getSwfInfoCount(isolateId);
 
 		// pick up the last one seen
-		DSwfInfo swf = m_lastSwfInfo;
+		DSwfInfo swf = getIsolateState(isolateId).m_lastSwfInfo;
 
 		// still don't have one then get or create the most recent one
 		// works if count = 0
 		if (swf == null)
-			swf = getOrCreateSwfInfo(count-1);
+			swf = getOrCreateSwfInfo(count - 1, isolateId);
 
-		if (swf.hasAllSource())
-		{
+		if (swf.hasAllSource()) {
 			// already full so create a new one on the end
-			swf = getOrCreateSwfInfo(count);
+			swf = getOrCreateSwfInfo(count, isolateId);
 		}
 		return swf;
 	}
 
 	/**
-	 * Walk the list of scripts and add them to our swfInfo object
-	 * This method may be called when min/max are zero and the swd
-	 * has not yet fully loaded in the player or it could be called
-	 * before we have all the scripts.
+	 * Walk the list of scripts and add them to our swfInfo object This method
+	 * may be called when min/max are zero and the swd has not yet fully loaded
+	 * in the player or it could be called before we have all the scripts.
 	 */
-	void tieScriptsToSwf(DSwfInfo info)
-	{
-		if (!info.hasAllSource())
-		{
+	void tieScriptsToSwf(DSwfInfo info, int isolateId) {
+		if (!info.hasAllSource()) {
 			int min = info.getFirstSourceId();
 			int max = info.getLastSourceId();
-//			System.out.println("attaching scripts "+min+"-"+max+" to "+info.getUrl());
-			for(int i=min; i<=max; i++)
-			{
-				DModule m = getSource(i);
-				if (m == null)
-				{
+			// System.out.println("attaching scripts "+min+"-"+max+" to "+info.getUrl());
+			for (int i = min; i <= max; i++) {
+				DModule m = getSource(i, isolateId);
+				if (m == null) {
 					// this is ok, it means the scripts are coming...
-				}
-				else
-				{
+				} else {
 					info.addSource(i, m);
 				}
 			}
@@ -316,35 +431,39 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 
 	/**
 	 * Record a new source file.
-	 * @param name filename in "basepath;package;filename" format
-	 * @param swfIndex the index of the SWF with which this source is associated,
-	 *                 or -1 is we don't know
+	 * 
+	 * @param name
+	 *            filename in "basepath;package;filename" format
+	 * @param swfIndex
+	 *            the index of the SWF with which this source is associated, or
+	 *            -1 is we don't know
 	 * @return true if our list of source files was modified, or false if we
-	 * already knew about that particular source file.
+	 *         already knew about that particular source file.
 	 */
-	private boolean putSource(int swfIndex, int moduleId, int bitmap, String name, String text)
-	{
-		synchronized (m_source)
-		{
+	private boolean putSource(int swfIndex, int moduleId, int bitmap,
+			String name, String text, int isolateId) {
+		// if isolateIndex is not -1, augment swfIndex and moduleId with isolate
+		// info.
+		Map<Integer, DModule> source = getIsolateState(isolateId).m_source;
+		synchronized (source) {
 			// if we haven't already recorded this script then do so.
-			if (!m_source.containsKey(moduleId))
-	        {
-				DModule s = new DModule(this, moduleId, bitmap, name, text);
+			if (!source.containsKey(moduleId)) {
+				DModule s = new DModule(this, moduleId, bitmap, name, text, isolateId);
 
-	            // put source in our large pool
-	            m_source.put(moduleId, s);
+				// put source in our large pool
+				source.put(moduleId, s);
 
-	            // put the source in the currently active swf
-	            DSwfInfo swf;
-				if (swfIndex == -1)				// caller didn't tell us what swf thi is for
-					swf = getActiveSwfInfo();	// ... so guess
+				// put the source in the currently active swf
+				DSwfInfo swf;
+				if (swfIndex == -1) // caller didn't tell us what swf thi is for
+					swf = getActiveSwfInfo(isolateId); // ... so guess
 				else
-					swf = getOrCreateSwfInfo(swfIndex);
+					swf = getOrCreateSwfInfo(swfIndex, isolateId);
 
-	            swf.addSource(moduleId, s);
+				swf.addSource(moduleId, s);
 
 				return true;
-	        }
+			}
 
 			return false;
 		}
@@ -352,237 +471,246 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 
 	/**
 	 * Remove our record of a particular source file.
-	 * @param id the id of the file to forget about.
-	 * @return true if source file was removed; false if we didn't know about
-	 * it to begin with.
+	 * 
+	 * @param id
+	 *            the id of the file to forget about.
+	 * @return true if source file was removed; false if we didn't know about it
+	 *         to begin with.
 	 */
-	private boolean removeSource(int id)
-	{
-		synchronized (m_source)
-		{
-			try
-			{
-				m_source.remove(id);
-			}
-			catch(Exception e)
-			{
+	private boolean removeSource(int id, int isolateId) {
+		Map<Integer, DModule> source = getIsolateState(isolateId).m_source;
+		synchronized (source) {
+			try {
+				source.remove(id);
+			} catch (Exception e) {
 				return false;
 			}
 			return true;
 		}
 	}
 
-	public DModule getSource(int id)
-	{
-		synchronized (m_source)
-		{
-			return m_source.get(id);
+	public DModule getSource(int id, int isolateId) {
+		Map<Integer, DModule> source = getIsolateState(isolateId).m_source;
+		synchronized (source) {
+			return source.get(id);
 		}
 	}
 
 	// @deprecated
-	public DModule[] getSources()
-	{
-		synchronized (m_source)
-		{
+	public DModule[] getSources() {
+		Map<Integer, DModule> source = getIsolateState(Isolate.DEFAULT_ID).m_source;
+		synchronized (source) {
 			m_sourceListModified = false;
 
 			/* find out the size of the array */
-			int count = m_source.size();
+			int count = source.size();
 			DModule[] ar = new DModule[count];
 
 			count = 0;
-			for (DModule sf: m_source.values())
+			for (DModule sf : source.values())
 				ar[count++] = sf;
 			return ar;
 		}
 	}
 
 	// @deprecated
-	boolean sourceListModified()
-	{
-		synchronized (m_source)
-		{
+	boolean sourceListModified() {
+		Map<Integer, DModule> source = getIsolateState(Isolate.DEFAULT_ID).m_source;
+		synchronized (source) {
 			return m_sourceListModified;
 		}
 	}
 
-	public DValue getValue(long id)
-	{
-		DValue v = m_values.get(id);
-		return v;
+	public DValue getValue(long id, int isolateId) {
+		return getIsolateState(isolateId).m_values.get(id);
 	}
 
 	/**
-	 * Returns the previous value object for the given id -- that is, the value that that
-	 * object had the last time the player was suspended.  Never requests it from the
-	 * player (because it can't, of course).  Returns <code>null</code> if we don't have
-	 * a value for that id.
+	 * Returns the previous value object for the given id -- that is, the value
+	 * that that object had the last time the player was suspended. Never
+	 * requests it from the player (because it can't, of course). Returns
+	 * <code>null</code> if we don't have a value for that id.
 	 */
-	public DValue getPreviousValue(long id)
-	{
-		return m_previousValues.get(id);
+	public DValue getPreviousValue(long id, int isolateId) {
+		return getIsolateState(isolateId).m_previousValues.get(id);
 	}
 
-	void putValue(long id, DValue v)
-	{
-		if (id != Value.UNKNOWN_ID)
-		{
-			m_values.put(id, v);
+	void putValue(long id, DValue v, int isolateId) {
+		if (id != Value.UNKNOWN_ID) {
+			getIsolateState(isolateId).m_values.put(id, v);
 		}
 	}
 
-	DValue removeValue(long id)
-	{
-		return m_values.remove((int)id);
+	DValue removeValue(long id, int isolateId) {
+		return getIsolateState(isolateId).m_values.remove((int)id);
 	}
 
-	void addVariableMember(long parentId, DVariable child)
-	{
-		DValue parent = getValue(parentId);
-		addVariableMember(parent, child);
+	void addVariableMember(long parentId, DVariable child, int isolateId) {
+		DValue parent = getValue(parentId, isolateId);
+		addVariableMember(parent, child, isolateId);
 	}
 
-	void addVariableMember(DValue parent, DVariable child)
-	{
-		if (m_attachChildren)
-		{
-			// There are certain situations when the Flash player will send us more
-			// than one variable or getter with the same name.  Basically, when a
-			// subclass implements (or overrides) something that was also declared in a
+	void addVariableMember(DValue parent, DVariable child, int isolateId) {
+		if (getIsolateState(isolateId).m_attachChildren) {
+			// There are certain situations when the Flash player will send us
+			// more
+			// than one variable or getter with the same name. Basically, when a
+			// subclass implements (or overrides) something that was also
+			// declared in a
 			// superclass, then we'll see that variable or getter in both the
 			// superclass and the subclass.
 			//
-			// Here are a few situations where that affects the debugger in different
+			// Here are a few situations where that affects the debugger in
+			// different
 			// ways:
 			//
-			// 1. When a class implements an interface, the class instance actually has
-			//    *two* members for each implemented function: One which is public and
-			//    represents the implementation function, and another which is internal
-			//    to the interface, and represents the declaration of the function.
-			//    Both of these come in to us.  In the UI, the one we want to show is
-			//    the public one.  They come in in random order (they are stored in a
-			//    hash table in the VM), so we don't know which one will come first.
+			// 1. When a class implements an interface, the class instance
+			// actually has
+			// *two* members for each implemented function: One which is public
+			// and
+			// represents the implementation function, and another which is
+			// internal
+			// to the interface, and represents the declaration of the function.
+			// Both of these come in to us. In the UI, the one we want to show
+			// is
+			// the public one. They come in in random order (they are stored in
+			// a
+			// hash table in the VM), so we don't know which one will come
+			// first.
 			//
-			// 2. When a superclass has a private member "m", and a subclass has its own
-			//    private member with the same name "m", we will receive both of them.
-			//    (They are scoped by different packages.)  In this case, the first one
-			//    the player sent us is the one from the subclass, and that is the one
-			//    we want to display in the debugger.
+			// 2. When a superclass has a private member "m", and a subclass has
+			// its own
+			// private member with the same name "m", we will receive both of
+			// them.
+			// (They are scoped by different packages.) In this case, the first
+			// one
+			// the player sent us is the one from the subclass, and that is the
+			// one
+			// we want to display in the debugger.
 			//
-			// The following logic correctly deals with all variations of those cases.
-			if (parent != null) 
-			{
-				DVariable existingChildWithSameName = parent.findMember(child.getName());
-				if (existingChildWithSameName != null)
-				{
+			// The following logic correctly deals with all variations of those
+			// cases.
+			if (parent != null) {
+				DVariable existingChildWithSameName = parent.findMember(child
+						.getName());
+				if (existingChildWithSameName != null) {
 					int existingScope = existingChildWithSameName.getScope();
 					int newScope = child.getScope();
 
-					if (existingScope == VariableAttribute.NAMESPACE_SCOPE && newScope == VariableAttribute.PUBLIC_SCOPE)
-					{
-						// This is the case described above where a class implements an interface,
-						// so that class's definition includes both a namespace-scoped declaration
-						// and a public declaration, in random order; in this case, the
-						// namespace-scoped declaration came first.  We want to use the public
+					if (existingScope == VariableAttribute.NAMESPACE_SCOPE
+							&& newScope == VariableAttribute.PUBLIC_SCOPE) {
+						// This is the case described above where a class
+						// implements an interface,
+						// so that class's definition includes both a
+						// namespace-scoped declaration
+						// and a public declaration, in random order; in this
+						// case, the
+						// namespace-scoped declaration came first. We want to
+						// use the public
 						// declaration.
 						parent.addMember(child);
-					}
-					else if (existingScope == VariableAttribute.PUBLIC_SCOPE && newScope == VariableAttribute.NAMESPACE_SCOPE)
-					{
+					} else if (existingScope == VariableAttribute.PUBLIC_SCOPE
+							&& newScope == VariableAttribute.NAMESPACE_SCOPE) {
 						// One of two things happened here:
 						//
-						// 1. This is the case described above where a class implements an interface,
-						//    so that class's definition includes both a namespace-scoped declaration
-						//    and a public declaration, in random order; in this case, the
-						//    public declaration came first.  It is tempting to use the public
-						//    member in this case, but there is a catch...
-						// 2. It might be more complicated than that: Perhaps there is interface I,
-						//    and class C1 implements I, but class C2 extends C1, and overrides
-						//    one of the members of I that was already implemented by C1.  In this
-						//    case, the public declaration from C2 came first, but now we are seeing
-						//    a namespace-scoped declaration in C1.  We need to record that the
-						//    member is public, but we also need to record that it is a member
-						//    of the base class, not just a member of the superclass.
+						// 1. This is the case described above where a class
+						// implements an interface,
+						// so that class's definition includes both a
+						// namespace-scoped declaration
+						// and a public declaration, in random order; in this
+						// case, the
+						// public declaration came first. It is tempting to use
+						// the public
+						// member in this case, but there is a catch...
+						// 2. It might be more complicated than that: Perhaps
+						// there is interface I,
+						// and class C1 implements I, but class C2 extends C1,
+						// and overrides
+						// one of the members of I that was already implemented
+						// by C1. In this
+						// case, the public declaration from C2 came first, but
+						// now we are seeing
+						// a namespace-scoped declaration in C1. We need to
+						// record that the
+						// member is public, but we also need to record that it
+						// is a member
+						// of the base class, not just a member of the
+						// superclass.
 						//
-						// The easiest way to deal with both cases is to use the child that came from
+						// The easiest way to deal with both cases is to use the
+						// child that came from
 						// the superclass, but to change its scope to public.
 						child.makePublic();
 						parent.addMember(child);
-					}
-					else if (existingScope != VariableAttribute.PRIVATE_SCOPE && existingScope == newScope)
-					{
-						// This is a public, protected, internal, or namespace-scoped member which
-						// was defined in a base class and overridden in a subclass.  We want to
-						// use the member from the base class, to that the debugger knows where the
+					} else if (existingScope != VariableAttribute.PRIVATE_SCOPE
+							&& existingScope == newScope) {
+						// This is a public, protected, internal, or
+						// namespace-scoped member which
+						// was defined in a base class and overridden in a
+						// subclass. We want to
+						// use the member from the base class, to that the
+						// debugger knows where the
 						// variable was actually defined.
 						parent.addMember(child);
-					}
-					else if (existingScope == VariableAttribute.PRIVATE_SCOPE && existingScope == newScope)
-					{
+					} else if (existingScope == VariableAttribute.PRIVATE_SCOPE
+							&& existingScope == newScope) {
 						parent.addInheritedPrivateMember(child);
 					}
-				}
-				else
-				{
+				} else {
 					parent.addMember(child);
 				}
 			}
 			// put child in the registry if it has an id and not already there
 			DValue childValue = (DValue) child.getValue();
 			long childId = childValue.getId();
-			if (childId != Value.UNKNOWN_ID)
-			{
-				DValue existingValue = getValue(childId);
-				if (existingValue != null)
-				{
-					assert existingValue == childValue; // TODO is this right? what about getters?
-				}
-				else
-				{
-					putValue(childId, childValue);
+			if (childId != Value.UNKNOWN_ID) {
+				DValue existingValue = getValue(childId, isolateId);
+				if (existingValue != null) {
+					assert existingValue == childValue; // TODO is this right?
+														// what about getters?
+				} else {
+					putValue(childId, childValue, isolateId);
 				}
 			}
 		}
 	}
 
 	// TODO is this right?
-	void addVariableMember(long parentId, DVariable child, long doubleAsId)
-	{
-		addVariableMember(parentId, child);
+	void addVariableMember(long parentId, DVariable child, long doubleAsId,
+			int isolateId) {
+		addVariableMember(parentId, child, isolateId);
 
 		// double book the child under another id
-		if (m_attachChildren)
-			putValue(doubleAsId, (DValue) child.getValue());
+		if (getIsolateState(isolateId).m_attachChildren)
+			putValue(doubleAsId, (DValue) child.getValue(), isolateId);
 	}
 
-	//  @deprecated last pool that was read
-	public String[] getConstantPool() { return m_lastConstantPool; }
+	// @deprecated last pool that was read
+	public String[] getConstantPool() {
+		return m_lastConstantPool;
+	}
 
 	/**
 	 * Breakpoints
 	 */
-	public DLocation getBreakpoint(int id)
-	{
-		synchronized (m_breakpoints)
-		{
+	public DLocation getBreakpoint(int id, int isolateId) {
+		ArrayList<DLocation> breakpoints = getIsolateState(isolateId).m_breakpoints;
+		synchronized (breakpoints) {
 			DLocation loc = null;
-			int which = findBreakpoint(id);
+			int which = findBreakpoint(id, isolateId);
 			if (which > -1)
-				loc = m_breakpoints.get(which);
+				loc = breakpoints.get(which);
 			return loc;
 		}
 	}
 
-	int findBreakpoint(int id)
-	{
-		synchronized (m_breakpoints)
-		{
+	int findBreakpoint(int id, int isolateId) {
+		ArrayList<DLocation> breakpoints = getIsolateState(isolateId).m_breakpoints;
+		synchronized (breakpoints) {
 			int which = -1;
-			int size = m_breakpoints.size();
-			for(int i=0; which < 0 && i<size; i++)
-			{
-				DLocation l = m_breakpoints.get(i);
+			int size = breakpoints.size();
+			for (int i = 0; which < 0 && i < size; i++) {
+				DLocation l = breakpoints.get(i);
 				if (l.getId() == id)
 					which = i;
 			}
@@ -590,68 +718,83 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 		}
 	}
 
-	DLocation removeBreakpoint(int id)
-	{
-		synchronized (m_breakpoints)
-		{
+	DLocation removeBreakpoint(int id, int isolateId) {
+		ArrayList<DLocation> breakpoints = getIsolateState(isolateId).m_breakpoints;
+		synchronized (breakpoints) {
 			DLocation loc = null;
-			int which = findBreakpoint(id);
-			if (which > -1)
-			{
-				loc = m_breakpoints.get(which);
-				m_breakpoints.remove(which);
+			int which = findBreakpoint(id, isolateId);
+			if (which > -1) {
+				loc = breakpoints.get(which);
+				breakpoints.remove(which);
 			}
 
 			return loc;
 		}
 	}
 
-	void addBreakpoint(int id, DLocation l)
-	{
-		synchronized (m_breakpoints)
-		{
-			m_breakpoints.add(l);
+	void addBreakpoint(int id, DLocation l, int isolateId) {
+		ArrayList<DLocation> breakpoints = getIsolateState(isolateId).m_breakpoints;
+		synchronized (breakpoints) {
+			breakpoints.add(l);
 		}
 	}
 
-	public DLocation[] getBreakpoints()
-	{
-		synchronized (m_breakpoints)
-		{
-			return m_breakpoints.toArray(new DLocation[m_breakpoints.size()]);
+	public DLocation[] getBreakpoints(int isolateId) {
+		ArrayList<DLocation> breakpoints = getIsolateState(isolateId).m_breakpoints;
+		synchronized (breakpoints) {
+			return breakpoints.toArray(new DLocation[breakpoints.size()]);
 		}
 	}
 
 	/**
 	 * Watchpoints
 	 */
-	public DWatch		getWatchpoint(int at)	{ synchronized (m_watchpoints) { return m_watchpoints.get(at); } }
-	public int			getWatchpointCount()	{ synchronized (m_watchpoints) { return m_watchpoints.size(); } }
-	public DWatch[]		getWatchpoints()		{ synchronized (m_watchpoints) { return m_watchpoints.toArray( new DWatch[m_watchpoints.size()] ); } }
+	public DWatch getWatchpoint(int at, int isolateId) {
+		DManagerIsolateState state = getIsolateState(isolateId);
+		synchronized (state.m_watchpoints) {
+			return state.m_watchpoints.get(at);
+		}
+	}
 
-	boolean addWatchpoint(DWatch w)				{ synchronized (m_watchpoints) { return m_watchpoints.add(w); } }
+	public int getWatchpointCount(int isolateId) {
+		DManagerIsolateState state = getIsolateState(isolateId);
+		synchronized (state.m_watchpoints) {
+			return state.m_watchpoints.size();
+		}
+	}
 
-	DWatch removeWatchpoint(int tag)
-	{
-		synchronized (m_watchpoints)
-		{
+	public DWatch[] getWatchpoints(int isolateId) {
+		DManagerIsolateState state = getIsolateState(isolateId);
+		synchronized (state.m_watchpoints) {
+			return state.m_watchpoints.toArray(new DWatch[state.m_watchpoints.size()]);
+		}
+	}
+
+	boolean addWatchpoint(DWatch w, int isolateId) {
+		ArrayList<DWatch> lockObject = getIsolateState(isolateId).m_watchpoints;
+		synchronized (lockObject) {
+			return lockObject.add(w);
+		}
+	}
+
+	DWatch removeWatchpoint(int tag, int isolateId) {
+		ArrayList<DWatch> lockObject = getIsolateState(isolateId).m_watchpoints;
+		synchronized (lockObject) {
 			DWatch w = null;
-			int at = findWatchpoint(tag);
+			int at = findWatchpoint(tag, isolateId);
 			if (at > -1)
-				w = m_watchpoints.remove(at);
+				w = lockObject.remove(at);
 			return w;
 		}
 	}
 
-	int findWatchpoint(int tag)
-	{
-		synchronized (m_watchpoints)
-		{
+	int findWatchpoint(int tag, int isolateId) {
+		ArrayList<DWatch> lockObject = getIsolateState(isolateId).m_watchpoints;
+		synchronized (lockObject) {
 			int at = -1;
-			int size = getWatchpointCount();
-			for(int i=0; i<size && at<0; i++)
-			{
-				DWatch w = getWatchpoint(i);
+			int size = getWatchpointCount(isolateId);
+			for (int i = 0; i < size && at < 0; i++) {
+				DWatch w = getWatchpoint(i, isolateId);
 				if (w.getTag() == tag)
 					at = i;
 			}
@@ -660,28 +803,140 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 	}
 
 	/**
+	 * Isolates
+	 */
+	public DIsolate getIsolate(int at) {
+
+		if (at == Isolate.DEFAULT_ID)
+			return (DIsolate) DEFAULT_ISOLATE;
+
+		synchronized (m_isolates) {
+			return m_isolates.get(at);
+		}
+	}
+
+	public DIsolate getOrCreateIsolate(int at) {
+		synchronized (m_isolates) {
+			if (m_isolates.containsKey(at)) {
+				return m_isolates.get(at);
+			} else {
+				DIsolate isolate = new DIsolate(at);
+				m_isolates.put(at, isolate);
+				return isolate;
+			}
+		}
+	}
+
+	public int getIsolateCount() {
+		synchronized (m_isolates) {
+			return m_isolates.size();
+		}
+	}
+
+	public DIsolate[] getIsolates() {
+		synchronized (m_isolates) {
+			return m_isolates.values().toArray(new DIsolate[m_isolates.size()]);
+		}
+	}
+
+	boolean addIsolate(DIsolate t) {
+		synchronized (m_isolates) {
+			m_isolates.put(t.getId(), t);
+			return true;
+		}
+	}
+
+	void clearIsolates() {
+		synchronized (m_isolates) {
+			m_isolates.clear();
+		}
+	}
+
+	DIsolate removeIsolate(int id) {
+		synchronized (m_isolates) {
+			DIsolate t = null;
+			int at = findIsolate(id);
+			if (at > -1)
+				t = m_isolates.remove(at);
+			return t;
+		}
+	}
+
+	int findIsolate(int id) {
+		synchronized (m_isolates) {
+			if (m_isolates.containsKey(id))
+				return id;
+			else
+				return -1;
+		}
+	}
+
+	void setActiveIsolate(Isolate t) {
+		synchronized (m_activeIsolateLock) {
+			if (t == null) {
+				m_activeIsolate = DEFAULT_ISOLATE;
+			} else
+				m_activeIsolate = t;
+		}
+	}
+	
+	Isolate getActiveIsolate() {
+		synchronized (m_activeIsolateLock) {
+			return m_activeIsolate;
+		}
+	}
+
+
+	void setInIsolate(Isolate t) {
+		synchronized (m_inIsolateLock) {
+			if (t == null) {
+				m_inIsolate = DEFAULT_ISOLATE;
+			} else
+				m_inIsolate = t;
+		}
+	}
+
+	Isolate getInIsolate() {
+		synchronized (m_inIsolateLock) {
+			return m_inIsolate;
+		}
+	}
+
+	Isolate getDefaultIsolate() {
+		return DEFAULT_ISOLATE;
+	}
+
+
+	/**
 	 * Frame stack management related stuff
+	 * 
 	 * @return true if we added this frame; false if we ignored it
 	 */
-	boolean addFrame(DStackContext ds)
-	{
-		m_frames.add(ds);
+	boolean addFrame(DStackContext ds, int isolateId) {
+		getIsolateState(isolateId).m_frames.add(ds);
 		return true;
 	}
 
-	void clearFrames()
-	{
-		if (m_frames.size() > 0)
-			m_previousFrames = m_frames;
-		m_frames = new ArrayList<DStackContext>();
+	void clearFrames(int isolateId) {
+		if (getIsolateState(isolateId).m_frames.size() > 0)
+			getIsolateState(isolateId).m_previousFrames = getIsolateState(isolateId).m_frames;
+		getIsolateState(isolateId).m_frames = new ArrayList<DStackContext>();
 	}
 
-	public DStackContext		getFrame(int at)		{ return m_frames.get(at);}
-	public int					getFrameCount()			{ return m_frames.size();}
-	public DStackContext[]		getFrames()				{ return m_frames.toArray( new DStackContext[m_frames.size()] );	}
+	public DStackContext getFrame(int at, int isolateId) {
+		return getIsolateState(isolateId).m_frames.get(at);
+	}
+
+	public int getFrameCount(int isolateId) {
+		return getIsolateState(isolateId).m_frames.size();
+	}
 
-	private boolean stringsEqual(String s1, String s2)
-	{
+	public DStackContext[] getFrames(int isolateId) {
+		ArrayList<DStackContext> frames = getIsolateState(isolateId).m_frames;
+		return frames.toArray(new DStackContext[frames.size()]);
+	}
+
+	private boolean stringsEqual(String s1, String s2) {
 		if (s1 == null)
 			return s2 == null;
 		else
@@ -691,34 +946,41 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 	/**
 	 * Correlates the old list of stack frames, from the last time the player
 	 * was suspended, with the new list of stack frames, attempting to guess
-	 * which frames correspond to each other.  This is done so that
+	 * which frames correspond to each other. This is done so that
 	 * Variable.hasValueChanged() can work correctly for local variables.
 	 */
-	private void mapOldFramesToNew() {
-		int oldSize = m_previousFrames.size();
-		int newSize = m_frames.size();
+	private void mapOldFramesToNew(int isolateId) {
+		ArrayList<DStackContext> previousFrames = null;
+		ArrayList<DStackContext> frames = null;
+		Map<Long, DValue> previousValues = null;
+
+		previousFrames = getIsolateState(isolateId).m_previousFrames;
+		frames = getIsolateState(isolateId).m_frames;
+		previousValues = getIsolateState(isolateId).m_previousValues;
+
+		int oldSize = previousFrames.size();
+		int newSize = frames.size();
 
 		// discard all old frames (we will restore some of them below)
 		DValue[] oldFrames = new DValue[oldSize];
 		for (int depth = 0; depth < oldSize; depth++) {
-			oldFrames[depth] = (DValue) m_previousValues.remove(Value.BASE_ID - depth);
+			oldFrames[depth] = (DValue) previousValues.remove(Value.BASE_ID
+					- depth);
 		}
 
 		// Start at the end of the stack (the stack frame farthest from the
 		// current one), and try to match up stack frames
-		int oldDepth = oldSize-1;
-		int newDepth = newSize-1;
-		while (oldDepth >= 0 && newDepth >= 0)
-		{
-			DStackContext oldFrame = m_previousFrames.get(oldDepth);
-			DStackContext newFrame = m_frames.get(newDepth);
-			if (oldFrame != null && newFrame != null)
-			{
-				if (stringsEqual(oldFrame.getCallSignature(), newFrame.getCallSignature()))
-				{
+		int oldDepth = oldSize - 1;
+		int newDepth = newSize - 1;
+		while (oldDepth >= 0 && newDepth >= 0) {
+			DStackContext oldFrame = previousFrames.get(oldDepth);
+			DStackContext newFrame = frames.get(newDepth);
+			if (oldFrame != null && newFrame != null) {
+				if (stringsEqual(oldFrame.getCallSignature(),
+						newFrame.getCallSignature())) {
 					DValue frame = oldFrames[oldDepth];
 					if (frame != null)
-						m_previousValues.put(Value.BASE_ID - newDepth, frame);
+						previousValues.put(Value.BASE_ID - newDepth, frame);
 				}
 			}
 			oldDepth--;
@@ -727,62 +989,72 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 	}
 
 	/**
-	 * Get function is only supported in players that
-	 * recognize the squelch message.
+	 * Get function is only supported in players that recognize the squelch
+	 * message.
 	 */
-	public boolean isGetSupported()
-	{
+	public boolean isGetSupported() {
 		return m_squelchEnabled;
 	}
 
+
 	/**
-	 * Returns a suspend information on
-	 * why the Player has suspended execution.
+	 * Returns a suspend information on why the Player has suspended execution.
+	 * 
 	 * @return see SuspendReason
 	 */
-	public DSuspendInfo getSuspendInfo()
-	{
-		return m_suspendInfo;
+	public DSuspendInfo getSuspendInfo(int isolateId) {
+		if (m_isolateState.containsKey(isolateId)) {
+			return m_isolateState.get(isolateId).m_suspendInfo;
+		}
+		return null;
+	}
+
+	public ArrayList<SwfInfo> getIsolateSwfList() {
+		ArrayList<SwfInfo> result = new ArrayList<SwfInfo>();
+
+		for (DManagerIsolateState state : m_isolateState.values()) {
+			if (state.m_swfInfo != null) {
+				result.addAll(state.m_swfInfo);
+			}
+		}
+
+		return result;
 	}
 
 	/**
 	 * Event management related stuff
 	 */
-	public int getEventCount()
-	{
-		synchronized (m_event) { return m_event.size(); }
+	public int getEventCount() {
+		synchronized (m_event) {
+			return m_event.size();
+		}
 	}
 
 	/**
 	 * Get an object on which callers can call wait(), in order to wait until
 	 * something happens.
-	 *
+	 * 
 	 * Note: The object will be signalled when EITHER of the following happens:
-	 * (1) An event is added to the event queue;
-	 * (2) The network connection is broken (and thus there will be no more events).
-	 *
+	 * (1) An event is added to the event queue; (2) The network connection is
+	 * broken (and thus there will be no more events).
+	 * 
 	 * @return an object on which the caller can call wait()
 	 */
-	public Object getEventNotifier()
-	{
+	public Object getEventNotifier() {
 		return m_event;
 	}
 
-	public DebugEvent nextEvent()
-	{
+	public DebugEvent nextEvent() {
 		DebugEvent s = null;
-		synchronized (m_event)
-		{
+		synchronized (m_event) {
 			if (m_event.size() > 0)
 				s = m_event.removeFirst();
 		}
 		return s;
 	}
 
-	public synchronized void addEvent(DebugEvent e)
-	{
-		synchronized (m_event)
-		{
+	public synchronized void addEvent(DebugEvent e) {
+		synchronized (m_event) {
 			m_event.add(e);
 			m_event.notifyAll(); // wake up listeners (see getEventNotifier())
 		}
@@ -791,954 +1063,1116 @@ public class DManager implements DProtocolNotifierIF, SourceLocator
 	/**
 	 * Issued when the socket connection to the player is cut
 	 */
-	public void disconnected()
-	{
-		synchronized (m_event)
-		{
+	public void disconnected() {
+		synchronized (m_event) {
 			m_event.notifyAll(); // see getEventNotifier()
 		}
 	}
 
 	/**
-	 * This is the core routine for decoding incoming messages and deciding what should be
-	 * done with them.  We have registered ourself with DProtocol to be notified when any
-	 * incoming messages have been received.
-	 *
-	 * It is important to note that we should not rely on the contents of the message
-	 * since it may be reused after we exit this method.
+	 * This is the core routine for decoding incoming messages and deciding what
+	 * should be done with them. We have registered ourself with DProtocol to be
+	 * notified when any incoming messages have been received.
+	 * 
+	 * It is important to note that we should not rely on the contents of the
+	 * message since it may be reused after we exit this method.
 	 */
-	public void messageArrived(DMessage msg, DProtocol which)
-	{
-		/* at this point we just open up a big switch statement and walk through all possible cases */
+	public void messageArrived(DMessage msg, DProtocol which) {
+		/*
+		 * at this point we just open up a big switch statement and walk through
+		 * all possible cases
+		 */
 		int type = msg.getType();
-//		System.out.println("manager msg = "+DMessage.inTypeName(type));
+		// System.out.println("manager msg = "+DMessage.inTypeName(type));
+		int inIsolateId = getInIsolate() != null ? getInIsolate().getId()
+				: Isolate.DEFAULT_ID;
+		if (inIsolateId != Isolate.DEFAULT_ID) {
+			msg.setTargetIsolate(inIsolateId);
+		}
+		switch (type) {
+		case DMessage.InVersion: {
+			long ver = msg.getDWord();
+			m_playerVersion = (int) ver;
+
+			// Newer players will send another byte, which is the pointer size
+			// that is used by the player (in bytes).
+			int pointerSize;
+			if (msg.getRemaining() >= 1)
+				pointerSize = msg.getByte();
+			else
+				pointerSize = 4;
+			DMessage.setSizeofPtr(pointerSize);
+			break;
+		}
 
-		switch(type)
-		{
-            case DMessage.InVersion:
-            {
-                long ver = msg.getDWord();
-                m_playerVersion = (int)ver;
-
-                // Newer players will send another byte, which is the pointer size
-                // that is used by the player (in bytes).
-                int pointerSize;
-                if (msg.getRemaining() >= 1)
-                	pointerSize = msg.getByte();
-                else
-                	pointerSize = 4;
-            	DMessage.setSizeofPtr(pointerSize);
-                break;
-            }
-
-			case DMessage.InErrorExecLimit:
-			{
-				handleFaultEvent(new RecursionLimitFault());
-				break;
-			}
+		case DMessage.InErrorExecLimit: {
+			handleFaultEvent(new RecursionLimitFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorWith:
-			{
-				handleFaultEvent(new InvalidWithFault());
-				break;
-			}
+		case DMessage.InErrorWith: {
+			handleFaultEvent(new InvalidWithFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorProtoLimit:
-			{
-				handleFaultEvent(new ProtoLimitFault());
-				break;
-			}
+		case DMessage.InErrorProtoLimit: {
+			handleFaultEvent(new ProtoLimitFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorURLOpen:
-			{
-				String url = msg.getString();
-				handleFaultEvent(new InvalidURLFault(url));
-				break;
-			}
+		case DMessage.InErrorURLOpen: {
+//			String url = msg.getString();
+//			handleFaultEvent(new InvalidURLFault(url, msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorTarget:
-			{
-				String name = msg.getString();
-				handleFaultEvent(new InvalidTargetFault(name));
-				break;
-			}
+		case DMessage.InErrorTarget: {
+//			String name = msg.getString();
+//			handleFaultEvent(new InvalidTargetFault(name, msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorException:
-			{
-				long offset = msg.getDWord();
-				// As of FP9, the player will also send the "toString()" message
-				// of the exception.  But for backward compatibility with older
-				// players, we won't assume that that is there.
-				String exceptionMessage;
-				boolean willExceptionBeCaught = false;
-				Value thrown = null;
-				if (msg.getRemaining() > 0)
-				{
-					exceptionMessage = msg.getString();
-					if (msg.getRemaining() > 0)
-					{
-						if (msg.getByte() != 0)
-						{
-							willExceptionBeCaught = (msg.getByte() != 0 ? true : false);
-							msg.getPtr();
-							DVariable thrownVar = extractVariable(msg);
-							thrown = thrownVar.getValue();
-						}
+		case DMessage.InErrorException: {
+			long offset = msg.getDWord();
+			// As of FP9, the player will also send the "toString()" message
+			// of the exception. But for backward compatibility with older
+			// players, we won't assume that that is there.
+			String exceptionMessage;
+			boolean willExceptionBeCaught = false;
+			Value thrown = null;
+			if (msg.getRemaining() > 0) {
+				exceptionMessage = msg.getString();
+				if (msg.getRemaining() > 0) {
+					if (msg.getByte() != 0) {
+						willExceptionBeCaught = (msg.getByte() != 0 ? true
+								: false);
+						msg.getPtr();
+						DVariable thrownVar = extractVariable(msg);
+						thrown = thrownVar.getValue();
 					}
 				}
-				else
-				{
-					exceptionMessage = ""; //$NON-NLS-1$
-				}
-				handleFaultEvent(new ExceptionFault(exceptionMessage, willExceptionBeCaught, thrown));
-				break;
+			} else {
+				exceptionMessage = ""; //$NON-NLS-1$
 			}
+			ExceptionFault exceptionFault = new ExceptionFault(
+					exceptionMessage, willExceptionBeCaught, thrown, msg.getTargetIsolate());
+			exceptionFault.isolateId = msg.getTargetIsolate();
+			handleFaultEvent(exceptionFault);
+			break;
+		}
 
-			case DMessage.InErrorStackUnderflow:
-			{
-				long offset = msg.getDWord();
-				handleFaultEvent(new StackUnderFlowFault());
-				break;
-			}
+		case DMessage.InErrorStackUnderflow: {
+//			long offset = msg.getDWord();
+			handleFaultEvent(new StackUnderFlowFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorZeroDivide:
-			{
-				long offset = msg.getDWord();
-				handleFaultEvent(new DivideByZeroFault());
-				break;
-			}
+		case DMessage.InErrorZeroDivide: {
+//			long offset = msg.getDWord();
+			handleFaultEvent(new DivideByZeroFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorScriptStuck:
-			{
-				handleFaultEvent(new ScriptTimeoutFault());
-				break;
-			}
+		case DMessage.InErrorScriptStuck: {
+			handleFaultEvent(new ScriptTimeoutFault(msg.getTargetIsolate()));
+			break;
+		}
 
-			case DMessage.InErrorConsole:
-			{
-				String s = msg.getString();
-				handleFaultEvent(new ConsoleErrorFault(s));
-				break;
-			}
+		case DMessage.InErrorConsole: {
+			String s = msg.getString();
+			handleFaultEvent(new ConsoleErrorFault(s, msg.getTargetIsolate()));
+			break;
+		}
 
-		    case DMessage.InTrace:
-			{
-				String text = msg.getString();
-				addEvent(new TraceEvent(text));
-				break;
-			}
+		case DMessage.InTrace: {
+			String text = msg.getString();
+			addEvent(new TraceEvent(text));
+			break;
+		}
 
-			case DMessage.InSquelch:
-			{
-				long state = msg.getDWord();
-				m_squelchEnabled = (state != 0) ? true : false;
-				break;
-			}
+		case DMessage.InSquelch: {
+			long state = msg.getDWord();
+			m_squelchEnabled = (state != 0) ? true : false;
+			break;
+		}
 
-			case DMessage.InParam:
-			{
-				String name = msg.getString();
-				String value = msg.getString();
+		case DMessage.InParam: {
+			String name = msg.getString();
+			String value = msg.getString();
 
-				// here's where we get movie = URL and password which I'm not sure what to do with?
-//				System.out.println(name+"="+value);
-				m_parms.put(name, value);
+			// here's where we get movie = URL and password which I'm not sure
+			// what to do with?
+			// System.out.println(name+"="+value);
+			m_parms.put(name, value);
 
-				// if string is a "movie", then this is a URL
-				if (name.startsWith("movie")) //$NON-NLS-1$
-					m_uri = convertToURI(value);
-				break;
-			}
+			// if string is a "movie", then this is a URL
+			if (name.startsWith("movie")) //$NON-NLS-1$
+				m_uri = convertToURI(value);
+			break;
+		}
 
-			case DMessage.InPlaceObject:
-			{
-				long objId = msg.getPtr();
-				String path = msg.getString();
-//				m_bag.placeObject((int)objId, path);
-				break;
-			}
+		case DMessage.InPlaceObject: {
+			long objId = msg.getPtr();
+			String path = msg.getString();
+			// m_bag.placeObject((int)objId, path);
+			break;
+		}
 
-			case DMessage.InSetProperty:
-			{
-				long objId = msg.getPtr();
-				int item = msg.getWord();
-				String value = msg.getString();
-				break;
-			}
+		case DMessage.InSetProperty: {
+			long objId = msg.getPtr();
+			int item = msg.getWord();
+			String value = msg.getString();
+			break;
+		}
 
-			case DMessage.InNewObject:
-			{
-				long objId = msg.getPtr();
-				break;
-			}
+		case DMessage.InNewObject: {
+			long objId = msg.getPtr();
+			break;
+		}
 
-			case DMessage.InRemoveObject:
-			{
-				long objId = msg.getPtr();
-//				m_bag.removeObject((int)objId);
-				break;
-			}
+		case DMessage.InRemoveObject: {
+			long objId = msg.getPtr();
+			// m_bag.removeObject((int)objId);
+			break;
+		}
 
-			case DMessage.InSetVariable:
-			{
-				long objId = msg.getPtr();
-				String name = msg.getString();
-				int dType = msg.getWord();
-				int flags = (int) msg.getDWord();
-				String value = msg.getString();
-
-//				m_bag.createVariable((int)objId, name, dType, flags, value);
-				break;
-			}
+		case DMessage.InSetVariable: {
+			long objId = msg.getPtr();
+			String name = msg.getString();
+			int dType = msg.getWord();
+			int flags = (int) msg.getDWord();
+			String value = msg.getString();
 
-			case DMessage.InDeleteVariable:
-			{
-				long objId = msg.getPtr();
-				String name = msg.getString();
-//				m_bag.deleteVariable((int)objId, name);
-				break;
-			}
+			// m_bag.createVariable((int)objId, name, dType, flags, value);
+			break;
+		}
 
-			case DMessage.InScript:
-			{
-				int module = (int)msg.getDWord();
-				int bitmap = (int)msg.getDWord();
-				String name = msg.getString(); // in "basepath;package;filename" format
-				String text = msg.getString();
-				int swfIndex = -1;
-
-				/* new in flash player 9: player tells us what swf this is for */
-				if (msg.getRemaining() >= 4)
-					swfIndex = (int)msg.getDWord();
-
-				synchronized (m_source)
-				{
-					// create new source file
-					if (putSource(swfIndex, module, bitmap, name, text))
-					{
-						// have we changed the list since last query
-						if (!m_sourceListModified)
-							addEvent(new FileListModifiedEvent());
-
-						m_sourceListModified = true;  /* current source list is stale */
-					}
-				}
-				break;
+		case DMessage.InDeleteVariable: {
+			long objId = msg.getPtr();
+			String name = msg.getString();
+			// m_bag.deleteVariable((int)objId, name);
+			break;
+		}
+
+		case DMessage.InScript: {
+			int module = (int) msg.getDWord();
+			int bitmap = (int) msg.getDWord();
+			String name = msg.getString(); // in "basepath;package;filename"
+											// format
+			String text = msg.getString();
+			int swfIndex = -1;
+			int isolateIndex = -1;
+
+			/* new in flash player 9: player tells us what swf this is for */
+			if (msg.getRemaining() >= 4)
+				swfIndex = (int) msg.getDWord();
+
+			isolateIndex = msg.getTargetIsolate();
+			getOrCreateIsolate(isolateIndex);
+			if (putSource(swfIndex, module, bitmap, name, text,
+					isolateIndex)) {
+				// have we changed the list since last query
+				if (!m_sourceListModified)
+					addEvent(new FileListModifiedEvent());
+
+				m_sourceListModified = true; 
 			}
+			break;
+		}
 
-			case DMessage.InRemoveScript:
-			{
-				long module = msg.getDWord();
-				synchronized (m_source)
-				{
-					if (removeSource((int)module))
-					{
-						// have we changed the list since last query
-						if (!m_sourceListModified)
-							addEvent(new FileListModifiedEvent());
-
-						m_sourceListModified = true;  /* current source list is stale */
-					}
+		case DMessage.InRemoveScript: {
+			long module = msg.getDWord();
+			int isolateId = msg.getTargetIsolate();
+			Map<Integer, DModule> source = getIsolateState(isolateId).m_source;
+			synchronized (source) {
+				if (removeSource((int) module, isolateId)) {
+					// have we changed the list since last query
+					if (!m_sourceListModified)
+						addEvent(new FileListModifiedEvent());
+
+					m_sourceListModified = true; /* current source list is stale */
 				}
-				break;
 			}
+			break;
+		}
 
-			case DMessage.InAskBreakpoints:
-			{
-				// the player has just loaded a swf and we know the player
-				// has halted, waiting for us to continue.  The only caveat
-				// is that it looks like it still does a number of things in
-				// the background which take a few seconds to complete.
-				if (m_suspendInfo == null)
-					m_suspendInfo = new DSuspendInfo(SuspendReason.ScriptLoaded, 0, 0, 0, 0);
-				break;
+		case DMessage.InAskBreakpoints: {
+			// the player has just loaded a swf and we know the player
+			// has halted, waiting for us to continue. The only caveat
+			// is that it looks like it still does a number of things in
+			// the background which take a few seconds to complete.
+			int targetIsolate = msg.getTargetIsolate();
+			DSuspendInfo iSusInfo = getIsolateState(targetIsolate).m_suspendInfo;
+			if (iSusInfo == null) {
+				iSusInfo = new DSuspendInfo(SuspendReason.ScriptLoaded, 0,
+						0, 0, 0);
 			}
+			break;
+		}
 
-			case DMessage.InBreakAt:
-			{
-				long bp = msg.getDWord();
-				long id = msg.getPtr();
-				String stack = msg.getString();
-//				System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16)+",id="+id+",stack=\n"+stack);
-
-				//System.out.println("InBreakAt");
-
-				int module = DLocation.decodeFile(bp);
-				int  line = DLocation.decodeLine (bp);
-				addEvent(new BreakEvent(module, line));
-				break;
+		case DMessage.InBreakAt: {
+			long bp = 0, wideLine = 0, wideModule = 0;
+			if (!m_wideLines) {
+				bp = msg.getDWord();
 			}
-
-			case DMessage.InContinue:
-			{
-				/* we are running again so trash all our variable contents */
-				continuing();
-				break;
+			else {
+				wideModule = msg.getDWord();
+				wideLine = msg.getDWord();
 			}
-
-			case DMessage.InSetLocalVariables:
-			{
-				long objId = msg.getPtr();
-//				m_bag.markObjectLocal((int)objId, true);
-				break;
+			long id = msg.getPtr();
+			String stack = msg.getString();
+			int targetIsolate = msg.getTargetIsolate();
+
+			int module = DLocation.decodeFile(bp);
+			int line = DLocation.decodeLine(bp);
+			if (m_wideLines) {
+				module = (int)wideModule;
+				line = (int)wideLine;
 			}
+			addEvent(new BreakEvent(module, line, targetIsolate));
+			break;
+		}
 
-			case DMessage.InSetBreakpoint:
-			{
-				long count = msg.getDWord();
-				while(count-- > 0)
-				{
-					long bp = msg.getDWord();
+		case DMessage.InContinue: {
+			/* we are running again so trash all our variable contents */
+			continuing(msg.getTargetIsolate());
+			break;
+		}
 
-					int fileId = DLocation.decodeFile(bp);
-					int line = DLocation.decodeLine(bp);
+		case DMessage.InSetLocalVariables: {
+//			long objId = msg.getPtr();
+			// m_bag.markObjectLocal((int)objId, true);
+			break;
+		}
 
-					DModule file = getSource(fileId);
-					DLocation l = new DLocation(file, line);
+		case DMessage.InSetBreakpoint: {
+			long count = msg.getDWord();
+			int targetIsolate = msg.getTargetIsolate();
+			while (count-- > 0) {
+				long bp = 0, moduleNumber = 0, lineNumber = 0;
+				if (!m_wideLines) {
+					bp = msg.getDWord();
+				}
+				else {
+					moduleNumber = msg.getDWord();
+					lineNumber = msg.getDWord();
+				}
 
-					if (file != null)
-						addBreakpoint((int)bp, l);
+				int fileId = DLocation.decodeFile(bp);
+				int line = DLocation.decodeLine(bp);
+				if (m_wideLines) {
+					fileId = (int)moduleNumber;
+					line = (int)lineNumber;
 				}
-				break;
-			}
 
-			case DMessage.InNumScript:
-			{
-				/* lets us know how many scripts there are */
-				int num = (int)msg.getDWord();
-				DSwfInfo swf;
+				DModule file = null;
+				file = getSource(fileId, targetIsolate);
 
-				/*
-				 * New as of flash player 9: another dword indicating which swf this is for.
-				 * That means we don't have to guess whether this is for an old SWF
-				 * which has just had some more modules loaded, or for a new SWF!
-				 */
-				if (msg.getRemaining() >= 4)
-				{
-					int swfIndex = (int) msg.getDWord();
-					swf = getOrCreateSwfInfo(swfIndex);
-					m_lastSwfInfo = swf;
-				}
-				else
-				{
-					/* This is not flash player 9 (or it is an early build of fp9).
-					 *
-					 * We use this message as a trigger that a new swf has been loaded, so make sure
-					 * we are ready to accept the scripts.
-					 */
-					swf = getActiveSwfInfo();
+				DLocation l = new DLocation(file, line, targetIsolate);
+
+				if (file != null) {
+					addBreakpoint((int) bp, l, targetIsolate);
 				}
+			}
+			break;
+		}
 
-				// It is NOT an error for the player to have sent us a new,
-				// different sourceExpectedCount from whatever we had before!
-				// In fact, this happens all the time, whenever a SWF has more
-				// than one ABC.
-				swf.setSourceExpectedCount(num);
-				break;
+		case DMessage.InNumScript: {
+			/* lets us know how many scripts there are */
+			int num = (int) msg.getDWord();
+			int targetIsolate = msg.getTargetIsolate();
+			DSwfInfo swf;
+
+			/*
+			 * New as of flash player 9: another dword indicating which swf this
+			 * is for. That means we don't have to guess whether this is for an
+			 * old SWF which has just had some more modules loaded, or for a new
+			 * SWF!
+			 */
+			if (msg.getRemaining() >= 4) {
+				int swfIndex = (int) msg.getDWord();
+				swf = getOrCreateSwfInfo(swfIndex, targetIsolate);
+				getIsolateState(targetIsolate).m_lastSwfInfo = swf;
+			} else {
+				/*
+				 * This is not flash player 9 (or it is an early build of fp9).
+				 * 
+				 * We use this message as a trigger that a new swf has been
+				 * loaded, so make sure we are ready to accept the scripts.
+				 */
+				swf = getActiveSwfInfo(targetIsolate);
 			}
 
-			case DMessage.InRemoveBreakpoint:
-			{
-				long count = msg.getDWord();
-				while(count-- > 0)
-				{
-					long bp = msg.getDWord();
-					removeBreakpoint((int)bp);
-				}
-				break;
+			// It is NOT an error for the player to have sent us a new,
+			// different sourceExpectedCount from whatever we had before!
+			// In fact, this happens all the time, whenever a SWF has more
+			// than one ABC.
+			swf.setSourceExpectedCount(num);
+			break;
+		}
 
+		case DMessage.InRemoveBreakpoint: {
+			long count = msg.getDWord();
+			int isolateId = msg.getTargetIsolate();
+			while (count-- > 0) {
+				long bp = msg.getDWord();
+				removeBreakpoint((int) bp, isolateId);
 			}
+			break;
 
-			case DMessage.InBreakAtExt:
-			{
-				long bp = msg.getDWord();
-				long num = msg.getDWord();
-
-//				System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16));
-				/* we have stack info to store away */
-				clearFrames();  // just in case
-				int depth = 0;
-				while(num-- > 0)
-				{
-					long bpi = msg.getDWord();
-					long id = msg.getPtr();
-					String stack = msg.getString();
-					int module = DLocation.decodeFile(bpi);
-					int  line = DLocation.decodeLine (bpi);
-					DModule m = getSource(module);
-					DStackContext c = new DStackContext( module, line, m, id, stack, depth);
-					// If addFrame() returns false, that means it chose to ignore this
-					// frame, so we do NOT want to increment our depth for the next
-					// time through the loop.  If it returns true, then we do want to.
-					if (addFrame(c))
-						++depth;
-//					System.out.println("   this="+id+",@"+(bpi&0xffff)+":"+(bpi>>16)+",stack="+stack);
-				}
-				mapOldFramesToNew();
-				break;
+		}
 
+		case DMessage.InBreakAtExt: {
+			long bp = 0, wideLine = 0, wideModule = 0;
+			if (!m_wideLines) {
+				bp = msg.getDWord();
 			}
-
-			case DMessage.InFrame:
-			{
-				// For InFrame the first element is really our frame id
-				DValue frame = null;
-				DVariable child = null;
-				ArrayList<DVariable> v = new ArrayList<DVariable>();
-				ArrayList<DVariable> registers = new ArrayList<DVariable>();
-
-				int depth = (int)msg.getDWord(); // depth of frame
-
-				// make sure we have a valid depth
-				if (depth > -1)
-				{
-					// first thing is number of registers
-					int num = (int)msg.getDWord();
-					for(int i=0; i<num; i++)
-						registers.add( extractRegister(msg, i+1) );
+			else {
+				wideModule = msg.getDWord();
+				wideLine = msg.getDWord();
+			}
+			long num = msg.getDWord();
+
+			int targetIsolate = msg.getTargetIsolate();
+			// System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16));
+			/* we have stack info to store away */
+			clearFrames(targetIsolate); // just in case
+			int depth = 0;
+
+			while (num-- > 0) {
+				long bpi = 0, wideLinei= 0, wideModulei = 0;
+				if (!m_wideLines) {
+					bpi = msg.getDWord();
+				}
+				else {
+					wideModulei = msg.getDWord();
+					wideLinei = msg.getDWord();
 				}
+				long id = msg.getPtr();
+				String stack = msg.getString();
+				int module = DLocation.decodeFile(bpi);
+				int line = DLocation.decodeLine(bpi);
+				if (m_wideLines) {
+					module = (int)wideModulei;
+					line = (int)wideLinei;
+				}
+				DModule m = null;
+				m = getSource(module, targetIsolate);
+				DStackContext c = new DStackContext(module, line, m, id, stack,
+						depth, targetIsolate);
+				// If addFrame() returns false, that means it chose to ignore
+				// this
+				// frame, so we do NOT want to increment our depth for the next
+				// time through the loop. If it returns true, then we do want
+				// to.
+				if (addFrame(c, targetIsolate))
+					++depth;
+				// System.out.println("   this="+id+",@"+(bpi&0xffff)+":"+(bpi>>16)+",stack="+stack);
+			}
+			mapOldFramesToNew(targetIsolate);
+			if (targetIsolate != Isolate.DEFAULT_ID) {
+				// ask for isolate id if it is present
+				appendIsolateInfoToFrame(targetIsolate);
 
-				int currentArg = -1;
-				boolean gettingScopeChain = false;
+			}
+			break;
+
+		}
 
-				// then our frame itself
-				while(msg.getRemaining() > 0)
-				{
-					long frameId = msg.getPtr();
+		case DMessage.InFrame: {
+			// For InFrame the first element is really our frame id
+			DValue frame = null;
+			DVariable child = null;
+			ArrayList<DVariable> v = new ArrayList<DVariable>();
+			ArrayList<DVariable> registers = new ArrayList<DVariable>();
+			int targetIsolate = msg.getTargetIsolate();
+			int depth = (int) msg.getDWord(); // depth of frame
+
+			// make sure we have a valid depth
+			if (depth > -1) {
+				// first thing is number of registers
+				int num = (int) msg.getDWord();
+				for (int i = 0; i < num; i++)
+					registers.add(extractRegister(msg, i + 1));
+			}
 
-					if (frame == null)
-					{
-						frame = getOrCreateValue(frameId);
-						extractVariable(msg);  // put the rest of the info in the trash
+			int currentArg = -1;
+			boolean gettingScopeChain = false;
+
+			// then our frame itself
+			while (msg.getRemaining() > 0) {
+				long frameId = msg.getPtr();
+
+				if (frame == null) {
+					frame = getOrCreateValue(frameId, targetIsolate);
+					extractVariable(msg); // put the rest of the info in the
+											// trash
+				} else {
+					child = extractVariable(msg);
+					if (currentArg == -1
+							&& child.getName().equals(ARGUMENTS_MARKER)) {
+						currentArg = 0;
+						gettingScopeChain = false;
+					} else if (child.getName().equals(SCOPE_CHAIN_MARKER)) {
+						currentArg = -1;
+						gettingScopeChain = true;
+					} else if (currentArg >= 0) {
+						// work around a compiler bug: If the variable's name is
+						// "undefined",
+						// then change its name to "_argN", where "N" is the
+						// argument index,
+						// e.g. _arg1, _arg2, etc.
+						++currentArg;
+						if (child.getName().equals("undefined")) //$NON-NLS-1$
+							child.setName("_arg" + currentArg); //$NON-NLS-1$
 					}
-					else
-					{
-						child = extractVariable(msg);
-						if (currentArg == -1 && child.getName().equals(ARGUMENTS_MARKER))
-						{
-							currentArg = 0;
-							gettingScopeChain = false;
-						}
-						else if (child.getName().equals(SCOPE_CHAIN_MARKER))
-						{
-							currentArg = -1;
-							gettingScopeChain = true;
-						}
-						else if (currentArg >= 0)
-						{
-							// work around a compiler bug: If the variable's name is "undefined",
-							// then change its name to "_argN", where "N" is the argument index,
-							// e.g. _arg1, _arg2, etc.
-							++currentArg;
-							if (child.getName().equals("undefined")) //$NON-NLS-1$
-								child.setName("_arg" + currentArg); //$NON-NLS-1$
-						}
 
-						// All args and locals get added as "children" of
-						// the frame; but scope chain entries do not.
-						if (!gettingScopeChain)
-							addVariableMember(frameId, child);
+					// All args and locals get added as "children" of
+					// the frame; but scope chain entries do not.
+					if (!gettingScopeChain)
+						addVariableMember(frameId, child, targetIsolate);
 
-						// Everything gets added to the ordered list of
-						// variables that came in.
-						v.add(child);
-					}
+					// Everything gets added to the ordered list of
+					// variables that came in.
+					v.add(child);
 				}
+			}
 
-				// let's transfer our newly gained knowledge into the stack context
-				if (depth == 0)
-					populateRootNode(frame, v);
-				else
-					populateFrame(depth, v);
+			// let's transfer our newly gained knowledge into the stack context
+			if (depth == 0)
+				populateRootNode(frame, v, targetIsolate);
+			else
+				populateFrame(depth, v, targetIsolate);
 
-				break;
-			}
+			break;
+		}
 
-			case DMessage.InOption:
-			{
-				String s = msg.getString();
-				String v = msg.getString();
-				m_options.put(s, v);
-				break;
-			}
+		case DMessage.InOption: {
+			String s = msg.getString();
+			String v = msg.getString();
+			m_options.put(s, v);
+			break;
+		}
 
-			case DMessage.InGetVariable:
-			{
-				// For InGetVariable the first element is the original entity we requested
-				DValue parent = null;
-				DVariable child = null;
-				String definingClass = null;
-				int level = 0;
-				int highestLevelWithMembers = -1;
-				List<String> classes = new ArrayList<String>();
-
-				while(msg.getRemaining() > 0)
-				{
-					long parentId = msg.getPtr();
-
-					// build or get parent node
-					if (parent == null)
-					{
-						String name = msg.getString();
-
-						// pull the contents of the node which normally are disposed of except if we did a 0,name call
-						m_lastInGetVariable = extractVariable(msg, name);
-
-						parent = getOrCreateValue(parentId);
-					}
-					else
-					{
-						// extract the child and add it to the parent.
-						child = extractVariable(msg);
-						if (showMember(child)) {
-							if (child.isAttributeSet(VariableAttribute.IS_DYNAMIC)) {
-								// Dynamic attributes always come in marked as a member of
-								// class "Object"; but to the user, it makes more sense to
-								// consider them as members of the topmost class.
-								if (classes.size() > 0) {
-									child.setDefiningClass(0, classes.get(0));
-									highestLevelWithMembers = Math.max(highestLevelWithMembers, 0);
-								}
-							} else {
-								child.setDefiningClass(level, definingClass);
-								if (definingClass != null) {
-									highestLevelWithMembers = Math.max(highestLevelWithMembers, level);
-								}
+		case DMessage.InGetVariable: {
+			// For InGetVariable the first element is the original entity we
+			// requested
+			DValue parent = null;
+			DVariable child = null;
+			String definingClass = null;
+			int level = 0;
+			int targetIsolate = msg.getTargetIsolate();
+			int highestLevelWithMembers = -1;
+			List<String> classes = new ArrayList<String>();
+
+			while (msg.getRemaining() > 0) {
+				long parentId = msg.getPtr();
+
+				// build or get parent node
+				if (parent == null) {
+					String name = msg.getString();
+
+					// pull the contents of the node which normally are disposed
+					// of except if we did a 0,name call
+					getIsolateState(targetIsolate).m_lastInGetVariable = extractVariable(msg, name); 
+
+					parent = getOrCreateValue(parentId, targetIsolate);
+				} else {
+					// extract the child and add it to the parent.
+					child = extractVariable(msg);
+					if (showMember(child)) {
+						if (child.isAttributeSet(VariableAttribute.IS_DYNAMIC)) {
+							// Dynamic attributes always come in marked as a
+							// member of
+							// class "Object"; but to the user, it makes more
+							// sense to
+							// consider them as members of the topmost class.
+							if (classes.size() > 0) {
+								child.setDefiningClass(0, classes.get(0));
+								highestLevelWithMembers = Math.max(
+										highestLevelWithMembers, 0);
 							}
-							addVariableMember(parent.getId(), child);
 						} else {
-							if (isTraits(child)) {
-								definingClass = child.getQualifiedName();
-								level = classes.size();
-
-								// If the traits name end with "$", then it represents a class object --
-								// in other words, the variables inside it are static variables of that
-								// class.  In that case, we need to juggle the information.  For example,
-								// if we are told that a variable is a member of "MyClass$", we actually
-								// store it into the information for "MyClass".
-								if (definingClass.endsWith("$")) { //$NON-NLS-1$
-									String classWithoutDollar = definingClass.substring(0, definingClass.length() - 1);
-									int indexOfClass = classes.indexOf(classWithoutDollar);
-									if (indexOfClass != -1) {
-										level = indexOfClass;
-										definingClass = classWithoutDollar;
-									}
+							child.setDefiningClass(level, definingClass);
+							if (definingClass != null) {
+								highestLevelWithMembers = Math.max(
+										highestLevelWithMembers, level);
+							}
+						}
+						addVariableMember(parent.getId(), child, targetIsolate);
+					} else {
+						if (isTraits(child)) {
+							definingClass = child.getQualifiedName();
+							level = classes.size();
+
+							// If the traits name end with "$", then it
+							// represents a class object --
+							// in other words, the variables inside it are
+							// static variables of that
+							// class. In that case, we need to juggle the
+							// information. For example,
+							// if we are told that a variable is a member of
+							// "MyClass$", we actually
+							// store it into the information for "MyClass".
+							if (definingClass.endsWith("$")) { //$NON-NLS-1$
+								String classWithoutDollar = definingClass
+										.substring(0,
+												definingClass.length() - 1);
+								int indexOfClass = classes
+										.indexOf(classWithoutDollar);
+								if (indexOfClass != -1) {
+									level = indexOfClass;
+									definingClass = classWithoutDollar;
 								}
+							}
 
-								// It wasn't static -- so, add this class to the end of the list of classes
-								if (level == classes.size()) {
-									classes.add(definingClass);
-								}
+							// It wasn't static -- so, add this class to the end
+							// of the list of classes
+							if (level == classes.size()) {
+								classes.add(definingClass);
 							}
 						}
 					}
 				}
+			}
 
-				if (parent != null && parent.getClassHierarchy(true) == null) {
-					parent.setClassHierarchy(classes.toArray(new String[classes.size()]), highestLevelWithMembers+1);
-				}
-
-				break;
+			if (parent != null && parent.getClassHierarchy(true) == null) {
+				parent.setClassHierarchy(
+						classes.toArray(new String[classes.size()]),
+						highestLevelWithMembers + 1);
 			}
 
-			case DMessage.InWatch:		// for AS2; sends 16-bit ID field
-			case DMessage.InWatch2:		// for AS3; sends 32-bit ID field
-			{
-				// This message is sent whenever a watchpoint is added
-				// modified or removed.
-				//
-				// For an addition, flags will be non-zero and
-				// success will be true.
-				//
-				// For a modification flags  will be non-zero.
-				// and oldFlags will be non-zero and success
-				// will be true.  Additionally oldFlags will not
-				// be equal to flags.
-				//
-				// For a removal flags will be zero.  oldFlags
-				// will be non-zero.
-				//
-				// flags identifies the type of watchpoint added,
-				// see WatchKind.
-				//
-				// success indicates whether the operation was successful
-				//
-				// request.   It will be associated with the watchpoint.
-				int success = msg.getWord();
-				int oldFlags = msg.getWord();
-				int oldTag = msg.getWord();
-				int flags = msg.getWord();
-				int tag = msg.getWord();
-				// for AS2, the ID came in above as a Word.  For AS3, the above value is
-				// bogus, and it has been sent again as a DWord.
-				long id = ((type == DMessage.InWatch2) ? msg.getPtr() : msg.getWord());
-				String name = msg.getString();
-
-				if (success != 0)
-				{
-					if (flags == 0)
-					{
-						removeWatchpoint(oldTag);
-					}
-					else
-					{
-						// modification or addition is the same to us
-						// a new watch is created and added into the table
-						// while any old entry if it exists is removed.
-						removeWatchpoint(oldTag);
-						DWatch w = new DWatch(id, name, flags, tag);
-						addWatchpoint(w);
-					}
+			break;
+		}
+
+		case DMessage.InWatch: // for AS2; sends 16-bit ID field
+		case DMessage.InWatch2: // for AS3; sends 32-bit ID field
+		{
+			// This message is sent whenever a watchpoint is added
+			// modified or removed.
+			//
+			// For an addition, flags will be non-zero and
+			// success will be true.
+			//
+			// For a modification flags will be non-zero.
+			// and oldFlags will be non-zero and success
+			// will be true. Additionally oldFlags will not
+			// be equal to flags.
+			//
+			// For a removal flags will be zero. oldFlags
+			// will be non-zero.
+			//
+			// flags identifies the type of watchpoint added,
+			// see WatchKind.
+			//
+			// success indicates whether the operation was successful
+			//
+			// request. It will be associated with the watchpoint.
+			int success = msg.getWord();
+			int oldFlags = msg.getWord();
+			int oldTag = msg.getWord();
+			int flags = msg.getWord();
+			int tag = msg.getWord();
+			// for AS2, the ID came in above as a Word. For AS3, the above value
+			// is
+			// bogus, and it has been sent again as a DWord.
+			long id = ((type == DMessage.InWatch2) ? msg.getPtr() : msg
+					.getWord());
+			String name = msg.getString();
+			int targetIsolate = msg.getTargetIsolate();
+
+			if (success != 0) {
+				if (flags == 0) {
+					removeWatchpoint(oldTag, targetIsolate);
+				} else {
+					// modification or addition is the same to us
+					// a new watch is created and added into the table
+					// while any old entry if it exists is removed.
+					removeWatchpoint(oldTag, targetIsolate);
+					DWatch w = new DWatch(id, name, flags, tag, targetIsolate);
+					addWatchpoint(w, targetIsolate);
 				}
-				break;
 			}
+			break;
+		}
 
-            case DMessage.InGetSwf:
-            {
-				// we only house the swf temporarily, PlayerSession then
-				// pieces it back into swfinfo record.  Also, we don't
-				// send any extra data in the message so that we need not
-				// copy the bytes.
-				m_swf = msg.getData();
-                break;
-            }
-
-            case DMessage.InGetSwd:
-            {
-				// we only house the swd temporarily, PlayerSession then
-				// pieces it back into swfinfo record.
-				m_swd = msg.getData();
-                break;
-            }
-
-            case DMessage.InBreakReason:
-            {
-				// the id map 1-1 with out SuspendReason interface constants
-                int suspendReason = msg.getWord();
-				int suspendPlayer = msg.getWord();  // item index of player
-				int breakOffset = (int)msg.getDWord();  // current script offset
-				int prevBreakOffset = (int)msg.getDWord();  // prev script offset
-				int nextBreakOffset = (int)msg.getDWord();  // next script offset
-				m_suspendInfo = new DSuspendInfo(suspendReason, suspendPlayer, breakOffset, prevBreakOffset, nextBreakOffset);
-
-				// augment the current frame with this information.  It
-				// should work ok since we only get this message after a
-				// InBreakAtExt message
-				try
-				{
-					DStackContext c = getFrame(0);
-					c.setOffset(breakOffset);
-					c.setSwfIndex(suspendPlayer);
-				}
-				catch(Exception e)
-				{
-					if (Trace.error)
-					{
-						Trace.trace("Oh my god, gag me with a spoon...getFrame(0) call failed"); //$NON-NLS-1$
-						e.printStackTrace();
-					}
-				}
-                break;
-            }
+		case DMessage.InGetSwf: {
+			// we only house the swf temporarily, PlayerSession then
+			// pieces it back into swfinfo record. Also, we don't
+			// send any extra data in the message so that we need not
+			// copy the bytes.
+			m_swf = msg.getData();
+			break;
+		}
 
-			// obtain raw action script byte codes
-            case DMessage.InGetActions:
-            {
-				int item = msg.getWord();
-				int rsvd = msg.getWord();
-				int at = (int)msg.getDWord();
-				int len = (int)msg.getDWord();
-				int i = 0;
+		case DMessage.InGetSwd: {
+			// we only house the swd temporarily, PlayerSession then
+			// pieces it back into swfinfo record.
+			m_swd = msg.getData();
+			break;
+		}
 
-				m_actions = (len <= 0) ? null : new byte[len];
-				while(len-- > 0)
-					m_actions[i++] = (byte)msg.getByte();
+		case DMessage.InBreakReason: {
+			// the id map 1-1 with out SuspendReason interface constants
+			int suspendReason = msg.getWord();
+			int suspendPlayer = msg.getWord(); // item index of player
+			int breakOffset = (int) msg.getDWord(); // current script offset
+			int prevBreakOffset = (int) msg.getDWord(); // prev script offset
+			int nextBreakOffset = (int) msg.getDWord(); // next script offset
+			int targetIsolate = msg.getTargetIsolate();
+
+			getIsolateState(targetIsolate).m_suspendInfo = new DSuspendInfo(
+					suspendReason, suspendPlayer, breakOffset,
+					prevBreakOffset, nextBreakOffset);
+
+			// augment the current frame with this information. It
+			// should work ok since we only get this message after a
+			// InBreakAtExt message
+			try {
+				DSt

<TRUNCATED>

Mime
View raw message