diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 7a1f7e3bf0405e7bac2467ee24acc196697ac838..147852fe3251bdc3f8f2737880ee84eba14e2c2d 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -157,10 +157,9 @@ public:
 Check::Check(Document::Ptr doc, const Snapshot &snapshot, const QStringList &importPaths)
     : _doc(doc)
     , _snapshot(snapshot)
-    , _context(&_engine)
     , _link(&_context, doc, snapshot, importPaths)
     , _scopeBuilder(doc, &_context)
-    , _ignoreTypeErrors(_context.documentImportsPlugins(_doc.data()))
+    , _ignoreTypeErrors(false)
 {
 }
 
diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h
index a6fddba361fd2d1211b98455cf73be5ead36a943..918d62fd588dec5f3b436c779e0f162e1d7efed1 100644
--- a/src/libs/qmljs/qmljscheck.h
+++ b/src/libs/qmljs/qmljscheck.h
@@ -71,7 +71,6 @@ private:
     Document::Ptr _doc;
     Snapshot _snapshot;
 
-    Interpreter::Engine _engine;
     Interpreter::Context _context;
     Link _link;
     ScopeBuilder _scopeBuilder;
diff --git a/src/libs/qmljs/qmljsicontextpane.h b/src/libs/qmljs/qmljsicontextpane.h
index ccb176ad261200e47cbf02a9971fa2f8ed31873c..759af9a2f52f2bb086fbb36ee96f00fa9213f268 100644
--- a/src/libs/qmljs/qmljsicontextpane.h
+++ b/src/libs/qmljs/qmljsicontextpane.h
@@ -33,7 +33,7 @@
 #include <QObject>
 #include "qmljs_global.h"
 #include <qmljs/parser/qmljsastfwd_p.h>
-#include <qmljs/qmljsdocument.h>
+#include <qmljs/qmljslookupcontext.h>
 
 
 namespace TextEditor {
@@ -52,9 +52,9 @@ class QMLJS_EXPORT IContextPane : public QObject
 public:
     IContextPane(QObject *parent = 0) : QObject(parent) {}
     virtual ~IContextPane() {}
-    virtual void apply(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node, bool update, bool force = false) = 0;
+    virtual void apply(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node, bool update, bool force = false) = 0;
     virtual void setEnabled(bool) = 0;
-    virtual bool isAvailable(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node) = 0;
+    virtual bool isAvailable(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node) = 0;
     virtual QWidget* widget() = 0;
 signals:
     void closed();
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 61770b747936a6e27afa2cab8c8c966c929a8029..e47e4c1fadb03d42c607b69b01a559dbd218de17 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -1419,8 +1419,8 @@ QList<const ObjectValue *> ScopeChain::all() const
 }
 
 
-Context::Context(Engine *engine)
-    : _engine(engine),
+Context::Context()
+    : _engine(new Engine),
       _qmlScopeObjectIndex(-1),
       _qmlScopeObjectSet(false)
 {
@@ -1430,9 +1430,10 @@ Context::~Context()
 {
 }
 
+// the engine is only guaranteed to live as long as the context
 Engine *Context::engine() const
 {
-    return _engine;
+    return _engine.data();
 }
 
 const ScopeChain &Context::scopeChain() const
@@ -1530,7 +1531,7 @@ void Context::setProperty(const ObjectValue *object, const QString &name, const
     _properties[object].insert(name, value);
 }
 
-QString Context::defaultPropertyName(const ObjectValue *object)
+QString Context::defaultPropertyName(const ObjectValue *object) const
 {
     for (const ObjectValue *o = object; o; o = o->prototype(this)) {
         if (const ASTObjectValue *astObjValue = dynamic_cast<const ASTObjectValue *>(o)) {
@@ -1544,16 +1545,6 @@ QString Context::defaultPropertyName(const ObjectValue *object)
     return QString();
 }
 
-bool Context::documentImportsPlugins(const QmlJS::Document *doc) const
-{
-    return _documentsImportingPlugins.contains(doc->fileName());
-}
-
-void Context::setDocumentImportsPlugins(const QmlJS::Document *doc)
-{
-    _documentsImportingPlugins.insert(doc->fileName());
-}
-
 Reference::Reference(Engine *engine)
     : _engine(engine)
 {
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 201b89cb009badeca1b70b9553ddd149d2758707..5ec91c009d5a48d8dc23452e1a4318e7fa90d32a 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -271,7 +271,7 @@ private:
 class QMLJS_EXPORT Context
 {
 public:
-    Context(Engine *engine);
+    Context();
     ~Context();
 
     Engine *engine() const;
@@ -289,18 +289,14 @@ public:
     const Value *property(const ObjectValue *object, const QString &name) const;
     void setProperty(const ObjectValue *object, const QString &name, const Value *value);
 
-    QString defaultPropertyName(const ObjectValue *object);
-
-    bool documentImportsPlugins(const Document *doc) const;
-    void setDocumentImportsPlugins(const Document *doc);
+    QString defaultPropertyName(const ObjectValue *object) const;
 
 private:
     typedef QHash<QString, const Value *> Properties;
 
-    Engine *_engine;
+    QSharedPointer<Engine> _engine;
     QHash<const ObjectValue *, Properties> _properties;
     QHash<QString, const ObjectValue *> _typeEnvironments;
-    QSet<QString> _documentsImportingPlugins;
     ScopeChain _scopeChain;
     int _qmlScopeObjectIndex;
     bool _qmlScopeObjectSet;
@@ -628,8 +624,7 @@ protected:
 
 class QMLJS_EXPORT Engine
 {
-    Engine(const Engine &other);
-    void operator = (const Engine &other);
+    Q_DISABLE_COPY(Engine)
 
 public:
     Engine();
diff --git a/src/libs/qmljs/qmljslookupcontext.cpp b/src/libs/qmljs/qmljslookupcontext.cpp
index 30fafb7f17ff2e8480901f760ef09d417455be0f..d943948107675aec392c967ba3db27ae66600eca 100644
--- a/src/libs/qmljs/qmljslookupcontext.cpp
+++ b/src/libs/qmljs/qmljslookupcontext.cpp
@@ -40,20 +40,30 @@ class QmlJS::LookupContextData
 {
 public:
     LookupContextData(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
-        : context(&interp),
+        : doc(doc),
+          snapshot(snapshot)
+    {
+        // since we keep the document and snapshot around, we don't need to keep the Link instance
+        Link link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths());
+
+        ScopeBuilder scopeBuilder(doc, &context);
+        scopeBuilder.push(path);
+    }
+
+    LookupContextData(Document::Ptr doc, const Snapshot &snapshot,
+                      const Interpreter::Context &linkedContextWithoutScope,
+                      const QList<AST::Node *> &path)
+        : context(linkedContextWithoutScope),
           doc(doc),
-          snapshot(snapshot),
-          link(&context, doc, snapshot, ModelManagerInterface::instance()->importPaths())
+          snapshot(snapshot)
     {
         ScopeBuilder scopeBuilder(doc, &context);
         scopeBuilder.push(path);
     }
 
-    Interpreter::Engine interp;
     Interpreter::Context context;
     Document::Ptr doc;
     Snapshot snapshot;
-    Link link;
 };
 
 LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path)
@@ -61,6 +71,13 @@ LookupContext::LookupContext(Document::Ptr doc, const Snapshot &snapshot, const
 {
 }
 
+LookupContext::LookupContext(const Document::Ptr doc, const Snapshot &snapshot,
+                             const Interpreter::Context &linkedContextWithoutScope,
+                             const QList<AST::Node *> &path)
+    : d(new LookupContextData(doc, snapshot, linkedContextWithoutScope, path))
+{
+}
+
 LookupContext::~LookupContext()
 {
 }
@@ -71,17 +88,37 @@ LookupContext::Ptr LookupContext::create(Document::Ptr doc, const Snapshot &snap
     return ptr;
 }
 
+LookupContext::Ptr LookupContext::create(const Document::Ptr doc, const Snapshot &snapshot,
+                                         const Interpreter::Context &linkedContextWithoutScope,
+                                         const QList<AST::Node *> &path)
+{
+    Ptr ptr(new LookupContext(doc, snapshot, linkedContextWithoutScope, path));
+    return ptr;
+}
+
 const Interpreter::Value *LookupContext::evaluate(AST::Node *node) const
 {
     Evaluate check(&d->context);
     return check(node);
 }
 
+Document::Ptr LookupContext::document() const
+{
+    return d->doc;
+}
+
+Snapshot LookupContext::snapshot() const
+{
+    return d->snapshot;
+}
+
+// the engine is only guaranteed to live as long as the LookupContext
 Interpreter::Engine *LookupContext::engine() const
 {
-    return &d->interp;
+    return d->context.engine();
 }
 
+// the context is only guaranteed to live as long as the LookupContext
 const Interpreter::Context *LookupContext::context() const
 {
     return &d->context;
diff --git a/src/libs/qmljs/qmljslookupcontext.h b/src/libs/qmljs/qmljslookupcontext.h
index ca93b43aa9ac35dfc8dbb74697c7881f7df3712f..b4736c7abc76269b74baff8498e2cfdc7e3f0d82 100644
--- a/src/libs/qmljs/qmljslookupcontext.h
+++ b/src/libs/qmljs/qmljslookupcontext.h
@@ -31,6 +31,7 @@
 #define QMLJSLOOKUPCONTEXT_H
 
 #include "qmljsdocument.h"
+#include "qmljsinterpreter.h"
 #include "parser/qmljsastfwd_p.h"
 
 #include <QtCore/QSharedPointer>
@@ -42,23 +43,34 @@ class LookupContextData;
 
 namespace Interpreter {
 class Value;
-class Engine;
 class Context;
 }
 
 class QMLJS_EXPORT LookupContext
 {
+    Q_DISABLE_COPY(LookupContext)
+
     LookupContext(const Document::Ptr doc, const Snapshot &snapshot, const QList<AST::Node *> &path);
+    LookupContext(const Document::Ptr doc, const Snapshot &snapshot,
+                  const Interpreter::Context &linkedContextWithoutScope,
+                  const QList<AST::Node *> &path);
 
 public:
     ~LookupContext();
 
     typedef QSharedPointer<LookupContext> Ptr;
 
+    // consider using SemanticInfo::lookupContext instead, it's faster
+    static Ptr create(const Document::Ptr doc, const Snapshot &snapshot,
+                      const QList<AST::Node *> &path);
     static Ptr create(const Document::Ptr doc, const Snapshot &snapshot,
+                      const Interpreter::Context &linkedContextWithoutScope,
                       const QList<AST::Node *> &path);
 
     const Interpreter::Value *evaluate(AST::Node *node) const;
+
+    Document::Ptr document() const;
+    Snapshot snapshot() const;
     Interpreter::Engine *engine() const;
     const Interpreter::Context *context() const;
 
diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
index af5b789c83832a38b4f62a5eb4a9362ce84ed4ac..97184c979250eb80014ec59a693490fe11db3b6d 100644
--- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
@@ -187,15 +187,14 @@ public:
                    const QStringList importPaths)
         : m_snapshot(snapshot)
         , m_doc(doc)
-        , m_engine(new Interpreter::Engine)
-        , m_context(new Interpreter::Context(m_engine))
+        , m_context(new Interpreter::Context)
         , m_link(m_context, doc, snapshot, importPaths)
         , m_scopeBuilder(doc, m_context)
     {
     }
 
     ~ReadingContext()
-    { delete m_context; delete m_engine; }
+    { delete m_context; }
 
     Document::Ptr doc() const
     { return m_doc; }
@@ -328,11 +327,11 @@ public:
         if (!value)
             return false;
         const Interpreter::ObjectValue *objectValue = value->asObjectValue();
-        if (objectValue && objectValue->prototype(m_context) == m_engine->arrayPrototype())
+        if (objectValue && objectValue->prototype(m_context) == m_context->engine()->arrayPrototype())
             return true;
 
         for (const Interpreter::ObjectValue *iter = containingObject; iter; iter = iter->prototype(m_context)) {
-            if (iter->property(name, m_context) == m_engine->arrayPrototype())
+            if (iter->property(name, m_context) == m_context->engine()->arrayPrototype())
                 return true;
             if (const Interpreter::QmlObjectValue *qmlIter = dynamic_cast<const Interpreter::QmlObjectValue *>(iter)) {
                 if (qmlIter->isListProperty(name))
@@ -451,7 +450,6 @@ public:
 private:
     Snapshot m_snapshot;
     Document::Ptr m_doc;
-    Interpreter::Engine *m_engine;
     Interpreter::Context *m_context;
     Link m_link;
     ScopeBuilder m_scopeBuilder;
diff --git a/src/plugins/qmljseditor/qmljscodecompletion.cpp b/src/plugins/qmljseditor/qmljscodecompletion.cpp
index d2222860a9ee3a451df9745f1f0e20ef53923fe4..c85d3e44b3fb5d2d3b03569109358f8c562704ee 100644
--- a/src/plugins/qmljseditor/qmljscodecompletion.cpp
+++ b/src/plugins/qmljseditor/qmljscodecompletion.cpp
@@ -691,7 +691,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
     const QIcon keywordIcon = iconForColor(Qt::darkYellow);
 
     const QList<AST::Node *> path = semanticInfo.astPath(editor->position());
-    LookupContext::Ptr lookupContext = LookupContext::create(document, snapshot, path);
+    LookupContext::Ptr lookupContext = semanticInfo.lookupContext(path);
     const Interpreter::Context *context = lookupContext->context();
 
     // Search for the operator that triggered the completion.
diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp
index 605b459e620f06da1a8bb083b3661fc6b0a3a9df..c2cb5610d5568e2dbd2a07dd9e090a9862969641 100644
--- a/src/plugins/qmljseditor/qmljseditor.cpp
+++ b/src/plugins/qmljseditor/qmljseditor.cpp
@@ -40,6 +40,7 @@
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljsicontextpane.h>
 #include <qmljs/qmljslookupcontext.h>
+#include <qmljs/qmljslink.h>
 #include <qmljs/parser/qmljsastvisitor_p.h>
 #include <qmljs/parser/qmljsast_p.h>
 #include <qmljs/parser/qmljsengine_p.h>
@@ -553,6 +554,18 @@ QList<AST::Node *> SemanticInfo::astPath(int cursorPosition) const
     return path;
 }
 
+LookupContext::Ptr SemanticInfo::lookupContext(const QList<QmlJS::AST::Node *> &path) const
+{
+    // create and link context if necessary
+    if (!m_context) {
+        Interpreter::Context *ctx = new Interpreter::Context;
+        Link link(ctx, document, snapshot, ModelManagerInterface::instance()->importPaths());
+        m_context = QSharedPointer<const QmlJS::Interpreter::Context>(ctx);
+    }
+
+    return LookupContext::create(document, snapshot, *m_context, path);
+}
+
 static bool importContainsCursor(UiImport *importAst, unsigned cursorPosition)
 {
     return cursorPosition >= importAst->firstSourceLocation().begin()
@@ -962,9 +975,9 @@ void QmlJSTextEditor::updateCursorPositionNow()
         Node *oldNode = m_semanticInfo.declaringMemberNoProperties(m_oldCursorPosition);
         Node *newNode = m_semanticInfo.declaringMemberNoProperties(position());
         if (oldNode != newNode && m_oldCursorPosition != -1)
-            m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode, false);
+            m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, false);
         if (oldNode != newNode &&
-            m_contextPane->isAvailable(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode) &&
+            m_contextPane->isAvailable(editableInterface(), m_semanticInfo.lookupContext(), newNode) &&
             !m_contextPane->widget()->isVisible()) {
             QList<TextEditor::Internal::RefactorMarker> markers;
             if (UiObjectMember *m = newNode->uiObjectMemberCast()) {
@@ -1042,22 +1055,19 @@ class SelectedElement: protected Visitor
     unsigned m_cursorPositionStart;
     unsigned m_cursorPositionEnd;
     QList<UiObjectMember *> m_selectedMembers;
-    Document::Ptr m_document;
-    Snapshot m_snapshot;
     LookupContext::Ptr m_lookupContext;
 
 public:
     SelectedElement()
         : m_cursorPositionStart(0), m_cursorPositionEnd(0) {}
 
-    QList<UiObjectMember *> operator()(Document::Ptr doc, Snapshot snapshot, unsigned startPosition, unsigned endPosition)
+    QList<UiObjectMember *> operator()(LookupContext::Ptr lookupContext, unsigned startPosition, unsigned endPosition)
     {
-        m_document = doc;
-        m_snapshot = snapshot;
+        m_lookupContext = lookupContext;
         m_cursorPositionStart = startPosition;
         m_cursorPositionEnd = endPosition;
         m_selectedMembers.clear();
-        Node::accept(doc->qmlProgram(), this);
+        Node::accept(lookupContext->document()->qmlProgram(), this);
         return m_selectedMembers;
     }
 
@@ -1092,14 +1102,10 @@ protected:
 
     inline bool hasVisualPresentation(Node *ast)
     {
-        Bind *bind = m_document->bind();
+        Bind *bind = m_lookupContext->document()->bind();
         const Interpreter::ObjectValue *objValue = bind->findQmlObject(ast);
         QStringList prototypes;
 
-        if (m_lookupContext.isNull()) {
-            m_lookupContext = LookupContext::create(m_document, m_snapshot, QList<Node*>());
-        }
-
         while (objValue) {
             prototypes.append(objValue->className());
             objValue = objValue->prototype(m_lookupContext->context());
@@ -1189,7 +1195,7 @@ void QmlJSTextEditor::setSelectedElements()
 
     if (m_semanticInfo.document) {
         SelectedElement selectedMembers;
-        QList<UiObjectMember *> members = selectedMembers(m_semanticInfo.document, m_semanticInfo.snapshot,
+        QList<UiObjectMember *> members = selectedMembers(m_semanticInfo.lookupContext(),
                                                           startPos, endPos);
         if (!members.isEmpty()) {
             foreach(UiObjectMember *m, members) {
@@ -1376,7 +1382,7 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
         return Link();
     }
 
-    LookupContext::Ptr lookupContext = LookupContext::create(semanticInfo.document, semanticInfo.snapshot, semanticInfo.astPath(cursorPosition));
+    LookupContext::Ptr lookupContext = semanticInfo.lookupContext(semanticInfo.astPath(cursorPosition));
     const Interpreter::Value *value = lookupContext->evaluate(node);
 
     QString fileName;
@@ -1422,7 +1428,7 @@ void QmlJSTextEditor::showContextPane()
 {
     if (m_contextPane) {
         Node *newNode = m_semanticInfo.declaringMemberNoProperties(position());
-        m_contextPane->apply(editableInterface(), m_semanticInfo.document, m_semanticInfo.snapshot, newNode, false, true);
+        m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, false, true);
         m_oldCursorPosition = position();
         QList<TextEditor::Internal::RefactorMarker> markers;
         setRefactorMarkers(markers);
@@ -1481,7 +1487,7 @@ void QmlJSTextEditor::wheelEvent(QWheelEvent *event)
     BaseTextEditor::wheelEvent(event);
 
     if (visible)
-        m_contextPane->apply(editableInterface(),  m_semanticInfo.document, m_semanticInfo.snapshot, m_semanticInfo.declaringMemberNoProperties(position()), false, true);
+        m_contextPane->apply(editableInterface(),  m_semanticInfo.lookupContext(), m_semanticInfo.declaringMemberNoProperties(position()), false, true);
 }
 
 void QmlJSTextEditor::resizeEvent(QResizeEvent *event)
@@ -1723,7 +1729,7 @@ void QmlJSTextEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
     if (m_contextPane) {
         Node *newNode = m_semanticInfo.declaringMemberNoProperties(position());
         if (newNode) {
-            m_contextPane->apply(editableInterface(), doc, m_semanticInfo.snapshot, newNode, true);
+            m_contextPane->apply(editableInterface(), m_semanticInfo.lookupContext(), newNode, true);
             showTextMarker();
         }
     }
@@ -1776,7 +1782,7 @@ bool QmlJSTextEditor::hideContextPane()
 {
     bool b = (m_contextPane) && m_contextPane->widget()->isVisible();
     if (b)
-        m_contextPane->apply(editableInterface(),  m_semanticInfo.document, m_semanticInfo.snapshot, 0, false);
+        m_contextPane->apply(editableInterface(),  m_semanticInfo.lookupContext(), 0, false);
     return b;
 }
 
diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h
index 058f5e6bd489c5325421aa2f0a64fcdd1639bae2..7e3c4efa0d52ca6a60e23906707606dfc4059b72 100644
--- a/src/plugins/qmljseditor/qmljseditor.h
+++ b/src/plugins/qmljseditor/qmljseditor.h
@@ -34,6 +34,7 @@
 
 #include <qmljs/qmljsdocument.h>
 #include <qmljs/qmljsscanner.h>
+#include <qmljs/qmljsinterpreter.h>
 #include <texteditor/basetexteditor.h>
 
 #include <QtCore/QWaitCondition>
@@ -53,6 +54,7 @@ class ICore;
 namespace QmlJS {
     class ModelManagerInterface;
     class IContextPane;
+    class LookupContext;
 }
 
 /*!
@@ -129,6 +131,9 @@ public:
     // Returns the list of nodes that enclose the given position.
     QList<QmlJS::AST::Node *> astPath(int cursorPosition) const;
 
+    // Returns a context for the given path
+    QSharedPointer<QmlJS::LookupContext> lookupContext(const QList<QmlJS::AST::Node *> &path = QList<QmlJS::AST::Node *>()) const;
+
 public: // attributes
     QmlJS::Document::Ptr document;
     QmlJS::Snapshot snapshot;
@@ -138,6 +143,10 @@ public: // attributes
 
     // these are in addition to the parser messages in the document
     QList<QmlJS::DiagnosticMessage> semanticMessages;
+
+private:
+    // created lazily
+    mutable QSharedPointer<const QmlJS::Interpreter::Context> m_context;
 };
 
 class SemanticHighlighter: public QThread
diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp
index 3d929d93d9ac6d58e143af8a9b7afe436be3352a..2e95585b92f2f228f9d17a22398fb2f40f250278 100644
--- a/src/plugins/qmljseditor/qmljshoverhandler.cpp
+++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp
@@ -111,9 +111,8 @@ void HoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
         if (astPath.isEmpty())
             return;
 
-        const Snapshot &snapshot = semanticInfo.snapshot;
         const Document::Ptr qmlDocument = semanticInfo.document;
-        LookupContext::Ptr lookupContext = LookupContext::create(qmlDocument, snapshot, astPath);
+        LookupContext::Ptr lookupContext = semanticInfo.lookupContext(astPath);
 
         if (!matchColorItem(lookupContext, qmlDocument, astPath, pos))
             handleOrdinaryMatch(lookupContext, semanticInfo.nodeUnderCursor(pos));
diff --git a/src/plugins/qmljseditor/qmloutlinemodel.cpp b/src/plugins/qmljseditor/qmloutlinemodel.cpp
index 7b2d9bf7e59581d0ae6ce44bafe713dde4bb1a10..8d9186c27edb676bc7e5b9d40bb4878c34ad4594 100644
--- a/src/plugins/qmljseditor/qmloutlinemodel.cpp
+++ b/src/plugins/qmljseditor/qmloutlinemodel.cpp
@@ -42,10 +42,7 @@ QVariant QmlOutlineItem::data(int role) const
             return QVariant();
 
         QList<AST::Node *> astPath = m_outlineModel->m_semanticInfo.astPath(location.begin());
-
-        Document::Ptr document = m_outlineModel->m_semanticInfo.document;
-        Snapshot snapshot = m_outlineModel->m_semanticInfo.snapshot;
-        LookupContext::Ptr lookupContext = LookupContext::create(document, snapshot, astPath);
+        LookupContext::Ptr lookupContext = m_outlineModel->m_semanticInfo.lookupContext(astPath);
         const Interpreter::Value *value = lookupContext->evaluate(uiQualifiedId);
 
         return prettyPrint(value, lookupContext->context());
@@ -331,10 +328,9 @@ void QmlOutlineModel::update(const SemanticInfo &semanticInfo)
 
     // Set up lookup context once to do the element type lookup
     //
-    // We're simplifying here by using the root context everywhere
-    // (empty node list). However, creating the LookupContext is quite expensive (about 3ms),
-    // and there is AFAIK no way to introduce new type names in a sub-context.
-    m_context = LookupContext::create(semanticInfo.document, semanticInfo.snapshot, QList<AST::Node*>());
+    // We're simplifying here by using the root context everywhere; should be
+    // ok since there is AFAIK no way to introduce new type names in a sub-context.
+    m_context = semanticInfo.lookupContext();
     m_typeToIcon.clear();
     m_itemToNode.clear();
     m_itemToIdNode.clear();
diff --git a/src/plugins/qmljseditor/quicktoolbar.cpp b/src/plugins/qmljseditor/quicktoolbar.cpp
index 60e257828be0643d070246d09a162b10e3b4183a..0d746e9fc85395ee87f7ad56e7cec0c78b832536 100644
--- a/src/plugins/qmljseditor/quicktoolbar.cpp
+++ b/src/plugins/qmljseditor/quicktoolbar.cpp
@@ -98,13 +98,16 @@ QuickToolBar::~QuickToolBar()
         m_widget.clear();
 }
 
-void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node, bool update, bool force)
+void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, LookupContext::Ptr lookupContext, AST::Node *node, bool update, bool force)
 {
     if (!QuickToolBarSettings::get().enableContextPane && !force && !update) {
         contextWidget()->hide();
         return;
     }
 
+    if (lookupContext.isNull())
+        return;
+    Document::Ptr doc = lookupContext->document();
     if (doc.isNull())
         return;
 
@@ -113,7 +116,6 @@ void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::P
 
     m_blockWriting = true;
 
-    LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<Node*>());
     const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node);
 
     QStringList prototypes;
@@ -211,43 +213,45 @@ void QuickToolBar::apply(TextEditor::BaseTextEditorEditable *editor, Document::P
 
 }
 
-bool QuickToolBar::isAvailable(TextEditor::BaseTextEditorEditable *, Document::Ptr doc, const QmlJS::Snapshot &snapshot, AST::Node *node)
+bool QuickToolBar::isAvailable(TextEditor::BaseTextEditorEditable *, LookupContext::Ptr lookupContext, AST::Node *node)
 {
+    if (lookupContext.isNull())
+        return false;
+    Document::Ptr doc = lookupContext->document();
     if (doc.isNull())
         return false;
 
     if (!node)
         return false;
 
-        LookupContext::Ptr lookupContext = LookupContext::create(doc, snapshot, QList<Node*>());
-        const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node);
+    const Interpreter::ObjectValue *scopeObject = doc->bind()->findQmlObject(node);
 
-        QStringList prototypes;
+    QStringList prototypes;
 
-        while (scopeObject) {
-            prototypes.append(scopeObject->className());
-            scopeObject =  scopeObject->prototype(lookupContext->context());
-        }
+    while (scopeObject) {
+        prototypes.append(scopeObject->className());
+        scopeObject =  scopeObject->prototype(lookupContext->context());
+    }
 
-        if (prototypes.contains("PropertyChanges")) {
-            const Interpreter::ObjectValue *targetObject = getPropertyChangesTarget(node, lookupContext);
-            prototypes.clear();
-            while (targetObject) {
-                prototypes.append(targetObject->className());
-                targetObject =  targetObject->prototype(lookupContext->context());
-            }
+    if (prototypes.contains("PropertyChanges")) {
+        const Interpreter::ObjectValue *targetObject = getPropertyChangesTarget(node, lookupContext);
+        prototypes.clear();
+        while (targetObject) {
+            prototypes.append(targetObject->className());
+            targetObject =  targetObject->prototype(lookupContext->context());
         }
+    }
 
-        if (prototypes.contains("Rectangle") ||
+    if (prototypes.contains("Rectangle") ||
             prototypes.contains("Image") ||
             prototypes.contains("BorderImage") ||
             prototypes.contains("TextEdit") ||
             prototypes.contains("TextInput") ||
             prototypes.contains("PropertyAnimation") ||
             prototypes.contains("Text"))
-            return true;
+        return true;
 
-        return false;
+    return false;
 }
 
 void QuickToolBar::setProperty(const QString &propertyName, const QVariant &value)
diff --git a/src/plugins/qmljseditor/quicktoolbar.h b/src/plugins/qmljseditor/quicktoolbar.h
index 75ea8d54c11faa4697c795cea7a8b17b8927bf1b..79c57165546db09e5655b309ab4f0c27957242f5 100644
--- a/src/plugins/qmljseditor/quicktoolbar.h
+++ b/src/plugins/qmljseditor/quicktoolbar.h
@@ -30,8 +30,8 @@ class QuickToolBar : public QmlJS::IContextPane
 public:
    QuickToolBar(QObject *parent = 0);
    ~QuickToolBar();
-   void apply(TextEditor::BaseTextEditorEditable *editor, QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot, QmlJS::AST::Node *node, bool update, bool force = 0);
-   bool isAvailable(TextEditor::BaseTextEditorEditable *editor, QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot, QmlJS::AST::Node *node);
+   void apply(TextEditor::BaseTextEditorEditable *editor, QmlJS::LookupContext::Ptr lookupContext, QmlJS::AST::Node *node, bool update, bool force = 0);
+   bool isAvailable(TextEditor::BaseTextEditorEditable *editor, QmlJS::LookupContext::Ptr lookupContext, QmlJS::AST::Node *node);
    void setProperty(const QString &propertyName, const QVariant &value);
    void removeProperty(const QString &propertyName);
    void setEnabled(bool);