Changeset 47622 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Aug 20, 2009, 10:41:54 PM (16 years ago)
Author:
[email protected]
Message:

Added a number => string cache.

Patch by Geoffrey Garen <[email protected]> on 2009-08-20
Reviewed by Maciej Stachowiak.

1.07x faster on v8 (1.7x faster on v8-splay).
1.004x faster on SunSpider.

  • runtime/JSCell.h: Moved JSValue::toString to JSString.h.
  • runtime/JSGlobalData.h: Holds the cache.
  • runtime/JSNumberCell.cpp:

(JSC::JSNumberCell::toString):
(JSC::JSNumberCell::toThisString): Removed -0 special case.
UString handles this now, since too many clients were
special-casing it.

  • runtime/JSString.h:

(JSC::JSValue::toString): Use the cache when converting
an int or double to string.

  • runtime/Operations.h:

(JSC::concatenateStrings): Call toString to take advantage
of the cache.

  • runtime/SmallStrings.h:

(JSC::NumericStrings::add):
(JSC::NumericStrings::lookup): The cache.

  • runtime/UString.cpp:

(JSC::UString::from): Added -0 special case mentioned above.
Removed appendNumeric because it's mutually exclusive with the
cache.

Location:
trunk/JavaScriptCore/runtime
Files:
7 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSCell.h

    r47288 r47622  
    316316    }
    317317
    318     inline UString JSValue::toString(ExecState* exec) const
    319     {
    320         if (isCell())
    321             return asCell()->toString(exec);
    322         if (isInt32())
    323             return UString::from(asInt32());
    324         if (isDouble())
    325             return asDouble() == 0.0 ? "0" : UString::from(asDouble());
    326         if (isTrue())
    327             return "true";
    328         if (isFalse())
    329             return "false";
    330         if (isNull())
    331             return "null";
    332         ASSERT(isUndefined());
    333         return "undefined";
    334     }
    335 
    336318    inline bool JSValue::needsThisConversion() const
    337319    {
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r47412 r47622  
    3535#include "JSValue.h"
    3636#include "MarkStack.h"
     37#include "NumericStrings.h"
    3738#include "SmallStrings.h"
    3839#include "TimeoutChecker.h"
     
    115116        const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
    116117        SmallStrings smallStrings;
     118        NumericStrings numericStrings;
    117119
    118120#if ENABLE(ASSEMBLER)
  • trunk/JavaScriptCore/runtime/JSNumberCell.cpp

    r46598 r47622  
    5555UString JSNumberCell::toString(ExecState*) const
    5656{
    57     if (m_value == 0.0) // +0.0 or -0.0
    58         return "0";
    5957    return UString::from(m_value);
    6058}
     
    6260UString JSNumberCell::toThisString(ExecState*) const
    6361{
    64     if (m_value == 0.0) // +0.0 or -0.0
    65         return "0";
    6662    return UString::from(m_value);
    6763}
  • trunk/JavaScriptCore/runtime/JSString.h

    r47267 r47622  
    212212    }
    213213
     214    inline UString JSValue::toString(ExecState* exec) const
     215    {
     216        if (isString())
     217            return static_cast<JSString*>(asCell())->value();
     218        if (isInt32())
     219            return exec->globalData().numericStrings.add(asInt32());
     220        if (isDouble())
     221            return exec->globalData().numericStrings.add(asDouble());
     222        if (isTrue())
     223            return "true";
     224        if (isFalse())
     225            return "false";
     226        if (isNull())
     227            return "null";
     228        if (isUndefined())
     229            return "undefined";
     230        ASSERT(isCell());
     231        return asCell()->toString(exec);
     232    }
     233
    214234} // namespace JSC
    215235
  • trunk/JavaScriptCore/runtime/NumericStrings.h

    r47617 r47622  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef SmallStrings_h
    27 #define SmallStrings_h
     26#ifndef NumericStrings_h
     27#define NumericStrings_h
    2828
    2929#include "UString.h"
    30 #include <wtf/OwnPtr.h>
     30#include <wtf/HashFunctions.h>
    3131
    3232namespace JSC {
    3333
    34     class JSGlobalData;
    35     class JSString;
    36 
    37     class SmallStringsStorage;
    38 
    39     class SmallStrings : public Noncopyable {
     34    class NumericStrings {
    4035    public:
    41         SmallStrings();
    42         ~SmallStrings();
    43 
    44         JSString* emptyString(JSGlobalData* globalData)
     36        UString add(double d)
    4537        {
    46             if (!m_emptyString)
    47                 createEmptyString(globalData);
    48             return m_emptyString;
    49         }
    50         JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
    51         {
    52             if (!m_singleCharacterStrings[character])
    53                 createSingleCharacterString(globalData, character);
    54             return m_singleCharacterStrings[character];
     38            CacheEntry<double>& entry = lookup(d);
     39            if (d == entry.key && !entry.value.isNull())
     40                return entry.value;
     41            entry.key = d;
     42            entry.value = UString::from(d);
     43            return entry.value;
    5544        }
    5645
    57         UString::Rep* singleCharacterStringRep(unsigned char character);
    58 
    59         void mark();
    60 
    61         unsigned count() const;
     46        UString add(int i)
     47        {
     48            CacheEntry<int>& entry = lookup(i);
     49            if (i == entry.key && !entry.value.isNull())
     50                return entry.value;
     51            entry.key = i;
     52            entry.value = UString::from(i);
     53            return entry.value;
     54        }
    6255
    6356    private:
    64         void createEmptyString(JSGlobalData*);
    65         void createSingleCharacterString(JSGlobalData*, unsigned char);
     57        static const size_t cacheSize = 64;
    6658
    67         JSString* m_emptyString;
    68         JSString* m_singleCharacterStrings[0x100];
    69         OwnPtr<SmallStringsStorage> m_storage;
     59        template<typename T>
     60        struct CacheEntry {
     61            T key;
     62            UString value;
     63        };
     64
     65        CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
     66        CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
     67
     68        CacheEntry<double> doubleCache[cacheSize];
     69        CacheEntry<int> intCache[cacheSize];
    7070    };
    7171
    7272} // namespace JSC
    7373
    74 #endif // SmallStrings_h
     74#endif // NumericStrings_h
  • trunk/JavaScriptCore/runtime/Operations.h

    r46598 r47622  
    309309        UString result(resultRep);
    310310
    311         // Loop over the openards, writing them into the output buffer.
     311        // Loop over the operands, writing them into the output buffer.
    312312        for (unsigned i = 0; i < count; ++i) {
    313313            JSValue v = strings[i].jsValue();
    314314            if (LIKELY(v.isString()))
    315315                result.append(asString(v)->value());
    316             else if (v.isInt32())
    317                 result.appendNumeric(v.asInt32());
    318             else {
    319                 double d;
    320                 if (v.getNumber(d))
    321                     result.appendNumeric(d);
    322                 else
    323                     result.append(v.toString(callFrame));
    324             }
     316            else
     317                result.append(v.toString(callFrame));
    325318        }
    326319
  • trunk/JavaScriptCore/runtime/UString.cpp

    r47102 r47622  
    10281028    if (isnan(d))
    10291029        return "NaN";
     1030    if (!d)
     1031        return "0"; // -0 -> "0"
    10301032
    10311033    char buf[80];
     
    12101212}
    12111213
    1212 UString& UString::appendNumeric(int i)
    1213 {
    1214     m_rep = concatenate(rep(), i);
    1215     return *this;
    1216 }
    1217 
    1218 UString& UString::appendNumeric(double d)
    1219 {
    1220     m_rep = concatenate(rep(), d);
    1221     return *this;
    1222 }
    1223 
    12241214UString& UString::append(const char* t)
    12251215{
  • trunk/JavaScriptCore/runtime/UString.h

    r47096 r47622  
    288288        UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
    289289        UString& append(const UChar*, int size);
    290         UString& appendNumeric(int);
    291         UString& appendNumeric(double);
    292290
    293291        bool getCString(CStringBuffer&) const;
Note: See TracChangeset for help on using the changeset viewer.