Implement loading of resolved imported scripts

We can resolve the use of names that refer to imported scripts at compile
time and load them at run-time by index through context->importedScripts.

Change-Id: I681b19e7d68dbf3b9a68af00b4cea2a9254c2d78
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Simon Hausmann 2013-10-28 17:02:54 +01:00 committed by The Qt Project
parent b0afac3daf
commit f0ad3a5943
14 changed files with 88 additions and 29 deletions

View File

@ -1324,11 +1324,11 @@ V4IR::Expr *JSCodeGen::member(V4IR::Expr *base, const QString *name)
// Check if it's suitable for caching
if (propertySuitable)
cache = engine->propertyCacheForType(baseAsMember->property->propType);
} else if (baseAsMember->type == V4IR::Member::MemberByObjectId) {
} else if (baseAsMember->type == V4IR::Member::MemberOfQmlContext) {
// Similarly, properties of an id referenced object also don't need to be final, because
// we intend to find the version of a property available at compile time, not at run-time.
foreach (const IdMapping &mapping, _idObjects) {
if (baseAsMember->objectId == mapping.idIndex) {
if (baseAsMember->memberIndex == mapping.idIndex) {
cache = mapping.type;
break;
}
@ -1363,15 +1363,21 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
// Look for IDs first.
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
result = _block->QML_CONTEXT_ID_MEMBER(_block->NAME(V4IR::Name::builtin_qml_id_scope, line, col),
result = _block->QML_CONTEXT_MEMBER(_block->NAME(V4IR::Name::builtin_qml_id_scope, line, col),
_function->newString(mapping.name), mapping.idIndex);
break;
}
if (!result) {
QQmlTypeNameCache::Result r = imports->query(name);
if (r.isValid())
return 0; // TODO: We can't do fast lookup for these yet.
if (r.isValid()) {
if (r.scriptIndex != -1) {
result = _block->QML_CONTEXT_MEMBER(_block->NAME(V4IR::Name::builtin_qml_imported_scripts_scope, line, col),
_function->newString(name), r.scriptIndex);
} else {
return 0; // TODO: We can't do fast lookup for these yet.
}
}
}
if (!result && _scopeObject) {

View File

@ -125,6 +125,7 @@ QT_BEGIN_NAMESPACE
F(SubNumberParams, subNumberParams) \
F(LoadThis, loadThis) \
F(LoadQmlIdObject, loadQmlIdObject) \
F(LoadQmlImportedScript, loadQmlImportedScript) \
F(LoadQmlContextObject, loadQmlContextObject) \
F(LoadQmlScopeObject, loadQmlScopeObject)
@ -644,6 +645,11 @@ union Instr
Param result;
int id;
};
struct instr_loadQmlImportedScript {
MOTH_INSTR_HEADER
Param result;
int index;
};
struct instr_loadQmlContextObject {
MOTH_INSTR_HEADER
Param result;
@ -729,6 +735,7 @@ union Instr
instr_subNumberParams subNumberParams;
instr_loadThis loadThis;
instr_loadQmlIdObject loadQmlIdObject;
instr_loadQmlImportedScript loadQmlImportedScript;
instr_loadQmlContextObject loadQmlContextObject;
instr_loadQmlScopeObject loadQmlScopeObject;

View File

@ -948,11 +948,16 @@ void InstructionSelection::loadThisObject(V4IR::Temp *temp)
#endif
}
void InstructionSelection::loadIdObject(int id, V4IR::Temp *temp)
void InstructionSelection::loadQmlIdObject(int id, V4IR::Temp *temp)
{
generateFunctionCall(temp, __qmljs_get_id_object, Assembler::ContextRegister, Assembler::TrustedImm32(id));
}
void InstructionSelection::loadQmlImportedScript(int index, V4IR::Temp *temp)
{
generateFunctionCall(temp, __qmljs_get_imported_script, Assembler::ContextRegister, Assembler::TrustedImm32(index));
}
void InstructionSelection::loadQmlContextObject(V4IR::Temp *temp)
{
generateFunctionCall(temp, __qmljs_get_context_object, Assembler::ContextRegister);

View File

@ -1469,7 +1469,8 @@ protected:
virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args, V4IR::Temp *result);
virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
virtual void loadThisObject(V4IR::Temp *temp);
virtual void loadIdObject(int id, V4IR::Temp *temp);
virtual void loadQmlIdObject(int id, V4IR::Temp *temp);
virtual void loadQmlImportedScript(int index, V4IR::Temp *temp);
virtual void loadQmlContextObject(V4IR::Temp *temp);
virtual void loadQmlScopeObject(V4IR::Temp *temp);
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);

View File

@ -454,7 +454,7 @@ void InstructionSelection::loadThisObject(V4IR::Temp *temp)
addInstruction(load);
}
void InstructionSelection::loadIdObject(int id, V4IR::Temp *temp)
void InstructionSelection::loadQmlIdObject(int id, V4IR::Temp *temp)
{
Instruction::LoadQmlIdObject load;
load.result = getResultParam(temp);
@ -462,6 +462,14 @@ void InstructionSelection::loadIdObject(int id, V4IR::Temp *temp)
addInstruction(load);
}
void InstructionSelection::loadQmlImportedScript(int index, V4IR::Temp *temp)
{
Instruction::LoadQmlImportedScript load;
load.result = getResultParam(temp);
load.index = index;
addInstruction(load);
}
void InstructionSelection::loadQmlContextObject(V4IR::Temp *temp)
{
Instruction::LoadQmlContextObject load;

View File

@ -114,7 +114,8 @@ protected:
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
virtual void loadThisObject(V4IR::Temp *temp);
virtual void loadIdObject(int id, V4IR::Temp *temp);
virtual void loadQmlIdObject(int id, V4IR::Temp *temp);
virtual void loadQmlImportedScript(int index, V4IR::Temp *temp);
virtual void loadQmlContextObject(V4IR::Temp *temp);
virtual void loadQmlScopeObject(V4IR::Temp *temp);
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);

View File

@ -140,9 +140,17 @@ void IRDecoder::visitMove(V4IR::Move *s)
return;
}
} else if (V4IR::Member *m = s->source->asMember()) {
if (m->type == V4IR::Member::MemberByObjectId) {
loadIdObject(m->objectId, t);
return;
if (m->type == V4IR::Member::MemberOfQmlContext) {
V4IR::Name *base = m->base->asName();
Q_ASSERT(base);
if (base->builtin == V4IR::Name::builtin_qml_id_scope) {
loadQmlIdObject(m->memberIndex, t);
return;
} else if (base->builtin == V4IR::Name::builtin_qml_imported_scripts_scope) {
loadQmlImportedScript(m->memberIndex, t);
return;
}
} else if (m->type == V4IR::Member::MemberOfQObject) {
getQObjectProperty(m->base, m->property->coreIndex, t);
return;

View File

@ -140,7 +140,8 @@ public: // to implement by subclasses:
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0;
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0;
virtual void loadThisObject(V4IR::Temp *temp) = 0;
virtual void loadIdObject(int id, V4IR::Temp *temp) = 0;
virtual void loadQmlIdObject(int id, V4IR::Temp *temp) = 0;
virtual void loadQmlImportedScript(int index, V4IR::Temp *temp) = 0;
virtual void loadQmlContextObject(V4IR::Temp *temp) = 0;
virtual void loadQmlScopeObject(V4IR::Temp *temp) = 0;
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp) = 0;

View File

@ -424,6 +424,8 @@ static const char *builtin_to_string(Name::Builtin b)
return "builtin_setup_argument_object";
case V4IR::Name::builtin_qml_id_scope:
return "builtin_qml_id_scope";
case V4IR::Name::builtin_qml_imported_scripts_scope:
return "builtin_qml_imported_scripts_scope";
case V4IR::Name::builtin_qml_scope_object:
return "builtin_qml_scope_object";
case V4IR::Name::builtin_qml_context_object:
@ -826,11 +828,10 @@ Expr *BasicBlock::MEMBER(Expr *base, const QString *name)
return e;
}
Expr *BasicBlock::QML_CONTEXT_ID_MEMBER(Expr *base, const QString *id, int objectId)
Expr *BasicBlock::QML_CONTEXT_MEMBER(Expr *base, const QString *id, int memberIndex)
{
Member*e = function->New<Member>();
Q_ASSERT(base->asName() && base->asName()->builtin == Name::builtin_qml_id_scope);
e->initQmlIdObject(base, id, objectId);
e->initQmlContextMember(base, id, memberIndex);
return e;
}
@ -1029,8 +1030,8 @@ void CloneExpr::visitMember(Member *e)
{
if (e->type == Member::MemberByName)
cloned = block->MEMBER(clone(e->base), e->name);
else if (e->type == Member::MemberByObjectId)
cloned = block->QML_CONTEXT_ID_MEMBER(clone(e->base), e->name, e->objectId);
else if (e->type == Member::MemberOfQmlContext)
cloned = block->QML_CONTEXT_MEMBER(clone(e->base), e->name, e->memberIndex);
else if (e->type == Member::MemberOfQObject)
cloned = block->QML_QOBJECT_PROPERTY(clone(e->base), e->name, e->property);
else
@ -1039,9 +1040,12 @@ void CloneExpr::visitMember(Member *e)
void QmlDependenciesCollector::visitMember(Member *e) {
e->base->accept(this);
if (e->type == Member::MemberByObjectId)
_usedIdObjects.insert(e->objectId);
else if (e->type == Member::MemberOfQObject
if (e->type == Member::MemberOfQmlContext) {
V4IR::Name *base = e->base->asName();
Q_ASSERT(base);
if (base->builtin == V4IR::Name::builtin_qml_id_scope)
_usedIdObjects.insert(e->memberIndex);
} else if (e->type == Member::MemberOfQObject
&& !e->property->isFunction()) { // only non-functions have notifyIndex
if (Name *base = e->base->asName()) {

View File

@ -325,6 +325,7 @@ struct Name: Expr {
builtin_define_object_literal,
builtin_setup_argument_object,
builtin_qml_id_scope,
builtin_qml_imported_scripts_scope,
builtin_qml_context_object,
builtin_qml_scope_object
};
@ -519,14 +520,14 @@ struct Member: Expr {
enum MemberType {
MemberByName,
// QML extensions
MemberByObjectId, // lookup in context's id values
MemberOfQmlContext, // lookup in context's id values
MemberOfQObject
};
MemberType type;
Expr *base;
const QString *name;
int objectId;
int memberIndex; // used if type == MemberOfQmlContext
QQmlPropertyData *property;
void init(Expr *base, const QString *name)
@ -534,16 +535,16 @@ struct Member: Expr {
this->type = MemberByName;
this->base = base;
this->name = name;
this->objectId = -1;
this->memberIndex = -1;
this->property = 0;
}
void initQmlIdObject(Expr *base, const QString *name, int objectId)
void initQmlContextMember(Expr *base, const QString *name, int memberIndex)
{
this->type = MemberByObjectId;
this->type = MemberOfQmlContext;
this->base = base;
this->name = name;
this->objectId = objectId;
this->memberIndex = memberIndex;
this->property = 0;
}
@ -846,7 +847,7 @@ struct BasicBlock {
Expr *NEW(Expr *base, ExprList *args = 0);
Expr *SUBSCRIPT(Expr *base, Expr *index);
Expr *MEMBER(Expr *base, const QString *name);
Expr *QML_CONTEXT_ID_MEMBER(Expr *base, const QString *id, int idIndex);
Expr *QML_CONTEXT_MEMBER(Expr *base, const QString *id, int memberIndex);
Expr *QML_QOBJECT_PROPERTY(Expr *base, const QString *id, QQmlPropertyData *property);
Stmt *EXP(Expr *expr);

View File

@ -334,7 +334,13 @@ protected: // IRDecoder
addDef(temp);
}
virtual void loadIdObject(int id, V4IR::Temp *temp)
virtual void loadQmlIdObject(int id, V4IR::Temp *temp)
{
addDef(temp);
addCall();
}
virtual void loadQmlImportedScript(int index, V4IR::Temp *temp)
{
addDef(temp);
addCall();

View File

@ -1218,6 +1218,12 @@ void __qmljs_set_qobject_property(ExecutionContext *ctx, const ValueRef object,
wrapper->setProperty(ctx, propertyIndex, value);
}
ReturnedValue __qmljs_get_imported_script(ExecutionContext *ctx, int index)
{
QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine);
return context->importedScripts.at(index).value();
}
} // namespace QV4
QT_END_NAMESPACE

View File

@ -165,6 +165,7 @@ QV4::ReturnedValue __qmljs_get_element(QV4::ExecutionContext *ctx, const QV4::Va
void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::ValueRef index, const QV4::ValueRef value);
QV4::ReturnedValue __qmljs_get_id_object(ExecutionContext *ctx, int id);
QV4::ReturnedValue __qmljs_get_imported_script(ExecutionContext *ctx, int index);
QV4::ReturnedValue __qmljs_get_context_object(ExecutionContext *ctx);
QV4::ReturnedValue __qmljs_get_scope_object(ExecutionContext *ctx);
QV4::ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex);

View File

@ -641,6 +641,10 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
VALUE(instr.result) = __qmljs_get_id_object(context, instr.id);
MOTH_END_INSTR(LoadQmlIdObject)
MOTH_BEGIN_INSTR(LoadQmlImportedScript)
VALUE(instr.result) = __qmljs_get_imported_script(context, instr.index);
MOTH_END_INSTR(LoadQmlImportedScript)
MOTH_BEGIN_INSTR(LoadQmlContextObject)
VALUE(instr.result) = __qmljs_get_context_object(context);
MOTH_END_INSTR(LoadContextObject)