Some smaller optimizations for indexed property access

Saves around 1% of instructions on crypto.js

Change-Id: Iccef08b204e6e752d827242baf156efd9a4d58a7
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Lars Knoll 2016-12-09 14:46:49 +01:00
parent d3bff5843b
commit 8c322d89ee
2 changed files with 47 additions and 23 deletions

View File

@ -118,7 +118,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs
ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const Value &object, const Value &index) ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const Value &object, const Value &index)
{ {
if (object.isObject() && index.asArrayIndex() < UINT_MAX) { uint idx;
if (object.isObject() && index.asArrayIndex(idx)) {
l->indexedGetter = indexedGetterObjectInt; l->indexedGetter = indexedGetterObjectInt;
return indexedGetterObjectInt(l, object, index); return indexedGetterObjectInt(l, object, index);
} }
@ -129,11 +130,12 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
{ {
Q_UNUSED(l); Q_UNUSED(l);
Scope scope(l->engine); Scope scope(l->engine);
uint idx = index.asArrayIndex(); uint idx;
bool isInt = index.asArrayIndex(idx);
ScopedObject o(scope, object); ScopedObject o(scope, object);
if (!o) { if (!o) {
if (idx < UINT_MAX) { if (isInt) {
if (const String *str = object.as<String>()) { if (const String *str = object.as<String>()) {
if (idx >= (uint)str->toQString().length()) { if (idx >= (uint)str->toQString().length()) {
return Encode::undefined(); return Encode::undefined();
@ -153,7 +155,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
return Encode::undefined(); return Encode::undefined();
} }
if (idx < UINT_MAX) { if (isInt) {
if (o->d()->arrayData && !o->d()->arrayData->attrs) { if (o->d()->arrayData && !o->d()->arrayData->attrs) {
ScopedValue v(scope, Scoped<ArrayData>(scope, o->arrayData())->get(idx)); ScopedValue v(scope, Scoped<ArrayData>(scope, o->arrayData())->get(idx));
if (!v->isEmpty()) if (!v->isEmpty())
@ -173,14 +175,17 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons
ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index) ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, const Value &index)
{ {
uint idx = index.asArrayIndex(); uint idx;
if (idx != UINT_MAX) { if (index.asArrayIndex(idx)) {
if (Object *o = object.objectValue()) { if (Heap::Base *b = object.heapObject()) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { if (b->vtable()->isObject) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Heap::Object *o = static_cast<Heap::Object *>(b);
if (idx < s->len) if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
if (!s->data(idx).isEmpty()) Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
return s->data(idx).asReturnedValue(); if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
}
} }
} }
} }
@ -191,7 +196,8 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con
void Lookup::indexedSetterGeneric(Lookup *l, const Value &object, const Value &index, const Value &v) void Lookup::indexedSetterGeneric(Lookup *l, const Value &object, const Value &index, const Value &v)
{ {
if (Object *o = object.objectValue()) { if (Object *o = object.objectValue()) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple && index.asArrayIndex() < UINT_MAX) { uint idx;
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple && index.asArrayIndex(idx)) {
l->indexedSetter = indexedSetterObjectInt; l->indexedSetter = indexedSetterObjectInt;
indexedSetterObjectInt(l, object, index, v); indexedSetterObjectInt(l, object, index, v);
return; return;
@ -207,8 +213,8 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
if (scope.engine->hasException) if (scope.engine->hasException)
return; return;
uint idx = index.asArrayIndex(); uint idx;
if (idx < UINT_MAX) { if (index.asArrayIndex(idx)) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>();
if (idx < s->len) { if (idx < s->len) {
@ -226,14 +232,17 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value &
void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v) void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value &index, const Value &v)
{ {
uint idx = index.asArrayIndex(); uint idx;
if (idx != UINT_MAX) { if (index.asArrayIndex(idx)) {
if (Object *o = object.objectValue()) { if (Heap::Base *b = object.heapObject()) {
if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { if (b->vtable()->isObject) {
Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Heap::Object *o = static_cast<Heap::Object *>(b);
if (idx < s->len) { if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) {
s->data(idx) = v; Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>();
return; if (idx < s->len) {
s->data(idx) = v;
return;
}
} }
} }
} }

View File

@ -453,6 +453,7 @@ public:
} }
inline uint asArrayIndex() const; inline uint asArrayIndex() const;
inline bool asArrayIndex(uint &idx) const;
#ifndef V4_BOOTSTRAP #ifndef V4_BOOTSTRAP
uint asArrayLength(bool *ok) const; uint asArrayLength(bool *ok) const;
#endif #endif
@ -531,6 +532,20 @@ inline uint Value::asArrayIndex() const
return UINT_MAX; return UINT_MAX;
return idx; return idx;
} }
inline bool Value::asArrayIndex(uint &idx) const
{
if (!isDouble()) {
if (isInteger() && int_32() >= 0) {
idx = (uint)int_32();
return true;
}
return false;
}
double d = doubleValue();
idx = (uint)d;
return (idx == d);
}
#endif #endif
inline inline