aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4object.cpp')
-rw-r--r--src/qml/jsruntime/qv4object.cpp293
1 files changed, 80 insertions, 213 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 94d5a74fe5..aa8e850aed 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -38,8 +38,6 @@
****************************************************************************/
#include "qv4object_p.h"
-#include "qv4jsir_p.h"
-#include "qv4isel_p.h"
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
@@ -51,6 +49,7 @@
#include "qv4identifier_p.h"
#include "qv4string_p.h"
#include "qv4identifiertable_p.h"
+#include "qv4jscall_p.h"
#include <stdint.h>
@@ -61,6 +60,8 @@ DEFINE_OBJECT_VTABLE(Object);
void Object::setInternalClass(InternalClass *ic)
{
d()->internalClass = ic;
+ if (ic->isUsedAsProto)
+ ic->updateProtoUsage(d());
Q_ASSERT(ic && ic->vtable);
uint nInline = d()->vtable()->nInlineProperties;
if (ic->size <= nInline)
@@ -86,6 +87,11 @@ void Object::setProperty(uint index, const Property *p)
setProperty(index + SetterOffset, p->set);
}
+void Heap::Object::setUsedAsProto()
+{
+ internalClass = internalClass->asProtoClass();
+}
+
bool Object::setPrototype(Object *proto)
{
Heap::Object *p = proto ? proto->d() : 0;
@@ -108,10 +114,9 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property
return Encode::undefined();
Scope scope(f->engine());
- ScopedCallData callData(scope);
- callData->thisObject = thisObject;
- f->call(scope, callData);
- return scope.result.asReturnedValue();
+ JSCallData jsCallData(scope);
+ *jsCallData->thisObject = thisObject;
+ return f->call(jsCallData);
}
bool Object::putValue(uint memberIndex, const Value &value)
@@ -127,25 +132,20 @@ bool Object::putValue(uint memberIndex, const Value &value)
if (set) {
Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
- ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = this;
- setter->call(scope, callData);
+ JSCallData jsCallData(scope, 1);
+ jsCallData->args[0] = value;
+ *jsCallData->thisObject = this;
+ setter->call(jsCallData);
return !ic->engine->hasException;
}
- goto reject;
+ return false;
}
if (!attrs.isWritable())
- goto reject;
+ return false;
setProperty(memberIndex, value);
return true;
-
- reject:
- if (engine()->current->strictMode)
- engine()->throwTypeError();
- return false;
}
void Object::defineDefaultProperty(const QString &name, const Value &value)
@@ -156,29 +156,29 @@ void Object::defineDefaultProperty(const QString &name, const Value &value)
defineDefaultProperty(s, value);
}
-void Object::defineDefaultProperty(const QString &name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount)
+void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
{
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, s, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(s, function);
}
-void Object::defineDefaultProperty(String *name, void (*code)(const BuiltinFunction *, Scope &, CallData *), int argumentCount)
+void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
{
ExecutionEngine *e = engine();
Scope scope(e);
ExecutionContext *global = e->rootContext();
- ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
+ ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, name, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
-void Object::defineAccessorProperty(const QString &name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
- void (*setter)(const BuiltinFunction *, Scope &, CallData *))
+void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
+ ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int))
{
ExecutionEngine *e = engine();
Scope scope(e);
@@ -186,18 +186,20 @@ void Object::defineAccessorProperty(const QString &name, void (*getter)(const Bu
defineAccessorProperty(s, getter, setter);
}
-void Object::defineAccessorProperty(String *name, void (*getter)(const BuiltinFunction *, Scope &, CallData *),
- void (*setter)(const BuiltinFunction *, Scope &, CallData *))
+void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
+ ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int))
{
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
ExecutionContext *global = v4->rootContext();
- p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
- p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
+ p->setGetter(ScopedFunctionObject(scope, (getter ? FunctionObject::createBuiltinFunction(global, name, getter) : 0)));
+ p->setSetter(ScopedFunctionObject(scope, (setter ? FunctionObject::createBuiltinFunction(global, name, setter) : 0)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
+
+
void Object::defineReadonlyProperty(const QString &name, const Value &value)
{
QV4::ExecutionEngine *e = engine();
@@ -224,9 +226,16 @@ void Object::defineReadonlyConfigurableProperty(String *name, const Value &value
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
-void Object::markObjects(Heap::Base *b, MarkStack *stack)
+void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
{
- Heap::Object *o = static_cast<Heap::Object *>(b);
+ Object *o = static_cast<Object *>(b);
+ if (o->memberData)
+ o->memberData->mark(stack);
+ if (o->arrayData) {
+ o->arrayData->setMarkBit();
+ if (o->arrayData->needsMark)
+ ArrayData::markObjects(o->arrayData, stack);
+ }
uint nInline = o->vtable()->nInlineProperties;
Value *v = reinterpret_cast<Value *>(o) + o->vtable()->inlinePropertyOffset;
const Value *end = v + nInline;
@@ -402,14 +411,14 @@ bool Object::hasOwnProperty(uint index) const
return false;
}
-void Object::construct(const Managed *m, Scope &scope, CallData *)
+ReturnedValue Object::callAsConstructor(const FunctionObject *f, const Value *, int)
{
- scope.result = static_cast<const Object *>(m)->engine()->throwTypeError();
+ return f->engine()->throwTypeError();
}
-void Object::call(const Managed *m, Scope &scope, CallData *)
+ReturnedValue Object::call(const FunctionObject *f, const Value *, const Value *, int)
{
- scope.result = static_cast<const Object *>(m)->engine()->throwTypeError();
+ return f->engine()->throwTypeError();
}
ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty)
@@ -472,98 +481,6 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-ReturnedValue Object::getLookup(const Managed *m, Lookup *l)
-{
- const Object *o = static_cast<const Object *>(m);
- PropertyAttributes attrs;
- ReturnedValue v = l->lookup(o, &attrs);
- if (v != Primitive::emptyValue().asReturnedValue()) {
- l->proto = l->classList[0]->prototype;
- if (attrs.isData()) {
- Q_ASSERT(l->classList[0] == o->internalClass());
- if (l->level == 0) {
- uint nInline = o->d()->vtable()->nInlineProperties;
- if (l->index < nInline)
- l->getter = Lookup::getter0Inline;
- else {
- l->index -= nInline;
- l->getter = Lookup::getter0MemberData;
- }
- }
- else if (l->level == 1)
- l->getter = Lookup::getter1;
- else if (l->level == 2)
- l->getter = Lookup::getter2;
- else
- l->getter = Lookup::getterFallback;
- return v;
- } else {
- if (l->level == 0)
- l->getter = Lookup::getterAccessor0;
- else if (l->level == 1)
- l->getter = Lookup::getterAccessor1;
- else if (l->level == 2)
- l->getter = Lookup::getterAccessor2;
- else
- l->getter = Lookup::getterFallback;
- return v;
- }
- }
- return Encode::undefined();
-}
-
-void Object::setLookup(Managed *m, Lookup *l, const Value &value)
-{
- Scope scope(static_cast<Object *>(m)->engine());
- ScopedObject o(scope, static_cast<Object *>(m));
- ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
-
- InternalClass *c = o->internalClass();
- uint idx = c->find(name);
- if (!o->isArrayObject() || idx != Heap::ArrayObject::LengthPropertyIndex) {
- if (idx != UINT_MAX && o->internalClass()->propertyData[idx].isData() && o->internalClass()->propertyData[idx].isWritable()) {
- l->classList[0] = o->internalClass();
- l->index = idx;
- l->setter = idx < o->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
- o->setProperty(idx, value);
- return;
- }
-
- if (idx != UINT_MAX) {
- o->putValue(idx, value);
- return;
- }
- }
-
- o->put(name, value);
-
- if (o->internalClass() == c)
- return;
- idx = o->internalClass()->find(name);
- if (idx == UINT_MAX)
- return;
- l->classList[0] = c;
- l->classList[3] = o->internalClass();
- l->index = idx;
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert0;
- return;
- }
- o = o->prototype();
- l->classList[1] = o->internalClass();
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert1;
- return;
- }
- o = o->prototype();
- l->classList[2] = o->internalClass();
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert2;
- return;
- }
- l->setter = Lookup::setterGeneric;
-}
-
void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
@@ -644,14 +561,13 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) const
name->makeIdentifier();
Identifier *id = name->identifier();
- Scope scope(engine());
- ScopedObject o(scope, this);
+ Heap::Object *o = d();
while (o) {
- uint idx = o->internalClass()->find(id);
+ uint idx = o->internalClass->find(id);
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(*o->propertyData(idx), o->internalClass()->propertyData.at(idx));
+ return getValue(*o->propertyData(idx), o->internalClass->propertyData.at(idx));
}
o = o->prototype();
@@ -725,9 +641,9 @@ bool Object::internalPut(String *name, const Value &value)
if (attrs.isAccessor()) {
if (memberIndex->as<FunctionObject>())
goto cont;
- goto reject;
+ return false;
} else if (!attrs.isWritable())
- goto reject;
+ return false;
else if (isArrayObject() && name->equals(engine->id_length())) {
bool ok;
uint l = value.asArrayLength(&ok);
@@ -737,14 +653,14 @@ bool Object::internalPut(String *name, const Value &value)
}
ok = setArrayLength(l);
if (!ok)
- goto reject;
+ return false;
} else {
memberIndex.set(engine, value);
}
return true;
} else if (!prototype()) {
if (!isExtensible())
- goto reject;
+ return false;
} else {
// clause 4
Scope scope(engine);
@@ -752,12 +668,12 @@ bool Object::internalPut(String *name, const Value &value)
if (!memberIndex.isNull()) {
if (attrs.isAccessor()) {
if (!memberIndex->as<FunctionObject>())
- goto reject;
+ return false;
} else if (!isExtensible() || !attrs.isWritable()) {
- goto reject;
+ return false;
}
} else if (!isExtensible()) {
- goto reject;
+ return false;
}
}
@@ -769,24 +685,15 @@ bool Object::internalPut(String *name, const Value &value)
Scope scope(engine);
ScopedFunctionObject setter(scope, *memberIndex);
- ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = this;
- setter->call(scope, callData);
- return !internalClass()->engine->hasException;
+ JSCallData jsCallData(scope, 1);
+ jsCallData->args[0] = value;
+ *jsCallData->thisObject = this;
+ setter->call(jsCallData);
+ return !engine->hasException;
}
insertMember(name, value);
return true;
-
- reject:
- // ### this should be removed once everything is ported to use Object::set()
- if (engine->current->strictMode) {
- QString message = QLatin1String("Cannot assign to read-only property \"") +
- name->toQString() + QLatin1Char('\"');
- engine->throwTypeError(message);
- }
- return false;
}
bool Object::internalPutIndexed(uint index, const Value &value)
@@ -802,7 +709,7 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (arrayIndex.isNull() && isStringObject()) {
if (index < static_cast<StringObject *>(this)->length())
// not writable
- goto reject;
+ return false;
}
// clause 1
@@ -810,15 +717,15 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (attrs.isAccessor()) {
if (arrayIndex->as<FunctionObject>())
goto cont;
- goto reject;
+ return false;
} else if (!attrs.isWritable())
- goto reject;
+ return false;
arrayIndex.set(engine, value);
return true;
} else if (!prototype()) {
if (!isExtensible())
- goto reject;
+ return false;
} else {
// clause 4
Scope scope(engine);
@@ -826,12 +733,12 @@ bool Object::internalPutIndexed(uint index, const Value &value)
if (!arrayIndex.isNull()) {
if (attrs.isAccessor()) {
if (!arrayIndex->as<FunctionObject>())
- goto reject;
+ return false;
} else if (!isExtensible() || !attrs.isWritable()) {
- goto reject;
+ return false;
}
} else if (!isExtensible()) {
- goto reject;
+ return false;
}
}
@@ -843,21 +750,15 @@ bool Object::internalPutIndexed(uint index, const Value &value)
Scope scope(engine);
ScopedFunctionObject setter(scope, *arrayIndex);
- ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = this;
- setter->call(scope, callData);
- return !internalClass()->engine->hasException;
+ JSCallData jsCallData(scope, 1);
+ jsCallData->args[0] = value;
+ *jsCallData->thisObject = this;
+ setter->call(jsCallData);
+ return !engine->hasException;
}
arraySet(index, value);
return true;
-
- reject:
- // ### this should be removed once everything is ported to use Object::setIndexed()
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
// Section 8.12.7
@@ -878,8 +779,6 @@ bool Object::internalDeleteProperty(String *name)
InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->current->strictMode)
- engine()->throwTypeError();
return false;
}
@@ -896,8 +795,6 @@ bool Object::internalDeleteIndexedProperty(uint index)
if (!ad || ad->vtable()->del(this, index))
return true;
- if (engine()->current->strictMode)
- engine()->throwTypeError();
return false;
}
@@ -921,7 +818,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
return true;
if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
- goto reject;
+ return false;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
bool ok;
@@ -938,7 +835,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
InternalClass::changeMember(this, engine->id_length(), cattrs);
}
if (!succeeded)
- goto reject;
+ return false;
return true;
}
@@ -948,7 +845,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
if (memberIndex == UINT_MAX) {
// clause 3
if (!isExtensible())
- goto reject;
+ return false;
// clause 4
ScopedProperty pd(scope);
pd->copy(p, attrs);
@@ -958,26 +855,18 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
}
return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
-reject:
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
// 15.4.5.1, 4b
if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
- goto reject;
+ return false;
if (ArgumentsObject::isNonStrictArgumentsObject(this))
return static_cast<ArgumentsObject *>(this)->defineOwnProperty(engine, index, p, attrs);
return defineOwnProperty2(engine, index, p, attrs);
-reject:
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
@@ -994,7 +883,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
if (!hasProperty) {
// clause 3
if (!isExtensible())
- goto reject;
+ return false;
// clause 4
Scope scope(engine);
ScopedProperty pp(scope);
@@ -1010,10 +899,6 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
}
return __defineOwnProperty__(engine, index, 0, p, attrs);
-reject:
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
@@ -1040,9 +925,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
// clause 7
if (!cattrs.isConfigurable()) {
if (attrs.isConfigurable())
- goto reject;
+ return false;
if (attrs.hasEnumerable() && attrs.isEnumerable() != cattrs.isEnumerable())
- goto reject;
+ return false;
}
// clause 8
@@ -1053,7 +938,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
if (cattrs.isData() != attrs.isData()) {
// 9a
if (!cattrs.isConfigurable())
- goto reject;
+ return false;
if (cattrs.isData()) {
// 9b
cattrs.setType(PropertyAttributes::Accessor);
@@ -1079,15 +964,15 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
} else if (cattrs.isData() && attrs.isData()) { // clause 10
if (!cattrs.isConfigurable() && !cattrs.isWritable()) {
if (attrs.isWritable() || !current->value.sameValue(p->value))
- goto reject;
+ return false;
}
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue())
- goto reject;
+ return false;
if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue())
- goto reject;
+ return false;
}
}
@@ -1102,10 +987,6 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *
arrayData()->setProperty(scope.engine, index, current);
}
return true;
- reject:
- if (engine->current->strictMode)
- engine->throwTypeError();
- return false;
}
@@ -1141,7 +1022,6 @@ void Object::copyArrayData(Object *other)
Heap::ArrayData *od = other->d()->arrayData;
Heap::ArrayData *dd = d()->arrayData;
dd->sparse = new SparseArray(*od->sparse);
- dd->freeList = od->freeList;
} else {
Heap::ArrayData *dd = d()->arrayData;
dd->values.size = other->d()->arrayData->values.size;
@@ -1257,19 +1137,6 @@ void Heap::ArrayObject::init(const QStringList &list)
a->setArrayLengthUnchecked(len);
}
-ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l)
-{
- Scope scope(static_cast<const Object *>(m)->engine());
- ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);
- if (name->equals(scope.engine->id_length())) {
- // special case, as the property is on the object itself
- l->getter = Lookup::arrayLengthGetter;
- const ArrayObject *a = static_cast<const ArrayObject *>(m);
- return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->asReturnedValue();
- }
- return Object::getLookup(m, l);
-}
-
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);