V4: Do not update proto usage before engine is fully initialized
Updating the prototype usage is very expensive. We only need to do it once there are lookups. Before the engine is fully initialized there are no lookups. Change-Id: Ic919a1f8955718d417e7747ea72e009d443c42fd Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
d183606126
commit
4c3098ab10
|
@ -867,6 +867,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
QV4::QObjectWrapper::initializeBindings(this);
|
||||
|
||||
m_delayedCallQueue.init(this);
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
ExecutionEngine::~ExecutionEngine()
|
||||
|
@ -2182,8 +2183,11 @@ const QSet<QString> &ExecutionEngine::illegalNames() const
|
|||
|
||||
void ExecutionEngine::setQmlEngine(QQmlEngine *engine)
|
||||
{
|
||||
// Second stage of initialization. We're updating some more prototypes here.
|
||||
isInitialized = false;
|
||||
m_qmlEngine = engine;
|
||||
initQmlGlobalObject();
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
|
||||
|
|
|
@ -44,7 +44,8 @@ struct Q_QML_EXPORT EngineBase {
|
|||
#endif
|
||||
|
||||
quint8 isExecutingInRegExpJIT = false;
|
||||
quint8 padding[3];
|
||||
quint8 isInitialized = false;
|
||||
quint8 padding[2];
|
||||
MemoryManager *memoryManager = nullptr;
|
||||
|
||||
qint32 callDepth = 0;
|
||||
|
|
|
@ -38,6 +38,9 @@ ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *objec
|
|||
|
||||
ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
primitiveLookup.type = object.type();
|
||||
switch (primitiveLookup.type) {
|
||||
case Value::Undefined_Type:
|
||||
|
@ -83,6 +86,9 @@ ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Valu
|
|||
|
||||
ReturnedValue Lookup::resolveGlobalGetter(ExecutionEngine *engine)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Object *o = engine->globalObject;
|
||||
PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
|
||||
protoLookup.protoId = o->internalClass()->protoId;
|
||||
|
@ -220,6 +226,9 @@ ReturnedValue Lookup::getter0Inline(Lookup *l, ExecutionEngine *engine, const Va
|
|||
|
||||
ReturnedValue Lookup::getterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
// we can safely cast to a QV4::Object here. If object is actually a string,
|
||||
// the internal class won't match
|
||||
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
|
||||
|
@ -277,6 +286,9 @@ ReturnedValue Lookup::getter0MemberDatagetter0MemberData(Lookup *l, ExecutionEng
|
|||
|
||||
ReturnedValue Lookup::getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
// we can safely cast to a QV4::Object here. If object is actually a string,
|
||||
// the internal class won't match
|
||||
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
|
||||
|
@ -312,6 +324,9 @@ ReturnedValue Lookup::getterAccessor(Lookup *l, ExecutionEngine *engine, const V
|
|||
|
||||
ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
// we can safely cast to a QV4::Object here. If object is actually a string,
|
||||
// the internal class won't match
|
||||
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
|
||||
|
@ -328,6 +343,9 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co
|
|||
|
||||
ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
// we can safely cast to a QV4::Object here. If object is actually a string,
|
||||
// the internal class won't match
|
||||
Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
|
||||
|
@ -381,6 +399,9 @@ ReturnedValue Lookup::getterQObject(Lookup *lookup, ExecutionEngine *engine, con
|
|||
|
||||
ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
if (object.type() == l->primitiveLookup.type && !object.isObject()) {
|
||||
Heap::Object *o = l->primitiveLookup.proto;
|
||||
if (l->primitiveLookup.protoId == o->internalClass->protoId)
|
||||
|
@ -392,6 +413,9 @@ ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, c
|
|||
|
||||
ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
if (object.type() == l->primitiveLookup.type && !object.isObject()) {
|
||||
Heap::Object *o = l->primitiveLookup.proto;
|
||||
if (l->primitiveLookup.protoId == o->internalClass->protoId) {
|
||||
|
@ -423,6 +447,9 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
|
|||
|
||||
ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Heap::Object *o = engine->globalObject->d();
|
||||
if (l->protoLookup.protoId == o->internalClass->protoId)
|
||||
return l->protoLookup.data->asReturnedValue();
|
||||
|
@ -432,6 +459,9 @@ ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine)
|
|||
|
||||
ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Heap::Object *o = engine->globalObject->d();
|
||||
if (l->protoLookup.protoId == o->internalClass->protoId) {
|
||||
const Value *getter = l->protoLookup.data;
|
||||
|
@ -551,6 +581,9 @@ bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, c
|
|||
|
||||
bool Lookup::setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Object *o = static_cast<Object *>(object.managed());
|
||||
if (o && o->internalClass()->protoId == l->insertionLookup.protoId) {
|
||||
o->setInternalClass(l->insertionLookup.newClass);
|
||||
|
|
|
@ -68,7 +68,9 @@ void Object::setInternalClass(Heap::InternalClass *ic)
|
|||
}
|
||||
}
|
||||
|
||||
if (ic->isUsedAsProto())
|
||||
// Before the engine is done initializing, we cannot have any lookups.
|
||||
// Therefore, there is no point in updating the proto IDs.
|
||||
if (ic->engine->isInitialized && ic->isUsedAsProto())
|
||||
ic->updateProtoUsage(p);
|
||||
|
||||
}
|
||||
|
@ -734,6 +736,9 @@ ReturnedValue Object::virtualInstanceOf(const Object *typeObject, const Value &v
|
|||
|
||||
ReturnedValue Object::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Heap::Object *obj = object->d();
|
||||
PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
|
||||
if (name.isArrayIndex()) {
|
||||
|
@ -769,6 +774,9 @@ ReturnedValue Object::virtualResolveLookupGetter(const Object *object, Execution
|
|||
|
||||
bool Object::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value)
|
||||
{
|
||||
// Otherwise we cannot trust the protoIds
|
||||
Q_ASSERT(engine->isInitialized);
|
||||
|
||||
Scope scope(engine);
|
||||
ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue