Add subtypes to String
authorLars Knoll <lars.knoll@digia.com>
Wed, 30 Jan 2013 12:04:16 +0000 (13:04 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Wed, 30 Jan 2013 13:10:30 +0000 (14:10 +0100)
This allows to store the full array index in the string,
as well as to optimise identifiers going forward.

Change-Id: I08974a5ee1149869ecfb635932bf54026d2bbab4
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/v4/qv4managed.h
src/v4/qv4string.cpp
src/v4/qv4string.h

index 8252fd6..7f36c83 100644 (file)
@@ -89,7 +89,10 @@ protected:
         , strictMode(0)
         , type(Type_Invalid)
         , subtype(0)
+        , stringIdentifier(0)
+#if CPU(X86_64)
         , unused(0)
+#endif
     {}
     virtual ~Managed();
 
@@ -156,12 +159,11 @@ protected:
             quintptr needsActivation : 1; // used by FunctionObject
             quintptr usesArgumentsObject : 1; // used by FunctionObject
             quintptr strictMode : 1; // used by FunctionObject
-            quintptr type : 8;
-            quintptr subtype : 8;
+            quintptr type : 5;
+            mutable quintptr subtype : 3;
+            quintptr stringIdentifier : 16;
 #if CPU(X86_64)
-            quintptr unused  : 40;
-#else
-            quintptr unused  : 8;
+            quintptr unused  : 32;
 #endif
         };
     };
index 6e0c14d..cdadbe7 100644 (file)
@@ -46,8 +46,9 @@
 namespace QQmlJS {
 namespace VM {
 
-static uint toArrayIndex(const QChar *ch, const QChar *end)
+static uint toArrayIndex(const QChar *ch, const QChar *end, bool *ok)
 {
+    *ok = false;
     uint i = ch->unicode() - '0';
     if (i > 9)
         return String::InvalidArrayIndex;
@@ -67,26 +68,17 @@ static uint toArrayIndex(const QChar *ch, const QChar *end)
         i = n;
         ++ch;
     }
+    *ok = true;
     return i;
 }
 
-uint String::asArrayIndexSlow() const
-{
-    if (stringHash < LargestHashedArrayIndex)
-        return stringHash;
-
-    const QChar *ch = _text.constData();
-    const QChar *end = ch + _text.length();
-    return toArrayIndex(ch, end);
-}
-
 uint String::toUInt(bool *ok) const
 {
     *ok = true;
 
-    if (stringHash == InvalidHashValue)
+    if (subtype == StringType_Unknown)
         createHashValue();
-    if (stringHash < LargestHashedArrayIndex)
+    if (subtype == StringType_ArrayIndex)
         return stringHash;
 
     double d = __qmljs_string_to_number(this);
@@ -102,11 +94,11 @@ void String::createHashValue() const
     const QChar *ch = _text.constData();
     const QChar *end = ch + _text.length();
 
-    // array indices get their number as hash value, for large numbers we set to INT_MAX
-    stringHash = toArrayIndex(ch, end);
-    if (stringHash < UINT_MAX) {
-        if (stringHash > INT_MAX)
-            stringHash = INT_MAX;
+    // array indices get their number as hash value
+    bool ok;
+    stringHash = toArrayIndex(ch, end, &ok);
+    if (ok) {
+        subtype = StringType_ArrayIndex;
         return;
     }
 
@@ -116,8 +108,8 @@ void String::createHashValue() const
         ++ch;
     }
 
-    // set highest bit to mark it as a non number
-    stringHash = h | 0xf0000000;
+    stringHash = h;
+    subtype = StringType_Regular;
 }
 
 }
index 958e6e1..2df221e 100644 (file)
@@ -48,15 +48,25 @@ namespace QQmlJS {
 namespace VM {
 
 struct String : public Managed {
+    enum StringType {
+        StringType_Unknown,
+        StringType_ArrayIndex,
+        StringType_Regular,
+        StringType_Identifier,
+    };
+
     String(const QString &text)
-        : _text(text), stringHash(0)
-    { type = Type_String; stringHash = InvalidHashValue; }
+        : _text(text), stringHash(InvalidHashValue)
+    { type = Type_String; subtype = StringType_Unknown; }
 
     inline bool isEqualTo(const String *other) const {
         if (this == other)
             return true;
-        else if (other && hashValue() == other->hashValue())
+        else if (hashValue() == other->hashValue()) {
+            if (subtype == StringType_ArrayIndex && other->subtype == StringType_ArrayIndex)
+                return true;
             return toQString() == other->toQString();
+        }
         return false;
     }
 
@@ -65,26 +75,22 @@ struct String : public Managed {
     }
 
     inline unsigned hashValue() const {
-        if (stringHash == InvalidHashValue)
+        if (subtype == StringType_Unknown)
             createHashValue();
 
         return stringHash;
     }
     enum {
         InvalidArrayIndex = 0xffffffff,
-        LargestHashedArrayIndex = 0x7fffffff,
         InvalidHashValue  = 0xffffffff
     };
     uint asArrayIndex() const {
-        if (stringHash == InvalidHashValue)
+        if (subtype == StringType_Unknown)
             createHashValue();
-        if (stringHash > LargestHashedArrayIndex)
-            return InvalidArrayIndex;
-        if (stringHash < LargestHashedArrayIndex)
+        if (subtype == StringType_ArrayIndex)
             return stringHash;
-        return asArrayIndexSlow();
+        return UINT_MAX;
     }
-    uint asArrayIndexSlow() const;
     uint toUInt(bool *ok) const;
 
 private: