From 8c322d89ee13f15141f3115dcb5ee9567270ba32 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 9 Dec 2016 14:46:49 +0100 Subject: Some smaller optimizations for indexed property access Saves around 1% of instructions on crypto.js Change-Id: Iccef08b204e6e752d827242baf156efd9a4d58a7 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4lookup.cpp | 55 ++++++++++++++++++++++++----------------- src/qml/jsruntime/qv4value_p.h | 15 +++++++++++ 2 files changed, 47 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 0b0b2685b3..8d322e69d1 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -118,7 +118,8 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs 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; return indexedGetterObjectInt(l, object, index); } @@ -129,11 +130,12 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons { Q_UNUSED(l); Scope scope(l->engine); - uint idx = index.asArrayIndex(); + uint idx; + bool isInt = index.asArrayIndex(idx); ScopedObject o(scope, object); if (!o) { - if (idx < UINT_MAX) { + if (isInt) { if (const String *str = object.as()) { if (idx >= (uint)str->toQString().length()) { return Encode::undefined(); @@ -153,7 +155,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons return Encode::undefined(); } - if (idx < UINT_MAX) { + if (isInt) { if (o->d()->arrayData && !o->d()->arrayData->attrs) { ScopedValue v(scope, Scoped(scope, o->arrayData())->get(idx)); 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) { - uint idx = index.asArrayIndex(); - if (idx != UINT_MAX) { - if (Object *o = object.objectValue()) { - if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { - Heap::SimpleArrayData *s = o->d()->arrayData.cast(); - if (idx < s->len) - if (!s->data(idx).isEmpty()) - return s->data(idx).asReturnedValue(); + uint idx; + if (index.asArrayIndex(idx)) { + if (Heap::Base *b = object.heapObject()) { + if (b->vtable()->isObject) { + Heap::Object *o = static_cast(b); + if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { + Heap::SimpleArrayData *s = o->arrayData.cast(); + 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) { 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; indexedSetterObjectInt(l, object, index, v); return; @@ -207,8 +213,8 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value & if (scope.engine->hasException) return; - uint idx = index.asArrayIndex(); - if (idx < UINT_MAX) { + uint idx; + if (index.asArrayIndex(idx)) { if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->d()->arrayData.cast(); 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) { - uint idx = index.asArrayIndex(); - if (idx != UINT_MAX) { - if (Object *o = object.objectValue()) { - if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { - Heap::SimpleArrayData *s = o->d()->arrayData.cast(); - if (idx < s->len) { - s->data(idx) = v; - return; + uint idx; + if (index.asArrayIndex(idx)) { + if (Heap::Base *b = object.heapObject()) { + if (b->vtable()->isObject) { + Heap::Object *o = static_cast(b); + if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { + Heap::SimpleArrayData *s = o->arrayData.cast(); + if (idx < s->len) { + s->data(idx) = v; + return; + } } } } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index e59ab9af0b..816b8fb11b 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -453,6 +453,7 @@ public: } inline uint asArrayIndex() const; + inline bool asArrayIndex(uint &idx) const; #ifndef V4_BOOTSTRAP uint asArrayLength(bool *ok) const; #endif @@ -531,6 +532,20 @@ inline uint Value::asArrayIndex() const return UINT_MAX; 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 inline -- cgit v1.2.3