aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-11-14 09:54:00 +0100
committerLars Knoll <lars.knoll@qt.io>2017-11-27 11:10:04 +0000
commite6d17c8691bfafa033b82a4d81a9caf4a2fd1b85 (patch)
tree68a8774562cf291eb4350facfd7feece4dd77443
parentfca89004d75412dd378cc44ad79ed3c1e05c765b (diff)
Convert setters to use the id in InternalClass
Change-Id: I7f3acf96e998a41d60d33f98b243089b9ee40ff0 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp165
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h11
-rw-r--r--src/qml/jsruntime/qv4object.cpp54
-rw-r--r--src/qml/jsruntime/qv4object_p.h5
4 files changed, 102 insertions, 133 deletions
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index c690c59270..73ae4bf410 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -508,32 +508,81 @@ ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engi
return globalGetterGeneric(l, engine);
}
-bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value &value)
{
Scope scope(engine);
- ScopedObject o(scope, object);
- if (!o) {
- o = RuntimeHelpers::convertToObject(scope.engine, object);
- if (!o) // type error
- return false;
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
- return o->put(name, value);
+ ScopedString name(scope, scope.engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+
+ InternalClass *c = object->internalClass();
+ uint idx = c->find(name);
+ if (idx != UINT_MAX) {
+ if (object->isArrayObject() && idx == Heap::ArrayObject::LengthPropertyIndex) {
+ setter = arrayLengthSetter;
+ return setter(this, engine, *object, value);
+ } else if (object->internalClass()->propertyData[idx].isData() && object->internalClass()->propertyData[idx].isWritable()) {
+ objectLookup.ic = object->internalClass();
+ objectLookup.offset = idx;
+ setter = idx < object->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
+ return setter(this, engine, *object, value);
+ } else {
+ // ### handle setter
+ setter = setterFallback;
+ }
+ return setter(this, engine, *object, value);
}
- return o->setLookup(l, value);
+
+ insertionLookup.icIdentifier = c->id;
+ if (!object->put(name, value)) {
+ setter = Lookup::setterFallback;
+ return false;
+ }
+
+ if (object->internalClass() == c) {
+ // ### setter in the prototype, should handle this
+ setter = setterFallback;
+ return true;
+ }
+ idx = object->internalClass()->find(name);
+ if (idx == UINT_MAX) { // ### can this even happen?
+ setter = setterFallback;
+ return false;
+ }
+ insertionLookup.newClass = object->internalClass();
+ insertionLookup.offset = idx;
+ setter = setterInsert;
+ return true;
+}
+
+bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+{
+ if (object.isObject())
+ return l->resolveSetter(engine, static_cast<Object *>(&object), value);
+
+ Scope scope(engine);
+ ScopedObject o(scope, RuntimeHelpers::convertToObject(scope.engine, object));
+ if (!o) // type error
+ return false;
+ ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
+ return o->put(name, value);
}
bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Lookup l1 = *l;
+ Lookup first = *l;
+ Lookup second = *l;
- if (Object *o = object.as<Object>()) {
- if (!o->setLookup(l, value))
+ if (object.isObject()) {
+ if (!l->resolveSetter(engine, static_cast<Object *>(&object), value)) {
+ l->setter = setterFallback;
return false;
+ }
if (l->setter == Lookup::setter0 || l->setter == Lookup::setter0Inline) {
+ l->objectLookupTwoClasses.ic = first.objectLookup.ic;
+ l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
+ l->objectLookupTwoClasses.offset = first.objectLookup.offset;
+ l->objectLookupTwoClasses.offset2 = second.objectLookup.offset;
l->setter = setter0setter0;
- l->classList[1] = l1.classList[0];
- l->index2 = l1.index;
return true;
}
}
@@ -555,9 +604,9 @@ bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, c
bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass() == l->classList[0]) {
- o->setProperty(engine, l->index, value);
+ Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
+ if (o && o->internalClass == l->objectLookup.ic) {
+ o->setProperty(engine, l->objectLookup.offset, value);
return true;
}
@@ -566,39 +615,25 @@ bool Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Va
bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass() == l->classList[0]) {
- o->d()->setInlineProperty(engine, l->index, value);
+ Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
+ if (o && o->internalClass == l->objectLookup.ic) {
+ o->setInlineProperty(engine, l->objectLookup.offset, value);
return true;
}
return setterTwoClasses(l, engine, object, value);
}
-bool Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
-{
- Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass() == l->classList[0]) {
- Q_ASSERT(!o->prototype());
- o->setInternalClass(l->classList[3]);
- o->setProperty(l->index, value);
- return true;
- }
-
- l->setter = setterFallback;
- return setterFallback(l, engine, object, value);
-}
-
-bool Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass() == l->classList[0]) {
- Heap::Object *p = o->prototype();
- Q_ASSERT(p);
- if (p->internalClass == l->classList[1]) {
- Q_ASSERT(!p->prototype());
- o->setInternalClass(l->classList[3]);
- o->setProperty(l->index, value);
+ Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
+ if (o) {
+ if (o->internalClass == l->objectLookupTwoClasses.ic) {
+ o->setProperty(engine, l->objectLookupTwoClasses.offset, value);
+ return true;
+ }
+ if (o->internalClass == l->objectLookupTwoClasses.ic2) {
+ o->setProperty(engine, l->objectLookupTwoClasses.offset2, value);
return true;
}
}
@@ -607,44 +642,32 @@ bool Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, co
return setterFallback(l, engine, object, value);
}
-bool Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
Object *o = static_cast<Object *>(object.managed());
- if (o && o->internalClass() == l->classList[0]) {
- Heap::Object *p = o->prototype();
- Q_ASSERT(p);
- if (p->internalClass == l->classList[1]) {
- p = p->prototype();
- Q_ASSERT(p);
- if (p->internalClass == l->classList[2]) {
- Q_ASSERT(!p->prototype());
- o->setInternalClass(l->classList[3]);
- o->setProperty(l->index, value);
- return true;
- }
- }
+ if (o && o->internalClass()->id == l->insertionLookup.icIdentifier) {
+ o->setInternalClass(l->insertionLookup.newClass);
+ o->d()->setProperty(engine, l->insertionLookup.offset, value);
+ return true;
}
l->setter = setterFallback;
return setterFallback(l, engine, object, value);
}
-bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
+bool Lookup::arrayLengthSetter(Lookup *, ExecutionEngine *engine, Value &object, const Value &value)
{
- Object *o = static_cast<Object *>(object.managed());
- if (o) {
- if (o->internalClass() == l->classList[0]) {
- o->setProperty(l->index, value);
- return true;
- }
- if (o->internalClass() == l->classList[1]) {
- o->setProperty(l->index2, value);
- return true;
- }
+ Q_ASSERT(object.isObject() && static_cast<Object &>(object).isArrayObject());
+ bool ok;
+ uint len = value.asArrayLength(&ok);
+ if (!ok) {
+ engine->throwRangeError(value);
+ return false;
}
-
- l->setter = setterFallback;
- return setterFallback(l, engine, object, value);
+ ok = static_cast<Object &>(object).setArrayLength(len);
+ if (!ok)
+ return false;
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 450d2d4364..5c58d2f669 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -99,6 +99,11 @@ struct Lookup {
unsigned type;
Heap::Object *proto;
} primitiveLookup;
+ struct {
+ InternalClass *newClass;
+ int icIdentifier;
+ int offset;
+ } insertionLookup;
InternalClass *classList[Size];
};
@@ -137,15 +142,15 @@ struct Lookup {
static ReturnedValue globalGetterProto(Lookup *l, ExecutionEngine *engine);
static ReturnedValue globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine);
+ bool resolveSetter(ExecutionEngine *engine, Object *object, const Value &value);
static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static bool setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static bool setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
- static bool setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
+ static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs);
ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index e7368edad2..b4034fd196 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -528,60 +528,6 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-bool 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->currentStackFrame->v4Function->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 true;
- }
-
- if (idx != UINT_MAX)
- return o->putValue(idx, value);
- }
-
- if (!o->put(name, value)) {
- l->setter = Lookup::setterFallback;
- return false;
- }
-
- if (o->internalClass() == c)
- return true;
- idx = o->internalClass()->find(name);
- if (idx == UINT_MAX) // ### can this even happen?
- return false;
- l->classList[0] = c;
- l->classList[3] = o->internalClass();
- l->index = idx;
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert0;
- return true;
- }
- o = o->prototype();
- l->classList[1] = o->internalClass();
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert1;
- return true;
- }
- o = o->prototype();
- l->classList[2] = o->internalClass();
- if (!o->prototype()) {
- l->setter = Lookup::setterInsert2;
- return true;
- }
- l->setter = Lookup::setterGeneric;
- return true;
-}
-
void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 4f4c60408e..66177617f7 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -172,7 +172,6 @@ struct ObjectVTable
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- bool (*setLookup)(Managed *m, Lookup *l, const Value &v);
uint (*getLength)(const Managed *m);
void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var);
@@ -192,7 +191,6 @@ const QV4::ObjectVTable classname::static_vtbl = \
queryIndexed, \
deleteProperty, \
deleteIndexedProperty, \
- setLookup, \
getLength, \
advanceIterator, \
instanceOf \
@@ -414,8 +412,6 @@ public:
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
- bool setLookup(Lookup *l, const Value &v)
- { return vtable()->setLookup(this, l, v); }
void advanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
@@ -433,7 +429,6 @@ protected:
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static bool setLookup(Managed *m, Lookup *l, const Value &v);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);