aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4compileddata.cpp13
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
-rw-r--r--src/qml/compiler/qv4compiler.cpp9
-rw-r--r--src/qml/compiler/qv4compiler_p.h1
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp102
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h12
-rw-r--r--src/qml/compiler/qv4isel_p.h1
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp57
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h5
-rw-r--r--src/qml/jsruntime/qv4object_p.h2
10 files changed, 97 insertions, 108 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 717e7f4ba2..367ada194b 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -95,21 +95,24 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
for (uint i = 0; i < data->lookupTableSize; ++i) {
QV4::Lookup *l = runtimeLookups + i;
- if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Getter)
+ Lookup::Type type = Lookup::Type(compiledLookups[i].type_and_flags);
+ if (type == CompiledData::Lookup::Type_Getter)
l->getter = QV4::Lookup::getterGeneric;
- else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Setter)
+ else if (type == CompiledData::Lookup::Type_Setter)
l->setter = QV4::Lookup::setterGeneric;
- else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_GlobalGetter)
+ else if (type == CompiledData::Lookup::Type_GlobalGetter)
l->globalGetter = QV4::Lookup::globalGetterGeneric;
- else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_IndexedGetter)
+ else if (type == CompiledData::Lookup::Type_IndexedGetter)
l->indexedGetter = QV4::Lookup::indexedGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_IndexedSetter)
+ l->indexedSetter = QV4::Lookup::indexedSetterGeneric;
for (int j = 0; j < QV4::Lookup::Size; ++j)
l->classList[j] = 0;
l->level = -1;
l->index = UINT_MAX;
l->name = runtimeStrings[compiledLookups[i].nameIndex].asString();
- if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_IndexedGetter)
+ if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter)
l->engine = engine;
}
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 29b6fd564e..451bf4216a 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -114,7 +114,8 @@ struct Lookup
Type_Getter = 0x0,
Type_Setter = 0x1,
Type_GlobalGetter = 2,
- Type_IndexedGetter = 3
+ Type_IndexedGetter = 3,
+ Type_IndexedSetter = 4
};
quint32 type_and_flags;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index d18c43a969..7fb10d5f42 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -81,6 +81,15 @@ uint QV4::Compiler::JSUnitGenerator::registerIndexedGetterLookup()
return lookups.size() - 1;
}
+uint QV4::Compiler::JSUnitGenerator::registerIndexedSetterLookup()
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_IndexedSetter;
+ l.nameIndex = 0;
+ lookups << l;
+ return lookups.size() - 1;
+}
+
uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
{
CompiledData::Lookup l;
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 4779b5d3c4..6baefae7b7 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -71,6 +71,7 @@ struct Q_QML_EXPORT JSUnitGenerator {
uint registerSetterLookup(const QString &name);
uint registerGlobalGetterLookup(const QString &name);
uint registerIndexedGetterLookup();
+ uint registerIndexedSetterLookup();
int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index b8b16a4151..427a6b7d56 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -1023,107 +1023,19 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
return;
}
-#if 0 // QT_POINTER_SIZE == 8
- V4IR::Temp *tbase = base->asTemp();
- V4IR::Temp *tindex = index->asTemp();
- if (tbase && tindex &&
- tbase->kind != V4IR::Temp::PhysicalRegister) {
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
- _as->load64(addr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsManaged_Shift), Assembler::ReturnValueRegister);
- Assembler::Jump notManaged = _as->branch64(Assembler::NotEqual, Assembler::ReturnValueRegister, Assembler::TrustedImm64(0));
- // check whether we have an object with a simple array
- // ### need to check we have an object first!
- Assembler::Address managedType(Assembler::ScratchRegister, qOffsetOf(QV4::Object, arrayData) + qOffsetOf(QV4::ArrayData, flags));
- _as->load8(managedType, Assembler::ReturnValueRegister);
- _as->and32(Assembler::TrustedImm32(QV4::ArrayData::SimpleArray), Assembler::ReturnValueRegister);
- Assembler::Jump notSimple = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0));
-
- bool needNegativeCheck = false;
- Assembler::Jump fallback, fallback2;
- if (tindex->kind == V4IR::Temp::PhysicalRegister) {
- if (tindex->type == V4IR::SInt32Type) {
- fallback = _as->branch32(Assembler::LessThan, (Assembler::RegisterID)tindex->index, Assembler::TrustedImm32(0));
- _as->move((Assembler::RegisterID) tindex->index, Assembler::ScratchRegister);
- needNegativeCheck = true;
- } else {
- // double, convert and check if it's a int
- fallback2 = _as->branchTruncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister);
- _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr0);
- fallback = _as->branchDouble(Assembler::DoubleNotEqual, Assembler::FPGpr0, (Assembler::FPRegisterID) tindex->index);
- }
- } else {
- Assembler::Pointer indexAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, tindex);
- _as->load64(indexAddr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsNumber_Shift), Assembler::ReturnValueRegister);
- Assembler::Jump isInteger = _as->branch64(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm64(1));
-
- // other type, convert to double and check if it's a int
- // this check is ok to do even if the type is something else than a double, as
- // that would result in a NaN
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ReturnValueRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
- fallback2 = _as->branchTruncateDoubleToUint32(Assembler::FPGpr0, Assembler::ScratchRegister);
- _as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr1);
- fallback = _as->branchDouble(Assembler::DoubleNotEqualOrUnordered, Assembler::FPGpr0, Assembler::FPGpr1);
-
- isInteger.link(_as);
- _as->or32(Assembler::TrustedImm32(0), Assembler::ScratchRegister);
- needNegativeCheck = true;
- }
-
- // get data, ScratchRegister holds index
- addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
- _as->load64(addr, Assembler::ReturnValueRegister);
- Address dataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData) + qOffsetOf(ArrayData, length));
- Assembler::Jump outOfRange;
- if (needNegativeCheck)
- outOfRange = _as->branch32(Assembler::LessThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
- Assembler::Jump outOfRange2 = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, dataLen);
- Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData) + qOffsetOf(ArrayData, data));
- _as->load64(arrayData, Assembler::ReturnValueRegister);
- Q_ASSERT(sizeof(Property) == (1<<4));
- _as->lshift64(Assembler::TrustedImm32(4), Assembler::ScratchRegister);
- _as->add64(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
- Address value(Assembler::ScratchRegister, qOffsetOf(Property, value));
- _as->load64(value, Assembler::ReturnValueRegister);
-
- // check that the value is not empty
- _as->move(Assembler::ReturnValueRegister, Assembler::ScratchRegister);
- _as->urshift64(Assembler::TrustedImm32(32), Assembler::ScratchRegister);
- Assembler::Jump emptyValue = _as->branch32(Assembler::Equal, Assembler::TrustedImm32(QV4::Value::Empty_Type), Assembler::ScratchRegister);
- _as->storeReturnValue(target);
-
- Assembler::Jump done = _as->jump();
-
- emptyValue.link(_as);
- if (outOfRange.isSet())
- outOfRange.link(_as);
- outOfRange2.link(_as);
- if (fallback.isSet())
- fallback.link(_as);
- if (fallback2.isSet())
- fallback2.link(_as);
- notSimple.link(_as);
- notManaged.link(_as);
-
- generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
-
- done.link(_as);
- return;
- }
-#endif
-
generateFunctionCall(target, __qmljs_get_element, Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex)
{
+ if (useFastLookups) {
+ uint lookup = registerIndexedSetterLookup();
+ generateLookupCall(Assembler::Void, lookup, qOffsetOf(QV4::Lookup, indexedSetter),
+ Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
+ Assembler::PointerToValue(source));
+ return;
+ }
generateFunctionCall(Assembler::Void, __qmljs_set_element, Assembler::ContextRegister,
Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
Assembler::PointerToValue(source));
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index a146220015..f22e0930e3 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -1580,8 +1580,8 @@ private:
int prepareVariableArguments(V4IR::ExprList* args);
int prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject);
- template <typename Retval, typename Arg1, typename Arg2>
- void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
+ template <typename Retval, typename Arg1, typename Arg2, typename Arg3>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
Assembler::RegisterID lookupRegister;
#if CPU(ARM)
@@ -1595,13 +1595,13 @@ private:
getterSetter.offset += getterSetterOffset;
_as->generateFunctionCallImp(retval, "lookup getter/setter",
- RelativeCall(getterSetter), lookupAddr, arg1, arg2);
+ RelativeCall(getterSetter), lookupAddr, arg1, arg2, arg3);
}
- template <typename Arg1>
- void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1)
+ template <typename Retval, typename Arg1, typename Arg2>
+ void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
{
- generateLookupCall(index, getterSetterOffset, arg1, Assembler::VoidType());
+ generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, Assembler::VoidType());
}
/// This is a temporary method, and will be removed when registers are fully supported.
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 6f33098172..57222672b9 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -73,6 +73,7 @@ public:
int registerString(const QString &str) { return jsGenerator->registerString(str); }
uint registerIndexedGetterLookup() { return jsGenerator->registerIndexedGetterLookup(); }
+ uint registerIndexedSetterLookup() { return jsGenerator->registerIndexedSetterLookup(); }
uint registerGetterLookup(const QString &name) { return jsGenerator->registerGetterLookup(name); }
uint registerSetterLookup(const QString &name) { return jsGenerator->registerSetterLookup(name); }
uint registerGlobalGetterLookup(const QString &name) { return jsGenerator->registerGlobalGetterLookup(name); }
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index c9d22523a9..4a75272843 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -180,6 +180,63 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, c
return indexedGetterFallback(l, object, index);
}
+void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
+{
+ if (object->isObject()) {
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
+ l->indexedSetter = indexedSetterObjectInt;
+ indexedSetterObjectInt(l, object, index, v);
+ return;
+ }
+ }
+ indexedSetterFallback(l, object, index, v);
+}
+
+void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value)
+{
+ ExecutionContext *ctx = l->engine->currentContext();
+ Scope scope(ctx);
+ ScopedObject o(scope, object->toObject(ctx));
+ if (scope.engine->hasException)
+ return;
+
+ uint idx = index->asArrayIndex();
+ if (idx < UINT_MAX) {
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
+ if (s && idx < s->len && !s->data[idx].isEmpty()) {
+ s->data[idx] = value;
+ return;
+ }
+ }
+ o->putIndexed(idx, value);
+ return;
+ }
+
+ ScopedString name(scope, index->toString(ctx));
+ o->put(name, value);
+}
+
+void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
+{
+ uint idx = index->asArrayIndex();
+ if (idx == UINT_MAX || !object->isObject()) {
+ indexedSetterGeneric(l, object, index, v);
+ return;
+ }
+
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
+ if (idx < s->len && !s->data[idx].isEmpty()) {
+ s->data[idx] = v;
+ return;
+ }
+ }
+ indexedSetterFallback(l, object, index, v);
+}
+
ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
{
if (Object *o = object->asObject())
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 50874411de..7f107bf8eb 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -56,6 +56,7 @@ struct Lookup {
enum { Size = 4 };
union {
ReturnedValue (*indexedGetter)(Lookup *l, const ValueRef object, const ValueRef index);
+ void (*indexedSetter)(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
ReturnedValue (*getter)(Lookup *l, const ValueRef object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionContext *ctx);
void (*setter)(Lookup *l, const ValueRef object, const ValueRef v);
@@ -78,6 +79,10 @@ struct Lookup {
static ReturnedValue indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index);
static ReturnedValue indexedGetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index);
+ static void indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
+ static void indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value);
+ static void indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
+
static ReturnedValue getterGeneric(Lookup *l, const ValueRef object);
static ReturnedValue getter0(Lookup *l, const ValueRef object);
static ReturnedValue getter1(Lookup *l, const ValueRef object);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index ca54388359..7541178dc1 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -206,7 +206,7 @@ public:
void push_back(const ValueRef v);
ArrayData::Type arrayType() const {
- return arrayData ? (ArrayData::Type)arrayData->type : ArrayData::Simple;
+ return arrayData ? arrayData->type : ArrayData::Simple;
}
// ### remove me
void setArrayType(ArrayData::Type t) {