QmlJS: Speed up ValueOwner construction.

* Don't build all default values (including the global object)
  separately for each ValueOwner instance.
* Instead, keep all global, immutable values in a single, shared
  instance.

While refactoring, some cases where we *modified* the global object had
to be removed:

* C++ context properties no longer get injected into the global object,
  instead they now have their own scope just above the global one.
* The Qt object's prototype no longer gets modified in Link. Instead,
  it's now a reference to the "Qt" object provided in a qmltypes file.
* The whole concept of a function 'Activation' that could potentially
  affect the global object was removed.

Change-Id: Id382faf965efa747fcc7a9b0bc2c90429d84d61b
Reviewed-by: Leandro Melo <leandro.melo@nokia.com>
This commit is contained in:
Christian Kamm
2011-11-21 14:51:03 +01:00
parent e2b0835b58
commit 097850c842
8 changed files with 408 additions and 728 deletions

View File

@@ -169,11 +169,6 @@ public:
{
return false;
}
virtual const Value *invoke(const Activation *) const
{
return valueOwner()->unknownValue();
}
};
} // end of anonymous namespace
@@ -1115,105 +1110,18 @@ QList<const ObjectValue *> PrototypeIterator::all()
return m_prototypes;
}
Activation::Activation(Context *parentContext)
: _thisObject(0),
_calledAsFunction(true),
_parentContext(parentContext)
{
}
Activation::~Activation()
{
}
Context *Activation::parentContext() const
{
return _parentContext;
}
Context *Activation::context() const
{
// ### FIXME: Real context for activations.
return 0;
}
bool Activation::calledAsConstructor() const
{
return ! _calledAsFunction;
}
void Activation::setCalledAsConstructor(bool calledAsConstructor)
{
_calledAsFunction = ! calledAsConstructor;
}
bool Activation::calledAsFunction() const
{
return _calledAsFunction;
}
void Activation::setCalledAsFunction(bool calledAsFunction)
{
_calledAsFunction = calledAsFunction;
}
ObjectValue *Activation::thisObject() const
{
return _thisObject;
}
void Activation::setThisObject(ObjectValue *thisObject)
{
_thisObject = thisObject;
}
ValueList Activation::arguments() const
{
return _arguments;
}
void Activation::setArguments(const ValueList &arguments)
{
_arguments = arguments;
}
FunctionValue::FunctionValue(ValueOwner *valueOwner)
: ObjectValue(valueOwner)
{
setClassName("Function");
setMember(QLatin1String("length"), valueOwner->numberValue());
setPrototype(valueOwner->functionPrototype());
}
FunctionValue::~FunctionValue()
{
}
const Value *FunctionValue::construct(const ValueList &actuals) const
{
Activation activation;
activation.setCalledAsConstructor(true);
activation.setThisObject(valueOwner()->newObject());
activation.setArguments(actuals);
return invoke(&activation);
}
const Value *FunctionValue::call(const ValueList &actuals) const
{
Activation activation;
activation.setCalledAsFunction(true);
activation.setThisObject(valueOwner()->globalObject()); // ### FIXME: it should be `null'
activation.setArguments(actuals);
return invoke(&activation);
}
const Value *FunctionValue::call(const ObjectValue *thisObject, const ValueList &actuals) const
{
Activation activation;
activation.setCalledAsFunction(true);
activation.setThisObject(const_cast<ObjectValue *>(thisObject)); // ### FIXME: remove the const_cast
activation.setArguments(actuals);
return invoke(&activation);
}
const Value *FunctionValue::returnValue() const
{
return valueOwner()->unknownValue();
@@ -1244,11 +1152,6 @@ bool FunctionValue::isVariadic() const
return true;
}
const Value *FunctionValue::invoke(const Activation *activation) const
{
return activation->thisObject(); // ### FIXME: it should return undefined
}
const FunctionValue *FunctionValue::asFunctionValue() const
{
return this;
@@ -1265,7 +1168,6 @@ Function::Function(ValueOwner *valueOwner)
, _optionalNamedArgumentCount(0)
, _isVariadic(false)
{
setClassName("Function");
}
Function::~Function()
@@ -1327,11 +1229,6 @@ QString Function::argumentName(int index) const
return FunctionValue::argumentName(index);
}
const Value *Function::invoke(const Activation *) const
{
return _returnValue;
}
bool Function::isVariadic() const
{
return _isVariadic;
@@ -1394,7 +1291,9 @@ void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml,
}
CppQmlTypes::CppQmlTypes(ValueOwner *valueOwner)
: _valueOwner(valueOwner)
: _cppContextProperties(0)
, _valueOwner(valueOwner)
{
}
@@ -1544,6 +1443,16 @@ const CppComponentValue *CppQmlTypes::objectByCppName(const QString &cppName) co
return objectByQualifiedName(qualifiedName(cppPackage, cppName, ComponentVersion()));
}
void CppQmlTypes::setCppContextProperties(const ObjectValue *contextProperties)
{
_cppContextProperties = contextProperties;
}
const ObjectValue *CppQmlTypes::cppContextProperties() const
{
return _cppContextProperties;
}
ConvertToNumber::ConvertToNumber(ValueOwner *valueOwner)
: _valueOwner(valueOwner), _result(0)
@@ -1595,14 +1504,14 @@ void ConvertToNumber::visit(const StringValue *)
void ConvertToNumber::visit(const ObjectValue *object)
{
if (const FunctionValue *valueOfMember = value_cast<FunctionValue>(object->lookupMember("valueOf", ContextPtr()))) {
_result = value_cast<NumberValue>(valueOfMember->call(object)); // ### invoke convert-to-number?
_result = value_cast<NumberValue>(valueOfMember->returnValue());
}
}
void ConvertToNumber::visit(const FunctionValue *object)
{
if (const FunctionValue *valueOfMember = value_cast<FunctionValue>(object->lookupMember("valueOf", ContextPtr()))) {
_result = value_cast<NumberValue>(valueOfMember->call(object)); // ### invoke convert-to-number?
_result = value_cast<NumberValue>(valueOfMember->returnValue());
}
}
@@ -1656,14 +1565,14 @@ void ConvertToString::visit(const StringValue *value)
void ConvertToString::visit(const ObjectValue *object)
{
if (const FunctionValue *toStringMember = value_cast<FunctionValue>(object->lookupMember("toString", ContextPtr()))) {
_result = value_cast<StringValue>(toStringMember->call(object)); // ### invoke convert-to-string?
_result = value_cast<StringValue>(toStringMember->returnValue());
}
}
void ConvertToString::visit(const FunctionValue *object)
{
if (const FunctionValue *toStringMember = value_cast<FunctionValue>(object->lookupMember("toString", ContextPtr()))) {
_result = value_cast<StringValue>(toStringMember->call(object)); // ### invoke convert-to-string?
_result = value_cast<StringValue>(toStringMember->returnValue());
}
}
@@ -1699,25 +1608,19 @@ void ConvertToObject::visit(const UndefinedValue *)
_result = _valueOwner->nullValue();
}
void ConvertToObject::visit(const NumberValue *value)
void ConvertToObject::visit(const NumberValue *)
{
ValueList actuals;
actuals.append(value);
_result = _valueOwner->numberCtor()->construct(actuals);
_result = _valueOwner->numberCtor()->returnValue();
}
void ConvertToObject::visit(const BooleanValue *value)
void ConvertToObject::visit(const BooleanValue *)
{
ValueList actuals;
actuals.append(value);
_result = _valueOwner->booleanCtor()->construct(actuals);
_result = _valueOwner->booleanCtor()->returnValue();
}
void ConvertToObject::visit(const StringValue *value)
void ConvertToObject::visit(const StringValue *)
{
ValueList actuals;
actuals.append(value);
_result = _valueOwner->stringCtor()->construct(actuals);
_result = _valueOwner->stringCtor()->returnValue();
}
void ConvertToObject::visit(const ObjectValue *object)