diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp
index acec98192d152ae179401db85eed6f6d72be8330..788e2446b4ad29113a66da40b785d14e950f1f0e 100644
--- a/src/particles/qquickcustomaffector.cpp
+++ b/src/particles/qquickcustomaffector.cpp
@@ -42,6 +42,7 @@
 #include "qquickcustomaffector_p.h"
 #include <private/qv8engine_p.h>
 #include <private/qqmlengine_p.h>
+#include <private/qqmlglobal_p.h>
 #include <QQmlEngine>
 #include <QDebug>
 QT_BEGIN_NAMESPACE
@@ -102,8 +103,7 @@ QQuickCustomAffector::QQuickCustomAffector(QQuickItem *parent) :
 
 bool QQuickCustomAffector::isAffectConnected()
 {
-    static int idx = QObjectPrivate::get(this)->signalIndex("affectParticles(QQmlV8Handle,qreal)");
-    return QObjectPrivate::get(this)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(this, "affectParticles(QQmlV8Handle,qreal)");
 }
 
 void QQuickCustomAffector::affectSystem(qreal dt)
diff --git a/src/particles/qquickparticleaffector.cpp b/src/particles/qquickparticleaffector.cpp
index 0005af86af97f70620ba2311b3163cc98c68b7e2..e2be8771d413ca36397fe33e6d74d2db1cbf3bd1 100644
--- a/src/particles/qquickparticleaffector.cpp
+++ b/src/particles/qquickparticleaffector.cpp
@@ -41,6 +41,7 @@
 
 #include "qquickparticleaffector_p.h"
 #include <QDebug>
+#include <private/qqmlglobal_p.h>
 QT_BEGIN_NAMESPACE
 
 /*!
@@ -146,8 +147,7 @@ QQuickParticleAffector::QQuickParticleAffector(QQuickItem *parent) :
 
 bool QQuickParticleAffector::isAffectedConnected()
 {
-    static int idx = QObjectPrivate::get(this)->signalIndex("affected(qreal,qreal)");
-    return QObjectPrivate::get(this)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(this, "affected(qreal,qreal)");
 }
 
 
diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp
index 035d66cbcd56779078c36a81e5ebac4a4c8f0cff..8181e8b4f150ec976f0d8c283625c071fcde03d2 100644
--- a/src/particles/qquickparticleemitter.cpp
+++ b/src/particles/qquickparticleemitter.cpp
@@ -41,6 +41,7 @@
 
 #include "qquickparticleemitter_p.h"
 #include <private/qqmlengine_p.h>
+#include <private/qqmlglobal_p.h>
 QT_BEGIN_NAMESPACE
 
 
@@ -253,8 +254,7 @@ QQuickParticleEmitter::~QQuickParticleEmitter()
 
 bool QQuickParticleEmitter::isEmitConnected()
 {
-    static int idx = QObjectPrivate::get(this)->signalIndex("emitParticles(QQmlV8Handle)");
-    return QObjectPrivate::get(this)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(this, "emitParticles(QQmlV8Handle)");
 }
 
 void QQuickParticleEmitter::componentComplete()
diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp
index 32f8763599736a9dde2357dde21134eb6aaea772..3ea68ce681332c06bcf4066941fc3c92c9e5f187 100644
--- a/src/particles/qquicktrailemitter.cpp
+++ b/src/particles/qquicktrailemitter.cpp
@@ -41,6 +41,7 @@
 
 #include "qquicktrailemitter_p.h"
 #include <private/qqmlengine_p.h>
+#include <private/qqmlglobal_p.h>
 #include <cmath>
 QT_BEGIN_NAMESPACE
 
@@ -126,8 +127,7 @@ QQuickTrailEmitter::QQuickTrailEmitter(QQuickItem *parent) :
 
 bool QQuickTrailEmitter::isEmitFollowConnected()
 {
-    static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticles(QQmlV8Handle,QQmlV8Handle)");
-    return QObjectPrivate::get(this)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(this, "emitFollowParticles(QQmlV8Handle,QQmlV8Handle)");
 }
 
 void QQuickTrailEmitter::recalcParticlesPerSecond(){
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index b8eee4775066d16a6de0bd8184aba593bcb44467..1a188f9e59d0e4c3ff96c0143e3f4dfa1ea6ac25 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -133,6 +133,7 @@ public:
     inline QQmlNotifierEndpoint *notify(int index);
     void addNotify(int index, QQmlNotifierEndpoint *);
     int endpointCount(int index);
+    bool signalHasEndpoint(int index);
 
     // The context that created the C++ object
     QQmlContextData *context; 
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 7317689907d21bfadd6ebbf293bb7ed9c0f36d81..c1ce012d274b0a617b6a2822759370f8d88786dc 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -77,13 +77,13 @@
 #include <QtCore/qmetaobject.h>
 #include <QNetworkAccessManager>
 #include <QDebug>
-#include <QMetaObject>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qdir.h>
 #include <QtCore/qmutex.h>
 #include <QtNetwork/qnetworkconfigmanager.h>
 
 #include <private/qobject_p.h>
+#include <private/qmetaobject_p.h>
 
 #include <private/qqmllocale_p.h>
 
@@ -1155,6 +1155,21 @@ void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
     }
 }
 
+bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
+{
+    QQmlData *data = QQmlData::get(obj);
+    return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
+}
+
+/*
+    index MUST be the index returned by QMetaMethod::index()
+    This is different than the index returned by QObjectPrivate::signalIndex()
+*/
+bool QQmlData::signalHasEndpoint(int index)
+{
+    return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
+}
+
 QQmlNotifier *QQmlData::objectNameNotifier() const
 {
     if (!extendedData) extendedData = new QQmlDataExtended;
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 2356b2d122b09841d0be62898ec123cb735b6af8..04711ae3fcaa08cecbcf54b79a06b9a9dea3dc52 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -89,6 +89,21 @@ QT_BEGIN_NAMESPACE
     QMetaObject::connect(sender, signalIdx, receiver, methodIdx, Qt::DirectConnection); \
 }
 
+bool Q_QML_EXPORT QQml_isSignalConnected(QObject*, int, int);
+
+#define IS_SIGNAL_CONNECTED(Sender, Signal) \
+do { \
+    QObject *sender = (Sender); \
+    const char *signal = (Signal); \
+    static int signalIdx = -1; \
+    static int methodIdx = -1; \
+    if (signalIdx < 0) { \
+        signalIdx = QObjectPrivate::get(sender)->signalIndex(signal); \
+        methodIdx = sender->metaObject()->indexOfSignal(signal); \
+    } \
+    return QQml_isSignalConnected(sender, signalIdx, methodIdx); \
+} while (0)
+
 struct QQmlGraphics_DerivedObject : public QObject
 {
     void setParent_noEvent(QObject *parent) {
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 4f849c771b2274244edbe5c4d2ddab57acab713f..6c8c8f3f53327a186e88f186760068bee7676df6 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -446,6 +446,11 @@ QQuickCanvasContext* QQuickCanvasItem::rawContext() const
     return d_func()->context;
 }
 
+bool QQuickCanvasItem::isPaintConnected()
+{
+    IS_SIGNAL_CONNECTED(this, "paint(QRect)");
+}
+
 void QQuickCanvasItem::sceneGraphInitialized()
 {
     Q_D(QQuickCanvasItem);
@@ -456,7 +461,7 @@ void QQuickCanvasItem::sceneGraphInitialized()
 
     if (!d->contextType.isNull())
         QMetaObject::invokeMethod(this, "delayedCreate", Qt::QueuedConnection);
-    else if (receivers(SIGNAL(paint(QRect))) > 0)
+    else if (isPaintConnected())
         QMetaObject::invokeMethod(this, "requestPaint", Qt::QueuedConnection);
 }
 
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index 9a57733d4ca1d8ea6fb8273cecb838a0bc3df4e5..5238fbcf6d6cf0f447ecc3140a71d0ee4d4ac184 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -158,6 +158,7 @@ private:
     bool createContext(const QString &contextType);
     void initializeContext(QQuickCanvasContext *context, const QVariantMap &args = QVariantMap());
     QRect tiledRect(const QRectF &window, const QSize &tileSize);
+    bool isPaintConnected();
 };
 
 QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index cf06dc228f7b3cd935e1ae20a9acc2fc5a93b8ba..5259b625262e98a01f08362f0a2e8ef5dbff2353 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -907,9 +907,13 @@ const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = {
     { 0, 0 }
 };
 
-bool QQuickKeysAttachedPrivate::isConnected(const char *signalName)
+bool QQuickKeysAttached::isConnected(const char *signalName)
 {
-    return isSignalConnected(signalIndex(signalName));
+    Q_D(QQuickKeysAttached);
+    //### doing two string-based lookups isn't ideal
+    int signal_index = d->signalIndex(signalName);
+    int index = metaObject()->indexOfSignal(signalName);
+    return QQml_isSignalConnected(this, signal_index, index);
 }
 
 /*!
@@ -1369,7 +1373,7 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
     QByteArray keySignal = keyToSignal(event->key());
     if (!keySignal.isEmpty()) {
         keySignal += "(QQuickKeyEvent*)";
-        if (d->isConnected(keySignal)) {
+        if (isConnected(keySignal)) {
             // If we specifically handle a key then default to accepted
             ke.setAccepted(true);
             int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(keySignal);
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 89c09ed01597635a0e79fbe79a2577540c6f39a0..ed762d011a7313b95171abcce6f8c606c181cfc5 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -710,8 +710,6 @@ public:
         , inIM(false), enabled(true), imeItem(0), item(0)
     {}
 
-    bool isConnected(const char *signalName);
-
     //loop detection
     bool inPress:1;
     bool inRelease:1;
@@ -827,6 +825,8 @@ private:
         return keySignal;
     }
 
+    bool isConnected(const char *signalName);
+
     struct SigMap {
         int key;
         const char *sig;
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 956ca09aacbc34ec2dded339686a46ada405acd5..9185556cc902a974c43c5e2a3782fe0321a24340 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -45,6 +45,8 @@
 #include "qquickevents_p_p.h"
 #include "qquickdrag_p.h"
 
+#include <private/qqmldata_p.h>
+
 #include <QtGui/qevent.h>
 #include <QtGui/qguiapplication.h>
 #include <QtGui/qstylehints.h>
@@ -218,29 +220,25 @@ void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event)
 bool QQuickMouseAreaPrivate::isPressAndHoldConnected()
 {
     Q_Q(QQuickMouseArea);
-    static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QQuickMouseEvent*)");
-    return QObjectPrivate::get(q)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(q, "pressAndHold(QQuickMouseEvent*)");
 }
 
 bool QQuickMouseAreaPrivate::isDoubleClickConnected()
 {
     Q_Q(QQuickMouseArea);
-    static int idx = QObjectPrivate::get(q)->signalIndex("doubleClicked(QQuickMouseEvent*)");
-    return QObjectPrivate::get(q)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(q, "doubleClicked(QQuickMouseEvent*)");
 }
 
 bool QQuickMouseAreaPrivate::isClickConnected()
 {
     Q_Q(QQuickMouseArea);
-    static int idx = QObjectPrivate::get(q)->signalIndex("clicked(QQuickMouseEvent*)");
-    return QObjectPrivate::get(q)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(q, "clicked(QQuickMouseEvent*)");
 }
 
 bool QQuickMouseAreaPrivate::isWheelConnected()
 {
     Q_Q(QQuickMouseArea);
-    static int idx = QObjectPrivate::get(q)->signalIndex("wheel(QQuickWheelEvent*)");
-    return QObjectPrivate::get(q)->isSignalConnected(idx);
+    IS_SIGNAL_CONNECTED(q, "wheel(QQuickWheelEvent*)");
 }
 
 void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t)
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index cfedfbd890c5a638e89470b900a1dedd9a1df4c5..2407ade98847bef45fb227b359ba23cff4a5981d 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -594,8 +594,8 @@ void QQuickText::doLayout()
 
 bool QQuickTextPrivate::isLineLaidOutConnected()
 {
-    static int idx = this->signalIndex("lineLaidOut(QQuickTextLine*)");
-    return this->isSignalConnected(idx);
+    Q_Q(QQuickText);
+    IS_SIGNAL_CONNECTED(q, "lineLaidOut(QQuickTextLine*)");
 }
 
 void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, int lineOffset)
@@ -2406,8 +2406,8 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos)
 
 bool QQuickTextPrivate::isLinkActivatedConnected()
 {
-    static int idx = this->signalIndex("linkActivated(QString)");
-    return this->isSignalConnected(idx);
+    Q_Q(QQuickText);
+    IS_SIGNAL_CONNECTED(q, "linkActivated(QString)");
 }
 
 /*!  \internal */
diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
index cea83969f3c025a3cfa2e8a7eacd0f5804ca2b1a..5046b1afe051332a9c8c2e85e1c1ca0151c9556d 100644
--- a/src/quick/items/qquickvisualdatamodel.cpp
+++ b/src/quick/items/qquickvisualdatamodel.cpp
@@ -1748,11 +1748,15 @@ void QQuickVisualDataGroupPrivate::setModel(QQuickVisualDataModel *m, Compositor
     group = g;
 }
 
+static bool isChangedConnected(QObject *obj)
+{
+    IS_SIGNAL_CONNECTED(obj, "changed(QQmlV8Handle,QQmlV8Handle)");
+}
+
 void QQuickVisualDataGroupPrivate::emitChanges(QV8Engine *engine)
 {
     Q_Q(QQuickVisualDataGroup);
-    static int idx = signalIndex("changed(QQmlV8Handle,QQmlV8Handle)");
-    if (isSignalConnected(idx) && !changeSet.isEmpty()) {
+    if (isChangedConnected(q) && !changeSet.isEmpty()) {
         v8::HandleScope handleScope;
         v8::Context::Scope contextScope(engine->context());
         v8::Local<v8::Array> removed  = QQuickVisualDataModelPrivate::buildChangeList(changeSet.removes());