aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-01-10 14:16:22 +0100
committerLars Knoll <lars.knoll@qt.io>2018-04-12 13:59:17 +0000
commit6c8c604f11e7a6d5880e4f951255d496fe905797 (patch)
tree117050abfb2164d45575ee1bfd35de46ddf224b2
parent6b110a30df178b2aaace579841e5bd74f2e9ee99 (diff)
Reorganize Lookup data structure to make marking faster
Do this by always using odd numbers for protoId's, and putting those into the same place as the InternalClass pointers. That makes it possible to quickly check whether the lookup contains a pointer to a valid heap object. Change-Id: I330017b26c090b4dcbbcce1a127dca7ba7e148d1 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4engine_p.h5
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp6
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h2
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp49
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h34
5 files changed, 32 insertions, 64 deletions
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 737f377730..4316967484 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -374,7 +374,7 @@ public:
const bool m_canAllocateExecutableMemory;
#endif
- int internalClassIdCount = 0;
+ quintptr protoIdCount = 1;
ExecutionEngine(QJSEngine *jsEngine = nullptr);
~ExecutionEngine();
@@ -398,7 +398,8 @@ public:
return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
}
- int newInternalClassId() { return ++internalClassIdCount; }
+ // ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
+ quintptr newProtoId() { return (protoIdCount += 2); }
Heap::InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index be9a12bc34..a01e42e817 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -145,7 +145,7 @@ void InternalClass::init(ExecutionEngine *engine)
isFrozen = false;
isSealed = false;
isUsedAsProto = false;
- protoId = engine->newInternalClassId();
+ protoId = engine->newProtoId();
// Also internal classes need an internal class pointer. Simply make it point to itself
internalClass.set(engine, this);
@@ -170,7 +170,7 @@ void InternalClass::init(Heap::InternalClass *other)
isSealed = other->isSealed;
isFrozen = other->isFrozen;
isUsedAsProto = other->isUsedAsProto;
- protoId = engine->newInternalClassId();
+ protoId = engine->newProtoId();
internalClass.set(engine, other->internalClass);
}
@@ -611,7 +611,7 @@ Heap::InternalClass *InternalClass::asProtoClass()
static void updateProtoUsage(Heap::Object *o, Heap::InternalClass *ic)
{
if (ic->prototype == o)
- ic->protoId = ic->engine->newInternalClassId();
+ ic->protoId = ic->engine->newProtoId();
for (auto &t : ic->transitions) {
if (t.lookup)
updateProtoUsage(o, t.lookup);
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 909335df58..0b6f088bd3 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -264,9 +264,9 @@ struct InternalClassTransition
namespace Heap {
struct InternalClass : Base {
- int protoId; // unique across the engine, gets changed whenever the proto chain changes
ExecutionEngine *engine;
const VTable *vtable;
+ quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
Heap::Object *prototype;
InternalClass *parent;
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 5730ea7bc0..fdf3d7685d 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -598,53 +598,4 @@ bool Lookup::arrayLengthSetter(Lookup *, ExecutionEngine *engine, Value &object,
return true;
}
-void Lookup::markObjects(MarkStack *stack)
-{
- if (getter == getterGeneric ||
- getter == getterTwoClasses ||
- getter == getterFallback) {
- ;
- } else if (getter == getter0MemberData ||
- getter == getter0Inline ||
- getter == getterAccessor) {
- objectLookup.ic->mark(stack);
- } else if (getter == getterProto) {
- ;
- } else if (getter == getter0Inlinegetter0Inline ||
- getter == getter0Inlinegetter0MemberData ||
- getter == getter0MemberDatagetter0MemberData) {
- objectLookupTwoClasses.ic->mark(stack);
- objectLookupTwoClasses.ic2->mark(stack);
- } else if (getter == getterProtoTwoClasses ||
- getter == getterProtoAccessor ||
- getter == getterProtoAccessorTwoClasses) {
-
- } else if (getter == primitiveGetterProto ||
- getter == primitiveGetterAccessor) {
- primitiveLookup.proto->mark(stack);
- } else if (getter == stringLengthGetter) {
- ;
-
- } else if (globalGetter == globalGetterGeneric ||
- globalGetter == globalGetterProto ||
- globalGetter == globalGetterProtoAccessor) {
- ;
-
- } else if (setter == setterGeneric ||
- setter == setterTwoClasses ||
- setter == setterFallback) {
- ;
- } else if (setter == setter0 ||
- setter == setter0Inline) {
- objectLookup.ic->mark(stack);
- } else if (setter == setter0setter0) {
- objectLookupTwoClasses.ic->mark(stack);
- objectLookupTwoClasses.ic2->mark(stack);
- } else if (setter == setterInsert) {
- insertionLookup.newClass->mark(stack);
- } else if (setter == arrayLengthSetter) {
- ;
- }
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 75219d1b84..49eb66d1fb 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct Lookup {
- enum { Size = 4 };
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
@@ -73,12 +72,20 @@ struct Lookup {
};
union {
struct {
+ Heap::Base *h1;
+ Heap::Base *h2;
+ quintptr unused;
+ quintptr unused2;
+ } markDef;
+ struct {
Heap::InternalClass *ic;
+ quintptr _unused;
int offset;
} objectLookup;
struct {
+ quintptr protoId;
+ quintptr _unused;
const Value *data;
- int protoId;
} protoLookup;
struct {
Heap::InternalClass *ic;
@@ -87,21 +94,21 @@ struct Lookup {
int offset2;
} objectLookupTwoClasses;
struct {
+ quintptr protoId;
+ quintptr protoId2;
const Value *data;
const Value *data2;
- int protoId;
- int protoId2;
} protoLookupTwoClasses;
struct {
// Make sure the next two values are in sync with protoLookup
- const Value *data;
- int protoId;
- unsigned type;
+ quintptr protoId;
Heap::Object *proto;
+ const Value *data;
+ quintptr type;
} primitiveLookup;
struct {
Heap::InternalClass *newClass;
- int protoId;
+ quintptr protoId;
int offset;
} insertionLookup;
};
@@ -145,7 +152,16 @@ struct Lookup {
static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- void markObjects(MarkStack *stack);
+ void markObjects(MarkStack *stack) {
+ if (markDef.h1 && !(reinterpret_cast<quintptr>(markDef.h1) & 1))
+ markDef.h1->mark(stack);
+ if (markDef.h2 && !(reinterpret_cast<quintptr>(markDef.h2) & 1))
+ markDef.h2->mark(stack);
+ }
+
+ void clear() {
+ memset(&markDef, 0, sizeof(markDef));
+ }
};
Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);