diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 523bcf31c8bf06bcf6e9ec773205eaf0bdc33f4c..168b660478828c6c49b9c9682efaa60eb4e6d085 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -3613,7 +3613,6 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
     data.iname = "local." + name;
     data.name = nam;
     data.exp = name;
-    data.framekey = m_currentFrame + data.name;
     setWatchDataType(data, item.findChild("type"));
     if (uninitializedVariables.contains(data.name)) {
         data.setError(WatchData::msgNotInScope());
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 3a03e0da8d069808d7a2603dfbec1c4b67cb70e4..44024385c66ea4f2c054d2a067cda1e02c1215b1 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -90,7 +90,7 @@ QDataStream& operator>>(QDataStream& s, WatchData &data)
     QString value;
     QString type;
     bool hasChildren;
-    s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId;
+    s >> data.exp >> data.name >> value >> type >> hasChildren >> data.id;
     data.setType(type.toUtf8(), false);
     data.setValue(value);
     data.setHasChildren(hasChildren);
@@ -535,7 +535,7 @@ void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal:
 
     if (!data.name.isEmpty() && data.isChildrenNeeded()
             && watchHandler()->isExpandedIName(data.iname))
-        expandObject(data.iname, data.objectId);
+        expandObject(data.iname, data.id);
 
     {
         QByteArray reply;
@@ -630,7 +630,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
 
             if (watchHandler()->expandedINames().contains(data.iname)) {
                 needPing = true;
-                expandObject(data.iname, data.objectId);
+                expandObject(data.iname, data.id);
             }
         }
 
@@ -640,7 +640,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
 
             if (watchHandler()->expandedINames().contains(data.iname)) {
                 needPing = true;
-                expandObject(data.iname, data.objectId);
+                expandObject(data.iname, data.id);
             }
         }
 
@@ -710,7 +710,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
 
             if (watchHandler()->expandedINames().contains(data.iname)) {
                 needPing = true;
-                expandObject(data.iname, data.objectId);
+                expandObject(data.iname, data.id);
             }
         }
         if (needPing)
@@ -726,7 +726,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
             watchHandler()->insertData(data);
             if (watchHandler()->expandedINames().contains(data.iname)) {
                 needPing = true;
-                expandObject(data.iname, data.objectId);
+                expandObject(data.iname, data.id);
             }
         }
         if (needPing)
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index 9fb2e337a25d4e657d1a96251064b2668bb1d3ee..09ac194e3d0e9c1a885260500c859cb64fda0e09 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -702,9 +702,11 @@ void ScriptEngine::updateLocals()
     m_scriptEngine->setAgent(0);
 
     WatchData data;
+    data.id = m_watchIdCounter++;
+    m_watchIdToScriptValue.insert(data.id, context->activationObject());
     data.iname = "local";
     data.name = _(data.iname);
-    data.scriptValue = context->activationObject();
+
     watchHandler()->beginCycle();
     updateSubItem(data);
     watchHandler()->endCycle();
@@ -744,8 +746,8 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
     //SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString());
     QTC_ASSERT(data.isValid(), return);
 
+    const QScriptValue &ob = m_watchIdToScriptValue.value(data.id);
     if (data.isTypeNeeded() || data.isValueNeeded()) {
-        const QScriptValue &ob = data.scriptValue;
         if (ob.isArray()) {
             data.setType("Array", false);
             data.setValue(QString(QLatin1Char(' ')));
@@ -802,14 +804,15 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
     }
 
     if (data.isChildrenNeeded()) {
-        QScriptValueIterator it(data.scriptValue);
+        QScriptValueIterator it(ob);
         while (it.hasNext()) {
             it.next();
             WatchData data1;
             data1.iname = data.iname + '.' + it.name().toLatin1();
             data1.exp = it.name().toLatin1();
             data1.name = it.name();
-            data1.scriptValue = it.value();
+            data.id = m_watchIdCounter++;
+            m_watchIdToScriptValue.insert(data.id, it.value());
             if (watchHandler()->isExpandedIName(data1.iname)) {
                 data1.setChildrenNeeded();
             } else {
@@ -822,7 +825,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
     }
 
     if (data.isHasChildrenNeeded()) {
-        QScriptValueIterator it(data.scriptValue);
+        QScriptValueIterator it(ob);
         data.setHasChildren(it.hasNext());
     }
 
diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h
index bd615eeea4eaea2e66943b8228d5aed86314bb83..82b6894fa78e1e0219f50ce6fa138ecf6dba2c73 100644
--- a/src/plugins/debugger/script/scriptengine.h
+++ b/src/plugins/debugger/script/scriptengine.h
@@ -34,6 +34,7 @@
 
 #include <QtCore/QSharedPointer>
 #include <QtCore/QScopedPointer>
+#include <QtCore/QHash>
 
 QT_BEGIN_NAMESPACE
 class QScriptEngine;
@@ -114,6 +115,8 @@ private:
     QString m_scriptContents;
     QString m_scriptFileName;
     QScopedPointer<ScriptAgent> m_scriptAgent;
+    QHash<quint64,QScriptValue> m_watchIdToScriptValue;
+    quint64 m_watchIdCounter;
 
     bool m_stopped;
     bool m_stopOnNextLine;
diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp
index b21d1609f6a460c6c05856852d41f433f20127d4..880ed4fb5268e84d7b6d1abd261b323963545941 100644
--- a/src/plugins/debugger/watchdata.cpp
+++ b/src/plugins/debugger/watchdata.cpp
@@ -1,12 +1,10 @@
 
 #include "watchdata.h"
-#include "watchutils.h"
 
 #include <QtCore/QTextStream>
 #include <QtCore/QDebug>
 
-#include <QtGui/QApplication>
-#include <QtGui/QTextDocument> // Qt::escape
+#include <QtCore/QCoreApplication>
 
 ////////////////////////////////////////////////////////////////////
 //
@@ -17,19 +15,107 @@
 namespace Debugger {
 namespace Internal {
 
+enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
+static QString qt_escape(const QString& plain)
+{
+    QString rich;
+    rich.reserve(int(plain.length() * 1.1));
+    for (int i = 0; i < plain.length(); ++i) {
+        if (plain.at(i) == QLatin1Char('<'))
+            rich += QLatin1String("&lt;");
+        else if (plain.at(i) == QLatin1Char('>'))
+            rich += QLatin1String("&gt;");
+        else if (plain.at(i) == QLatin1Char('&'))
+            rich += QLatin1String("&amp;");
+        else if (plain.at(i) == QLatin1Char('"'))
+            rich += QLatin1String("&quot;");
+        else
+            rich += plain.at(i);
+    }
+    return rich;
+}
+
+bool isPointerType(const QByteArray &type)
+{
+    return type.endsWith('*') || type.endsWith("* const");
+}
+
+bool isCharPointerType(const QByteArray &type)
+{
+    return type == "char *" || type == "const char *" || type == "char const *";
+}
+
+bool isIntType(const QByteArray &type)
+{
+    if (type.isEmpty())
+        return false;
+    switch (type.at(0)) {
+        case 'b':
+            return type == "bool";
+        case 'c':
+            return type == "char";
+        case 'i':
+            return type == "int" || type == "int64";
+        case 'l':
+            return type == "long"
+                || type == "long long";
+        case 'p':
+            return type == "ptrdiff_t";
+        case 'q':
+            return type == "qint16" || type == "quint16"
+                || type == "qint32" || type == "quint32"
+                || type == "qint64" || type == "quint64";
+        case 's':
+            return type == "short"
+                || type == "signed"
+                || type == "size_t"
+                || type == "std::size_t"
+                || type == "std::ptrdiff_t"
+                || type.startsWith("signed ");
+        case 'u':
+            return type == "unsigned"
+                || type.startsWith("unsigned ");
+        default:
+            return false;
+    }
+}
+
+bool isFloatType(const QByteArray &type)
+{
+   return type == "float" || type == "double" || type == "qreal";
+}
+
+bool isIntOrFloatType(const QByteArray &type)
+{
+    return isIntType(type) || isFloatType(type);
+}
+
+GuessChildrenResult guessChildren(const QByteArray &type)
+{
+    if (isIntOrFloatType(type))
+        return HasNoChildren;
+    if (isCharPointerType(type))
+        return HasNoChildren;
+    if (isPointerType(type))
+        return HasChildren;
+    if (type.endsWith("QString"))
+        return HasNoChildren;
+    return HasPossiblyChildren;
+}
+
 WatchData::WatchData() :
+    id(0),
+    state(InitialState),
     editformat(0),
     address(0),
-    hasChildren(false),
     generation(-1),
+    hasChildren(false),
     valueEnabled(true),
     valueEditable(true),
     error(false),
-    source(0),
-    objectId(0),
-    state(InitialState),
     changed(false),
-    sortId(0)
+    sortId(0),
+    source(0)
 {
 }
 
@@ -45,7 +131,6 @@ bool WatchData::isEqual(const WatchData &other) const
       && displayedType == other.displayedType
       && variable == other.variable
       && address == other.address
-      && framekey == other.framekey
       && hasChildren == other.hasChildren
       && valueEnabled == other.valueEnabled
       && valueEditable == other.valueEditable
@@ -213,8 +298,6 @@ QString WatchData::toString() const
 
     if (isChildrenNeeded())
         str << "children=<needed>,";
-    if (source)
-        str << "source=" << source;
     str.flush();
     if (res.endsWith(QLatin1Char(',')))
         res.truncate(res.size() - 1);
@@ -226,7 +309,7 @@ static void formatToolTipRow(QTextStream &str,
     const QString &category, const QString &value)
 {
     str << "<tr><td>" << category << "</td><td> : </td><td>"
-        << Qt::escape(value) << "</td></tr>";
+        << qt_escape(value) << "</td></tr>";
 }
 
 static QString typeToolTip(const WatchData &wd)
@@ -247,19 +330,19 @@ QString WatchData::toToolTip() const
     QString res;
     QTextStream str(&res);
     str << "<html><body><table>";
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Name"), name);
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Expression"), exp);
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Type"), typeToolTip(*this));
+    formatToolTipRow(str, tr("Name"), name);
+    formatToolTipRow(str, tr("Expression"), exp);
+    formatToolTipRow(str, tr("Type"), typeToolTip(*this));
     QString val = value;
     if (value.size() > 1000) {
         val.truncate(1000);
-        val += QCoreApplication::translate("Debugger::Internal::WatchHandler", " ... <cut off>");
+        val += tr(" ... <cut off>");
     }
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Value"), val);
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Object Address"),
+    formatToolTipRow(str, tr("Value"), val);
+    formatToolTipRow(str, tr("Object Address"),
                      QString::fromAscii(hexAddress()));
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Internal ID"), iname);
-    formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Generation"),
+    formatToolTipRow(str, tr("Internal ID"), iname);
+    formatToolTipRow(str, tr("Generation"),
         QString::number(generation));
     str << "</table></body></html>";
     return res;
diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h
index f36fce1fe6502227234279e8d6ed3b27a49ed643..370ef897abb58c928bc59c21e9ead818140ec70e 100644
--- a/src/plugins/debugger/watchdata.h
+++ b/src/plugins/debugger/watchdata.h
@@ -33,6 +33,7 @@
 #include <QtCore/QMetaType>
 #include <QtCore/QtGlobal>
 #include <QtCore/QObject>
+#include <QtCore/QCoreApplication>
 #include <QtScript/QScriptValue>
 
 namespace Debugger {
@@ -45,11 +46,11 @@ public:
 
     enum State
     {
-        Complete = 0,
+        Complete          = 0,
         HasChildrenNeeded = 1,
-        ValueNeeded = 2,
-        TypeNeeded = 4,
-        ChildrenNeeded = 8,
+        ValueNeeded       = 2,
+        TypeNeeded        = 4,
+        ChildrenNeeded    = 8,
 
         NeededMask = ValueNeeded
             | TypeNeeded
@@ -62,81 +63,84 @@ public:
             | HasChildrenNeeded
     };
 
-    void setValue(const QString &);
-    void setType(const QByteArray &, bool guessChildrenFromType = true);
-    void setValueToolTip(const QString &);
-    void setError(const QString &);
-    void setAddress(const quint64 &);
-    void setHexAddress(const QByteArray &a);
-
     bool isSomethingNeeded() const { return state & NeededMask; }
-    void setAllNeeded() { state = NeededMask; }
-    void setAllUnneeded() { state = State(0); }
+    void setAllNeeded()            { state = NeededMask; }
+    void setAllUnneeded()          { state = State(0); }
 
     bool isTypeNeeded() const { return state & TypeNeeded; }
-    bool isTypeKnown() const { return !(state & TypeNeeded); }
-    void setTypeNeeded() { state = State(state | TypeNeeded); }
-    void setTypeUnneeded() { state = State(state & ~TypeNeeded); }
+    bool isTypeKnown()  const { return !(state & TypeNeeded); }
+    void setTypeNeeded()      { state = State(state | TypeNeeded); }
+    void setTypeUnneeded()    { state = State(state & ~TypeNeeded); }
 
     bool isValueNeeded() const { return state & ValueNeeded; }
-    bool isValueKnown() const { return !(state & ValueNeeded); }
-    void setValueNeeded() { state = State(state | ValueNeeded); }
-    void setValueUnneeded() { state = State(state & ~ValueNeeded); }
+    bool isValueKnown()  const { return !(state & ValueNeeded); }
+    void setValueNeeded()      { state = State(state | ValueNeeded); }
+    void setValueUnneeded()    { state = State(state & ~ValueNeeded); }
 
     bool isChildrenNeeded() const { return state & ChildrenNeeded; }
-    bool isChildrenKnown() const { return !(state & ChildrenNeeded); }
-    void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
+    bool isChildrenKnown()  const { return !(state & ChildrenNeeded); }
+    void setChildrenNeeded()   { state = State(state | ChildrenNeeded); }
     void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); }
 
     bool isHasChildrenNeeded() const { return state & HasChildrenNeeded; }
-    bool isHasChildrenKnown() const { return !(state & HasChildrenNeeded); }
-    void setHasChildrenNeeded() { state = State(state | HasChildrenNeeded); }
+    bool isHasChildrenKnown()  const { return !(state & HasChildrenNeeded); }
+    void setHasChildrenNeeded()   { state = State(state | HasChildrenNeeded); }
     void setHasChildrenUnneeded() { state = State(state & ~HasChildrenNeeded); }
-    void setHasChildren(bool c) { hasChildren = c; setHasChildrenUnneeded();
-        if (!c) setChildrenUnneeded(); }
+    void setHasChildren(bool c)   { hasChildren = c; setHasChildrenUnneeded();
+                                         if (!c) setChildrenUnneeded(); }
 
-    QString toString() const;
-    QString toToolTip() const;
-    bool isLocal() const { return iname.startsWith("local."); }
+    bool isLocal()   const { return iname.startsWith("local."); }
     bool isWatcher() const { return iname.startsWith("watch."); }
-    bool isValid() const { return !iname.isEmpty(); }
+    bool isValid()   const { return !iname.isEmpty(); }
 
     bool isEqual(const WatchData &other) const;
-    quint64 coreAddress() const;
-    QByteArray hexAddress() const;
+
+    void setError(const QString &);
+    void setValue(const QString &);
+    void setValueToolTip(const QString &);
+    void setType(const QByteArray &, bool guessChildrenFromType = true);
+    void setAddress(const quint64 &);
+    void setHexAddress(const QByteArray &a);
+
+    QString toString()  const;
+    QString toToolTip() const;
 
     static QString msgNotInScope();
     static QString shadowedName(const QString &name, int seen);
     static const QString &shadowedNameFormat();
 
+    quint64    coreAddress() const;
+    QByteArray hexAddress()  const;
+
 public:
-    QByteArray iname;     // Internal name sth like 'local.baz.public.a'
-    QByteArray exp;       // The expression
-    QString name;         // Displayed name
-    QString value;        // Displayed value
-    QByteArray editvalue; // Displayed value
-    int editformat;       // Format of displayed value
-    QString valuetooltip; // Tooltip in value column
-    QString typeFormats;  // Selection of formats of displayed value
+    quint64    id;           // Token for the engine for internal mapping
+    qint32     state;        // 'needed' flags;
+    QByteArray iname;        // Internal name sth like 'local.baz.public.a'
+    QByteArray exp;          // The expression
+    QString    name;         // Displayed name
+    QString    value;        // Displayed value
+    QByteArray editvalue;    // Displayed value
+    qint32     editformat;   // Format of displayed value
+    QString    valuetooltip; // Tooltip in value column
+    QString    typeFormats;  // Selection of formats of displayed value
     QByteArray type;         // Type for further processing
-    QString displayedType;// Displayed type (optional)
-    QByteArray variable;  // Name of internal Gdb variable if created
-    quint64 address;      // Displayed address
-    QString framekey;     // Key for type cache
-    QScriptValue scriptValue; // If needed...
+    QString    displayedType;// Displayed type (optional)
+    quint64    address;      // Displayed address
+    qint32     generation;   // When updated?
     bool hasChildren;
-    int generation;       // When updated?
-    bool valueEnabled;    // Value will be greyed out or not
-    bool valueEditable;   // Value will be editable
+    bool valueEnabled;       // Value will be greyed out or not
+    bool valueEditable;      // Value will be editable
     bool error;
+    bool changed;
+    qint32 sortId;
     QByteArray dumperFlags;
 
+    Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::WatchHandler)
+
 public:
-    int source;  // Originated from dumper or symbol evaluation? (CDB only)
-    quint64 objectId; // Object id used for the QMLEngine
-    int state;
-    bool changed;
-    int sortId;
+    // FIXME: this is engine specific data that should be mapped internally
+    QByteArray variable;  // Name of internal Gdb variable if created
+    qint32 source;  // Originated from dumper or symbol evaluation? (CDB only)
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index dd0a1dff049cb22b540d3f4b610654a627a63bea..7c02512cb9571dd96258a5e223503c3c5fff17fe 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -273,16 +273,6 @@ bool isKeyWord(const QString &exp)
         || exp == QLatin1String("while");
 }
 
-bool isPointerType(const QByteArray &type)
-{
-    return type.endsWith('*') || type.endsWith("* const");
-}
-
-bool isCharPointerType(const QByteArray &type)
-{
-    return type == "char *" || type == "const char *" || type == "char const *";
-}
-
 bool startsWithDigit(const QString &str)
 {
     return !str.isEmpty() && str.at(0).isDigit();
@@ -540,69 +530,11 @@ QString extractTypeFromPTypeOutput(const QString &str)
     return res.simplified();
 }
 
-bool isIntType(const QByteArray &type)
-{
-    if (type.isEmpty())
-        return false;
-    switch (type.at(0)) {
-        case 'b':
-            return type == "bool";
-        case 'c':
-            return type == "char";
-        case 'i':
-            return type == "int" || type == "int64";
-        case 'l':
-            return type == "long"
-                || type == "long long";
-        case 'p':
-            return type == "ptrdiff_t";
-        case 'q':
-            return type == "qint16" || type == "quint16"
-                || type == "qint32" || type == "quint32"
-                || type == "qint64" || type == "quint64";
-        case 's':
-            return type == "short"
-                || type == "signed"
-                || type == "size_t"
-                || type == "std::size_t"
-                || type == "std::ptrdiff_t"
-                || type.startsWith("signed ");
-        case 'u':
-            return type == "unsigned"
-                || type.startsWith("unsigned ");
-        default:
-            return false;
-    }
-}
-
 bool isSymbianIntType(const QByteArray &type)
 {
     return type == "TInt" || type == "TBool";
 }
 
-bool isFloatType(const QByteArray &type)
-{
-   return type == "float" || type == "double" || type == "qreal";
-}
-
-bool isIntOrFloatType(const QByteArray &type)
-{
-    return isIntType(type) || isFloatType(type);
-}
-
-GuessChildrenResult guessChildren(const QByteArray &type)
-{
-    if (isIntOrFloatType(type))
-        return HasNoChildren;
-    if (isCharPointerType(type))
-        return HasNoChildren;
-    if (isPointerType(type))
-        return HasChildren;
-    if (type.endsWith("QString"))
-        return HasNoChildren;
-    return HasPossiblyChildren;
-}
-
 QByteArray sizeofTypeExpression(const QByteArray &type, QtDumperHelper::Debugger debugger)
 {
     if (type.endsWith('*'))