Changeset 98624 in webkit


Ignore:
Timestamp:
Oct 27, 2011 1:16:20 PM (12 years ago)
Author:
msaboff@apple.com
Message:

Investigate storing strings in 8-bit buffers when possible
https://bugs.webkit.org/show_bug.cgi?id=66161

Source/JavaScriptCore:

Investigate storing strings in 8-bit buffers when possible
https://bugs.webkit.org/show_bug.cgi?id=66161

Added support for 8 bit string data in StringImpl. Changed
(UChar*) m_data to m_data16. Added char* m_data8 as a union
with m_data16. Added UChar* m_copyData16 to the other union
to store a 16 bit copy of an 8 bit string when needed.
Added characters8() and characters16() accessor methods
that assume the caller has checked the underlying string type
via the new is8Bit() method. The characters() method will
return a UChar* of the string, materializing a 16 bit copy if the
string is an 8 bit string. Added two flags, one for 8 bit buffer
and a second for a 16 bit copy for an 8 bit string.

Fixed method name typo (StringHasher::defaultCoverter()).

Over time the goal is to eliminate calls to characters() and
us the character8() and characters16() accessors.

This patch does not include changes that actually create 8 bit
strings. This is the first of at least 8 patches. Subsequent
patches will be submitted for JIT changes, making the JSC lexer,
parser and literal parser, JavaScript string changes and
then changes in webcore to take advantage of the 8 bit strings.

This change is performance neutral for SunSpider and V8 when
run from the command line with "jsc".

Reviewed by Geoffrey Garen.

(JSC::Interpreter::callEval):

  • parser/SourceProvider.h:

(JSC::UStringSourceProvider::data):
(JSC::UStringSourceProvider::UStringSourceProvider):

  • runtime/Identifier.cpp:

(JSC::IdentifierCStringTranslator::hash):
(JSC::IdentifierCStringTranslator::equal):
(JSC::IdentifierCStringTranslator::translate):
(JSC::Identifier::add):
(JSC::Identifier::toUInt32):

  • runtime/Identifier.h:

(JSC::Identifier::equal):
(JSC::operator==):
(JSC::operator!=):

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope):
(JSC::JSString::resolveRopeSlowCase):

  • runtime/RegExp.cpp:

(JSC::RegExp::match):

  • runtime/StringPrototype.cpp:

(JSC::jsSpliceSubstringsWithSeparators):

  • runtime/UString.cpp:

(JSC::UString::UString):
(JSC::equalSlowCase):
(JSC::UString::utf8):

  • runtime/UString.h:

(JSC::UString::characters):
(JSC::UString::characters8):
(JSC::UString::characters16):
(JSC::UString::is8Bit):
(JSC::UString::operator[]):
(JSC::UString::find):
(JSC::operator==):

  • wtf/StringHasher.h:

(WTF::StringHasher::computeHash):
(WTF::StringHasher::defaultConverter):

  • wtf/text/AtomicString.cpp:

(WTF::CStringTranslator::hash):
(WTF::CStringTranslator::equal):
(WTF::CStringTranslator::translate):
(WTF::AtomicString::add):

  • wtf/text/AtomicString.h:

(WTF::AtomicString::AtomicString):
(WTF::AtomicString::contains):
(WTF::AtomicString::find):
(WTF::AtomicString::add):
(WTF::operator==):
(WTF::operator!=):
(WTF::equalIgnoringCase):

  • wtf/text/StringConcatenate.h:
  • wtf/text/StringHash.h:

(WTF::StringHash::equal):
(WTF::CaseFoldingHash::hash):

  • wtf/text/StringImpl.cpp:

(WTF::StringImpl::~StringImpl):
(WTF::StringImpl::createUninitialized):
(WTF::StringImpl::create):
(WTF::StringImpl::getData16SlowCase):
(WTF::StringImpl::containsOnlyWhitespace):
(WTF::StringImpl::substring):
(WTF::StringImpl::characterStartingAt):
(WTF::StringImpl::lower):
(WTF::StringImpl::upper):
(WTF::StringImpl::fill):
(WTF::StringImpl::foldCase):
(WTF::StringImpl::stripMatchedCharacters):
(WTF::StringImpl::removeCharacters):
(WTF::StringImpl::simplifyMatchedCharactersToSpace):
(WTF::StringImpl::toIntStrict):
(WTF::StringImpl::toUIntStrict):
(WTF::StringImpl::toInt64Strict):
(WTF::StringImpl::toUInt64Strict):
(WTF::StringImpl::toIntPtrStrict):
(WTF::StringImpl::toInt):
(WTF::StringImpl::toUInt):
(WTF::StringImpl::toInt64):
(WTF::StringImpl::toUInt64):
(WTF::StringImpl::toIntPtr):
(WTF::StringImpl::toDouble):
(WTF::StringImpl::toFloat):
(WTF::equal):
(WTF::equalIgnoringCase):
(WTF::StringImpl::find):
(WTF::StringImpl::findIgnoringCase):
(WTF::StringImpl::reverseFind):
(WTF::StringImpl::replace):
(WTF::StringImpl::defaultWritingDirection):
(WTF::StringImpl::adopt):
(WTF::StringImpl::createWithTerminatingNullCharacter):

  • wtf/text/StringImpl.h:

(WTF::StringImpl::StringImpl):
(WTF::StringImpl::create):
(WTF::StringImpl::create8):
(WTF::StringImpl::tryCreateUninitialized):
(WTF::StringImpl::flagsOffset):
(WTF::StringImpl::flagIs8Bit):
(WTF::StringImpl::dataOffset):
(WTF::StringImpl::is8Bit):
(WTF::StringImpl::characters8):
(WTF::StringImpl::characters16):
(WTF::StringImpl::characters):
(WTF::StringImpl::has16BitShadow):
(WTF::StringImpl::setHash):
(WTF::StringImpl::hash):
(WTF::StringImpl::copyChars):
(WTF::StringImpl::operator[]):
(WTF::StringImpl::find):
(WTF::StringImpl::findIgnoringCase):
(WTF::equal):
(WTF::equalIgnoringCase):
(WTF::StringImpl::isolatedCopy):

  • wtf/text/WTFString.cpp:

(WTF::String::String):
(WTF::String::append):
(WTF::String::format):
(WTF::String::fromUTF8):
(WTF::String::fromUTF8WithLatin1Fallback):

  • wtf/text/WTFString.h:

(WTF::String::find):
(WTF::String::findIgnoringCase):
(WTF::String::contains):
(WTF::String::append):
(WTF::String::fromUTF8):
(WTF::String::fromUTF8WithLatin1Fallback):
(WTF::operator==):
(WTF::operator!=):
(WTF::equalIgnoringCase):

  • wtf/unicode/Unicode.h:
  • yarr/YarrJIT.cpp:

(JSC::Yarr::execute):

  • yarr/YarrJIT.h:

(JSC::Yarr::YarrCodeBlock::execute):

  • yarr/YarrParser.h:

(JSC::Yarr::Parser::Parser):

Source/WebCore:

Changes to support 8 bit StringImpl changes.

Reviewed by Geoffrey Garen.

No new tests, refactored StringImpl for 8 bit strings.

  • platform/text/cf/StringImplCF.cpp:

(WTF::StringImpl::createCFString):

Source/WebKit2:

Added export of StringImpl::getData16SlowCase for linking tests.

Reviewed by Geoffrey Garen.

  • win/WebKit2.def:
Location:
trunk/Source
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r98606 r98624  
     12011-10-27  Michael Saboff  <msaboff@apple.com>
     2
     3        Investigate storing strings in 8-bit buffers when possible
     4        https://bugs.webkit.org/show_bug.cgi?id=66161
     5
     6        Investigate storing strings in 8-bit buffers when possible
     7        https://bugs.webkit.org/show_bug.cgi?id=66161
     8
     9        Added support for 8 bit string data in StringImpl.  Changed
     10        (UChar*) m_data to m_data16.  Added char* m_data8 as a union
     11        with m_data16.  Added UChar* m_copyData16 to the other union
     12        to store a 16 bit copy of an 8 bit string when needed.
     13        Added characters8() and characters16() accessor methods
     14        that assume the caller has checked the underlying string type
     15        via the new is8Bit() method. The characters() method will
     16        return a UChar* of the string, materializing a 16 bit copy if the
     17        string is an 8 bit string.  Added two flags, one for 8 bit buffer
     18        and a second for a 16 bit copy for an 8 bit string.
     19
     20        Fixed method name typo (StringHasher::defaultCoverter()).
     21
     22        Over time the goal is to eliminate calls to characters() and
     23        us the character8() and characters16() accessors.
     24
     25        This patch does not include changes that actually create 8 bit
     26        strings. This is the first of at least 8 patches.  Subsequent
     27        patches will be submitted for JIT changes, making the JSC lexer,
     28        parser and literal parser, JavaScript string changes and
     29        then changes in webcore to take advantage of the 8 bit strings.
     30
     31        This change is performance neutral for SunSpider and V8 when
     32        run from the command line with "jsc".
     33
     34        Reviewed by Geoffrey Garen.
     35
     36        * JavaScriptCore.exp:
     37        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
     38        * interpreter/Interpreter.cpp:
     39        (JSC::Interpreter::callEval):
     40        * parser/SourceProvider.h:
     41        (JSC::UStringSourceProvider::data):
     42        (JSC::UStringSourceProvider::UStringSourceProvider):
     43        * runtime/Identifier.cpp:
     44        (JSC::IdentifierCStringTranslator::hash):
     45        (JSC::IdentifierCStringTranslator::equal):
     46        (JSC::IdentifierCStringTranslator::translate):
     47        (JSC::Identifier::add):
     48        (JSC::Identifier::toUInt32):
     49        * runtime/Identifier.h:
     50        (JSC::Identifier::equal):
     51        (JSC::operator==):
     52        (JSC::operator!=):
     53        * runtime/JSString.cpp:
     54        (JSC::JSString::resolveRope):
     55        (JSC::JSString::resolveRopeSlowCase):
     56        * runtime/RegExp.cpp:
     57        (JSC::RegExp::match):
     58        * runtime/StringPrototype.cpp:
     59        (JSC::jsSpliceSubstringsWithSeparators):
     60        * runtime/UString.cpp:
     61        (JSC::UString::UString):
     62        (JSC::equalSlowCase):
     63        (JSC::UString::utf8):
     64        * runtime/UString.h:
     65        (JSC::UString::characters):
     66        (JSC::UString::characters8):
     67        (JSC::UString::characters16):
     68        (JSC::UString::is8Bit):
     69        (JSC::UString::operator[]):
     70        (JSC::UString::find):
     71        (JSC::operator==):
     72        * wtf/StringHasher.h:
     73        (WTF::StringHasher::computeHash):
     74        (WTF::StringHasher::defaultConverter):
     75        * wtf/text/AtomicString.cpp:
     76        (WTF::CStringTranslator::hash):
     77        (WTF::CStringTranslator::equal):
     78        (WTF::CStringTranslator::translate):
     79        (WTF::AtomicString::add):
     80        * wtf/text/AtomicString.h:
     81        (WTF::AtomicString::AtomicString):
     82        (WTF::AtomicString::contains):
     83        (WTF::AtomicString::find):
     84        (WTF::AtomicString::add):
     85        (WTF::operator==):
     86        (WTF::operator!=):
     87        (WTF::equalIgnoringCase):
     88        * wtf/text/StringConcatenate.h:
     89        * wtf/text/StringHash.h:
     90        (WTF::StringHash::equal):
     91        (WTF::CaseFoldingHash::hash):
     92        * wtf/text/StringImpl.cpp:
     93        (WTF::StringImpl::~StringImpl):
     94        (WTF::StringImpl::createUninitialized):
     95        (WTF::StringImpl::create):
     96        (WTF::StringImpl::getData16SlowCase):
     97        (WTF::StringImpl::containsOnlyWhitespace):
     98        (WTF::StringImpl::substring):
     99        (WTF::StringImpl::characterStartingAt):
     100        (WTF::StringImpl::lower):
     101        (WTF::StringImpl::upper):
     102        (WTF::StringImpl::fill):
     103        (WTF::StringImpl::foldCase):
     104        (WTF::StringImpl::stripMatchedCharacters):
     105        (WTF::StringImpl::removeCharacters):
     106        (WTF::StringImpl::simplifyMatchedCharactersToSpace):
     107        (WTF::StringImpl::toIntStrict):
     108        (WTF::StringImpl::toUIntStrict):
     109        (WTF::StringImpl::toInt64Strict):
     110        (WTF::StringImpl::toUInt64Strict):
     111        (WTF::StringImpl::toIntPtrStrict):
     112        (WTF::StringImpl::toInt):
     113        (WTF::StringImpl::toUInt):
     114        (WTF::StringImpl::toInt64):
     115        (WTF::StringImpl::toUInt64):
     116        (WTF::StringImpl::toIntPtr):
     117        (WTF::StringImpl::toDouble):
     118        (WTF::StringImpl::toFloat):
     119        (WTF::equal):
     120        (WTF::equalIgnoringCase):
     121        (WTF::StringImpl::find):
     122        (WTF::StringImpl::findIgnoringCase):
     123        (WTF::StringImpl::reverseFind):
     124        (WTF::StringImpl::replace):
     125        (WTF::StringImpl::defaultWritingDirection):
     126        (WTF::StringImpl::adopt):
     127        (WTF::StringImpl::createWithTerminatingNullCharacter):
     128        * wtf/text/StringImpl.h:
     129        (WTF::StringImpl::StringImpl):
     130        (WTF::StringImpl::create):
     131        (WTF::StringImpl::create8):
     132        (WTF::StringImpl::tryCreateUninitialized):
     133        (WTF::StringImpl::flagsOffset):
     134        (WTF::StringImpl::flagIs8Bit):
     135        (WTF::StringImpl::dataOffset):
     136        (WTF::StringImpl::is8Bit):
     137        (WTF::StringImpl::characters8):
     138        (WTF::StringImpl::characters16):
     139        (WTF::StringImpl::characters):
     140        (WTF::StringImpl::has16BitShadow):
     141        (WTF::StringImpl::setHash):
     142        (WTF::StringImpl::hash):
     143        (WTF::StringImpl::copyChars):
     144        (WTF::StringImpl::operator[]):
     145        (WTF::StringImpl::find):
     146        (WTF::StringImpl::findIgnoringCase):
     147        (WTF::equal):
     148        (WTF::equalIgnoringCase):
     149        (WTF::StringImpl::isolatedCopy):
     150        * wtf/text/WTFString.cpp:
     151        (WTF::String::String):
     152        (WTF::String::append):
     153        (WTF::String::format):
     154        (WTF::String::fromUTF8):
     155        (WTF::String::fromUTF8WithLatin1Fallback):
     156        * wtf/text/WTFString.h:
     157        (WTF::String::find):
     158        (WTF::String::findIgnoringCase):
     159        (WTF::String::contains):
     160        (WTF::String::append):
     161        (WTF::String::fromUTF8):
     162        (WTF::String::fromUTF8WithLatin1Fallback):
     163        (WTF::operator==):
     164        (WTF::operator!=):
     165        (WTF::equalIgnoringCase):
     166        * wtf/unicode/Unicode.h:
     167        * yarr/YarrJIT.cpp:
     168        (JSC::Yarr::execute):
     169        * yarr/YarrJIT.h:
     170        (JSC::Yarr::YarrCodeBlock::execute):
     171        * yarr/YarrParser.h:
     172        (JSC::Yarr::Parser::Parser):
     173
    11742011-10-27  Mark Hahnenberg  <mhahnenberg@apple.com>
    2175
  • trunk/Source/JavaScriptCore/JavaScriptCore.exp

    r98593 r98624  
    353353__ZN3WTF10StringImpl11reverseFindEPS0_j
    354354__ZN3WTF10StringImpl11reverseFindEtj
    355 __ZN3WTF10StringImpl16findIgnoringCaseEPKcj
    356355__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
    357356__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
     
    363362__ZN3WTF10StringImpl4fillEt
    364363__ZN3WTF10StringImpl4findEPFbtEj
    365 __ZN3WTF10StringImpl4findEPKcj
    366364__ZN3WTF10StringImpl4findEPS0_j
    367365__ZN3WTF10StringImpl4findEtj
     
    371369__ZN3WTF10StringImpl5toIntEPb
    372370__ZN3WTF10StringImpl5upperEv
    373 __ZN3WTF10StringImpl6createEPKc
    374 __ZN3WTF10StringImpl6createEPKcj
     371__ZN3WTF10StringImpl6createEPKh
    375372__ZN3WTF10StringImpl6createEPKtj
    376373__ZN3WTF10StringImpl7replaceEPS0_S1_
     
    392389__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
    393390__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
    394 __ZN3WTF12AtomicString3addEPKc
     391__ZN3WTF12AtomicString3addEPKh
    395392__ZN3WTF12AtomicString3addEPKt
    396393__ZN3WTF12AtomicString3addEPKtj
     
    434431__ZN3WTF16fastZeroedMallocEm
    435432__ZN3WTF17charactersToFloatEPKtmPbS2_
    436 __ZN3WTF17equalIgnoringCaseEPKtPKcj
    437 __ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
     433__ZN3WTF17equalIgnoringCaseEPKtPKhj
    438434__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
     435__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKh
    439436__ZN3WTF18calculateDSTOffsetEdd
    440437__ZN3WTF18calculateUTCOffsetEv
     
    481478__ZN3WTF5MutexC1Ev
    482479__ZN3WTF5MutexD1Ev
    483 __ZN3WTF5equalEPKNS_10StringImplEPKc
     480__ZN3WTF5equalEPKNS_10StringImplEPKh
    484481__ZN3WTF5equalEPKNS_10StringImplEPKtj
    485482__ZN3WTF5equalEPKNS_10StringImplES2_
    486483__ZN3WTF5yieldEv
    487 __ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
     484__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKhm
    488485__ZN3WTF6String29charactersWithNullTerminationEv
     486__ZN3WTF6StringC1EPKcj
     487__ZN3WTF6String6appendEh
    489488__ZN3WTF6String6appendEPKtj
    490489__ZN3WTF6String6appendERKS0_
    491 __ZN3WTF6String6appendEc
    492490__ZN3WTF6String6appendEt
    493491__ZN3WTF6String6formatEPKcz
     
    502500__ZN3WTF6String6numberEy
    503501__ZN3WTF6String6removeEji
    504 __ZN3WTF6String8fromUTF8EPKc
    505 __ZN3WTF6String8fromUTF8EPKcm
     502__ZN3WTF6String8fromUTF8EPKh
     503__ZN3WTF6String8fromUTF8EPKhm
    506504__ZN3WTF6String8truncateEj
    507505__ZN3WTF6StringC1EPKc
    508 __ZN3WTF6StringC1EPKcj
    509506__ZN3WTF6StringC1EPKt
    510507__ZN3WTF6StringC1EPKtj
     
    578575__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
    579576__ZNK3JSC9HashTable11deleteTableEv
     577__ZNK3WTF10StringImpl17getData16SlowCaseEv
    580578__ZNK3WTF12AtomicString5lowerEv
    581579__ZNK3WTF13DecimalNumber15toStringDecimalEPtj
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r98606 r98624  
    4848    ?absoluteTimeToWaitTimeoutInterval@WTF@@YAKN@Z
    4949    ?activityCallback@Heap@JSC@@QAEPAVGCActivityCallback@2@XZ
     50    ?add@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PBD@Z
    5051    ?add@Identifier@JSC@@SA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PBD@Z
    5152    ?add@PropertyNameArray@JSC@@QAEXPAVStringImpl@WTF@@@Z
     
    158159    ?empty@StringImpl@WTF@@SAPAV12@XZ
    159160    ?enumerable@PropertyDescriptor@JSC@@QBE_NXZ
    160     ?equal@Identifier@JSC@@SA_NPBVStringImpl@WTF@@PBD@Z
    161161    ?equalUTF16WithUTF8@Unicode@WTF@@YA_NPB_W0PBD1@Z
    162162    ?evaluate@DebuggerCallFrame@JSC@@QBE?AVJSValue@2@ABVUString@2@AAV32@@Z
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r98422 r98624  
    446446            // FIXME: We can use the preparser in strict mode, we just need additional logic
    447447            // to prevent duplicates.
    448             LiteralParser preparser(callFrame, programSource.characters(), programSource.length(), LiteralParser::NonStrictJSON);
     448            LiteralParser preparser(callFrame, programSource.characters16(), programSource.length(), LiteralParser::NonStrictJSON);
    449449            if (JSValue parsedObject = preparser.tryLiteralParse())
    450450                return parsedObject;
  • trunk/Source/JavaScriptCore/parser/SourceProvider.h

    r95901 r98624  
    8989            return m_source.substringSharingImpl(start, end - start);
    9090        }
    91         const UChar* data() const { return m_source.characters(); }
     91        const UChar* data() const { return m_data; }
    9292        int length() const { return m_source.length(); }
    9393
     
    9696            : SourceProvider(url)
    9797            , m_source(source)
     98            , m_data(m_source.characters16())
    9899        {
    99100        }
    100101
    101102        UString m_source;
     103        const UChar* m_data;
    102104    };
    103105   
  • trunk/Source/JavaScriptCore/runtime/Identifier.cpp

    r94475 r98624  
    6969
    7070struct IdentifierCStringTranslator {
    71     static unsigned hash(const char* c)
    72     {
    73         return StringHasher::computeHash<char>(c);
    74     }
    75 
    76     static bool equal(StringImpl* r, const char* s)
     71    static unsigned hash(const LChar* c)
     72    {
     73        return StringHasher::computeHash<LChar>(c);
     74    }
     75
     76    static bool equal(StringImpl* r, const LChar* s)
    7777    {
    7878        return Identifier::equal(r, s);
    7979    }
    8080
    81     static void translate(StringImpl*& location, const char* c, unsigned hash)
    82     {
    83         size_t length = strlen(c);
     81    static void translate(StringImpl*& location, const LChar* c, unsigned hash)
     82    {
     83        size_t length = strlen(reinterpret_cast<const char*>(c));
    8484        UChar* d;
    8585        StringImpl* r = StringImpl::createUninitialized(length, d).leakRef();
    8686        for (size_t i = 0; i != length; i++)
    87             d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
     87            d[i] = c[i];
    8888        r->setHash(hash);
    8989        location = r;
     
    9898        return StringImpl::empty();
    9999    if (!c[1])
    100         return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
     100        return add(globalData, globalData->smallStrings.singleCharacterStringRep(c[0]));
    101101
    102102    IdentifierTable& identifierTable = *globalData->identifierTable;
     
    107107        return iter->second;
    108108
    109     pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c);
     109    pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const LChar*, IdentifierCStringTranslator>(reinterpret_cast<const LChar*>(c));
    110110
    111111    // If the string is newly-translated, then we need to adopt it.
     
    155155
    156156    unsigned length = string.length();
    157     const UChar* characters = string.characters();
    158157
    159158    // An empty string is not a number.
    160159    if (!length)
    161160        return 0;
     161
     162    const UChar* characters = string.characters16();
    162163
    163164    // Get the first character, turning it into a digit.
  • trunk/Source/JavaScriptCore/runtime/Identifier.h

    r97675 r98624  
    7171        friend bool operator!=(const Identifier&, const Identifier&);
    7272
     73        friend bool operator==(const Identifier&, const LChar*);
    7374        friend bool operator==(const Identifier&, const char*);
     75        friend bool operator!=(const Identifier&, const LChar*);
    7476        friend bool operator!=(const Identifier&, const char*);
    7577   
    76         static bool equal(const StringImpl*, const char*);
     78        static bool equal(const StringImpl*, const LChar*);
     79        static inline bool equal(const StringImpl*a, const char*b) { return Identifier::equal(a, reinterpret_cast<const LChar*>(b)); };
    7780        static bool equal(const StringImpl*, const UChar*, unsigned length);
    7881        static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
     
    8588       
    8689        static bool equal(const Identifier& a, const Identifier& b) { return a.m_string.impl() == b.m_string.impl(); }
    87         static bool equal(const Identifier& a, const char* b) { return equal(a.m_string.impl(), b); }
     90        static bool equal(const Identifier& a, const LChar* b) { return equal(a.m_string.impl(), b); }
    8891
    8992        static PassRefPtr<StringImpl> add(ExecState*, const UChar*, int length);
     
    126129    }
    127130
    128     inline bool operator==(const Identifier& a, const char* b)
     131    inline bool operator==(const Identifier& a, const LChar* b)
    129132    {
    130133        return Identifier::equal(a, b);
    131134    }
    132135
    133     inline bool operator!=(const Identifier& a, const char* b)
     136    inline bool operator==(const Identifier& a, const char* b)
     137    {
     138        return Identifier::equal(a, reinterpret_cast<const LChar*>(b));
     139    }
     140   
     141    inline bool operator!=(const Identifier& a, const LChar* b)
    134142    {
    135143        return !Identifier::equal(a, b);
    136144    }
    137145
    138     inline bool Identifier::equal(const StringImpl* r, const char* s)
     146    inline bool operator!=(const Identifier& a, const char* b)
     147    {
     148        return !Identifier::equal(a, reinterpret_cast<const LChar*>(b));
     149    }
     150   
     151    inline bool Identifier::equal(const StringImpl* r, const LChar* s)
    139152    {
    140153        return WTF::equal(r, s);
  • trunk/Source/JavaScriptCore/runtime/JSString.cpp

    r98593 r98624  
    8080        StringImpl* string = m_fibers[i]->m_value.impl();
    8181        unsigned length = string->length();
    82         StringImpl::copyChars(position, string->characters(), length);
     82        StringImpl::copyChars(position, string->characters16(), length);
    8383        position += length;
    8484        m_fibers[i].clear();
     
    121121        unsigned length = string->length();
    122122        position -= length;
    123         StringImpl::copyChars(position, string->characters(), length);
     123        StringImpl::copyChars(position, string->characters16(), length);
    124124    }
    125125
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r95936 r98624  
    367367        if (m_state == JITCode) {
    368368            if (s.is8Bit())
    369                 result = Yarr::execute(m_representation->m_regExpJITCode, s.latin1().data(), startOffset, s.length(), offsetVector);
     369                result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector);
    370370            else
    371                 result = Yarr::execute(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector);
     371                result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector);
    372372#if ENABLE(YARR_JIT_DEBUG)
    373373            matchCompareWithInterpreter(s, startOffset, offsetVector, result);
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r98501 r98624  
    331331        if (i < rangeCount) {
    332332            if (int srcLen = substringRanges[i].length) {
    333                 StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
     333                StringImpl::copyChars(buffer + bufferPos, source.characters16() + substringRanges[i].position, srcLen);
    334334                bufferPos += srcLen;
    335335            }
     
    337337        if (i < separatorCount) {
    338338            if (int sepLen = separators[i].length()) {
    339                 StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen);
     339                StringImpl::copyChars(buffer + bufferPos, separators[i].characters16(), sepLen);
    340340                bufferPos += sepLen;
    341341            }
  • trunk/Source/JavaScriptCore/runtime/UString.cpp

    r94452 r98624  
    7474
    7575// Construct a string with latin1 data.
     76UString::UString(const LChar* characters, unsigned length)
     77    : m_impl(characters ? StringImpl::create(characters, length) : 0)
     78{
     79}
     80
    7681UString::UString(const char* characters, unsigned length)
    77     : m_impl(characters ? StringImpl::create(characters, length) : 0)
     82    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters), length) : 0)
    7883{
    7984}
    8085
    8186// Construct a string with latin1 data, from a null-terminated source.
     87UString::UString(const LChar* characters)
     88    : m_impl(characters ? StringImpl::create(characters) : 0)
     89{
     90}
     91
    8292UString::UString(const char* characters)
    83     : m_impl(characters ? StringImpl::create(characters) : 0)
     93    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters)) : 0)
    8494{
    8595}
     
    230240}
    231241
     242// This method assumes that all simple checks have been performed by
     243// the inlined operator==() in the header file.
     244bool equalSlowCase(const UString& s1, const UString& s2)
     245{
     246    StringImpl* rep1 = s1.impl();
     247    StringImpl* rep2 = s2.impl();
     248    unsigned size1 = rep1->length();
     249
     250    // At this point we know
     251    //   (a) that the strings are the same length and
     252    //   (b) that they are greater than zero length.
     253    bool s1Is8Bit = rep1->is8Bit();
     254    bool s2Is8Bit = rep2->is8Bit();
     255   
     256    if (s1Is8Bit) {
     257        const LChar* d1 = rep1->characters8();
     258        if (s2Is8Bit) {
     259            const LChar* d2 = rep2->characters8();
     260           
     261            if (d1 == d2) // Check to see if the data pointers are the same.
     262                return true;
     263           
     264            // Do quick checks for sizes 1 and 2.
     265            switch (size1) {
     266            case 1:
     267                return d1[0] == d2[0];
     268            case 2:
     269                return (d1[0] == d2[0]) & (d1[1] == d2[1]);
     270            default:
     271                return (!memcmp(d1, d2, size1 * sizeof(LChar)));
     272            }
     273        }
     274       
     275        const UChar* d2 = rep2->characters16();
     276       
     277        for (unsigned i = 0; i < size1; i++) {
     278            if (d1[i] != d2[i])
     279                return false;
     280        }
     281        return true;
     282    }
     283   
     284    if (s2Is8Bit) {
     285        const UChar* d1 = rep1->characters16();
     286        const LChar* d2 = rep2->characters8();
     287       
     288        for (unsigned i = 0; i < size1; i++) {
     289            if (d1[i] != d2[i])
     290                return false;
     291        }
     292        return true;
     293       
     294    }
     295   
     296    const UChar* d1 = rep1->characters16();
     297    const UChar* d2 = rep2->characters16();
     298   
     299    if (d1 == d2) // Check to see if the data pointers are the same.
     300        return true;
     301   
     302    // Do quick checks for sizes 1 and 2.
     303    switch (size1) {
     304    case 1:
     305        return d1[0] == d2[0];
     306    case 2:
     307        return (d1[0] == d2[0]) & (d1[1] == d2[1]);
     308    default:
     309        return (!memcmp(d1, d2, size1 * sizeof(UChar)));
     310    }
     311}
     312
    232313bool operator<(const UString& s1, const UString& s2)
    233314{
     
    318399{
    319400    unsigned length = this->length();
    320     const UChar* characters = this->characters();
     401
     402    if (is8Bit())
     403        return CString(reinterpret_cast<const char*>(characters8()), length);
    321404
    322405    // Allocate a buffer big enough to hold all the characters
     
    332415    if (length > numeric_limits<unsigned>::max() / 3)
    333416        return CString();
     417
     418    const UChar* characters = this->characters16();
    334419    Vector<char, 1024> bufferVector(length * 3);
    335420
  • trunk/Source/JavaScriptCore/runtime/UString.h

    r94981 r98624  
    4040
    4141    // Construct a string with latin1 data.
     42    UString(const LChar* characters, unsigned length);
    4243    UString(const char* characters, unsigned length);
    4344
    4445    // Construct a string with latin1 data, from a null-terminated source.
     46    UString(const LChar* characters);
    4547    UString(const char* characters);
    4648
     
    7476        if (!m_impl)
    7577            return 0;
    76         return m_impl->characters();
    77     }
    78 
    79     bool is8Bit() const { return false; }
     78        return m_impl->characters16();
     79    }
     80
     81    const LChar* characters8() const
     82    {
     83        if (!m_impl)
     84            return 0;
     85        ASSERT(m_impl->is8Bit());
     86        return m_impl->characters8();
     87    }
     88
     89    const UChar* characters16() const
     90    {
     91        if (!m_impl)
     92            return 0;
     93        ASSERT(!m_impl->is8Bit());
     94        return m_impl->characters16();
     95    }
     96
     97    bool is8Bit() const { return m_impl->is8Bit(); }
    8098
    8199    CString ascii() const;
     
    87105        if (!m_impl || index >= m_impl->length())
    88106            return 0;
    89         return m_impl->characters()[index];
     107        if (is8Bit())
     108            return m_impl->characters8()[index];
     109        return m_impl->characters16()[index];
    90110    }
    91111
     
    101121    size_t find(const UString& str, unsigned start = 0) const
    102122        { return m_impl ? m_impl->find(str.impl(), start) : notFound; }
    103     size_t find(const char* str, unsigned start = 0) const
     123    size_t find(const LChar* str, unsigned start = 0) const
    104124        { return m_impl ? m_impl->find(str, start) : notFound; }
    105125
     
    116136};
    117137
     138NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2);
     139
    118140ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
    119141{
    120142    StringImpl* rep1 = s1.impl();
    121143    StringImpl* rep2 = s2.impl();
     144
     145    if (rep1 == rep2) // If they're the same rep, they're equal.
     146        return true;
     147
    122148    unsigned size1 = 0;
    123149    unsigned size2 = 0;
    124150
    125     if (rep1 == rep2) // If they're the same rep, they're equal.
    126         return true;
    127    
    128151    if (rep1)
    129152        size1 = rep1->length();
    130        
     153
    131154    if (rep2)
    132155        size2 = rep2->length();
    133        
     156
    134157    if (size1 != size2) // If the lengths are not the same, we're done.
    135158        return false;
    136    
     159
    137160    if (!size1)
    138161        return true;
    139    
    140     // At this point we know
    141     //   (a) that the strings are the same length and
    142     //   (b) that they are greater than zero length.
    143     const UChar* d1 = rep1->characters();
    144     const UChar* d2 = rep2->characters();
    145    
    146     if (d1 == d2) // Check to see if the data pointers are the same.
    147         return true;
    148    
    149     // Do quick checks for sizes 1 and 2.
    150     switch (size1) {
    151     case 1:
    152         return d1[0] == d2[0];
    153     case 2:
    154         return (d1[0] == d2[0]) & (d1[1] == d2[1]);
    155     default:
    156         return memcmp(d1, d2, size1 * sizeof(UChar)) == 0;
    157     }
     162
     163    if (size1 == 1)
     164        return (*rep1)[0] == (*rep2)[0];
     165
     166    return equalSlowCase(s1, s2);
    158167}
    159168
  • trunk/Source/JavaScriptCore/wtf/StringHasher.h

    r98495 r98624  
    135135    template<typename T> static inline unsigned computeHash(const T* data, unsigned length)
    136136    {
    137         return computeHash<T, defaultCoverter>(data, length);
     137        return computeHash<T, defaultConverter>(data, length);
    138138    }
    139139
    140140    template<typename T> static inline unsigned computeHash(const T* data)
    141141    {
    142         return computeHash<T, defaultCoverter>(data);
     142        return computeHash<T, defaultConverter>(data);
    143143    }
    144144
     
    156156
    157157private:
    158     static inline UChar defaultCoverter(UChar ch)
     158    static inline UChar defaultConverter(UChar ch)
    159159    {
    160160        return ch;
    161161    }
    162162
    163     static inline UChar defaultCoverter(char ch)
     163    static inline UChar defaultConverter(LChar ch)
    164164    {
    165         return static_cast<unsigned char>(ch);
     165        return ch;
    166166    }
    167167
  • trunk/Source/JavaScriptCore/wtf/text/AtomicString.cpp

    r94475 r98624  
    8686
    8787struct CStringTranslator {
    88     static unsigned hash(const char* c)
     88    static unsigned hash(const LChar* c)
    8989    {
    9090        return StringHasher::computeHash(c);
    9191    }
    9292
    93     static inline bool equal(StringImpl* r, const char* s)
     93    static inline bool equal(StringImpl* r, const LChar* s)
    9494    {
    9595        return WTF::equal(r, s);
    9696    }
    9797
    98     static void translate(StringImpl*& location, const char* const& c, unsigned hash)
     98    static void translate(StringImpl*& location, const LChar* const& c, unsigned hash)
    9999    {
    100100        location = StringImpl::create(c).leakRef();
     
    104104};
    105105
    106 PassRefPtr<StringImpl> AtomicString::add(const char* c)
     106PassRefPtr<StringImpl> AtomicString::add(const LChar* c)
    107107{
    108108    if (!c)
     
    111111        return StringImpl::empty();
    112112
    113     return addToStringTable<const char*, CStringTranslator>(c);
     113    return addToStringTable<const LChar*, CStringTranslator>(c);
    114114}
    115115
  • trunk/Source/JavaScriptCore/wtf/text/AtomicString.h

    r94475 r98624  
    4242
    4343    AtomicString() { }
     44    AtomicString(const LChar* s) : m_string(add(s)) { }
    4445    AtomicString(const char* s) : m_string(add(s)) { }
    4546    AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { }
     
    6768   
    6869    bool contains(UChar c) const { return m_string.contains(c); }
    69     bool contains(const char* s, bool caseSensitive = true) const
     70    bool contains(const LChar* s, bool caseSensitive = true) const
    7071        { return m_string.contains(s, caseSensitive); }
    7172    bool contains(const String& s, bool caseSensitive = true) const
     
    7374
    7475    size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); }
    75     size_t find(const char* s, size_t start = 0, bool caseSentitive = true) const
     76    size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) const
    7677        { return m_string.find(s, start, caseSentitive); }
    7778    size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const
     
    120121    String m_string;
    121122   
    122     static PassRefPtr<StringImpl> add(const char*);
     123    static PassRefPtr<StringImpl> add(const LChar*);
     124    ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s) { return add(reinterpret_cast<const LChar*>(s)); };
    123125    static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
     126    ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const char*>(s), length); };
    124127    static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
    125128    static PassRefPtr<StringImpl> add(const UChar*);
     
    135138
    136139inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
    137 bool operator==(const AtomicString& a, const char* b);
    138 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), b); }
     140bool operator==(const AtomicString&, const LChar*);
     141inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
    139142inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }   
    140143inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
    141 inline bool operator==(const char* a, const AtomicString& b) { return b == a; }
     144inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
    142145inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
    143146inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
    144147
    145148inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
    146 inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); }
     149inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); }
     150inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b); }
    147151inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
    148152inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
    149 inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); }
     153inline bool operator!=(const LChar* a, const AtomicString& b) { return !(b == a); }
    150154inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
    151155inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
    152156
    153157inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    154 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
     158inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); }
     159inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); }
    155160inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    156 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
     161inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
     162inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
    157163inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    158164
  • trunk/Source/JavaScriptCore/wtf/text/StringConcatenate.h

    r90813 r98624  
    5959
    6060template<>
     61class StringTypeAdapter<LChar> {
     62public:
     63    StringTypeAdapter<LChar>(LChar buffer)
     64        : m_buffer(buffer)
     65    {
     66    }
     67
     68    unsigned length() { return 1; }
     69    void writeTo(UChar* destination) { *destination = m_buffer; }
     70
     71private:
     72    LChar m_buffer;
     73};
     74
     75template<>
    6176class StringTypeAdapter<UChar> {
    6277public:
     
    98113
    99114template<>
     115class StringTypeAdapter<LChar*> {
     116public:
     117    StringTypeAdapter<LChar*>(LChar* buffer)
     118    : m_buffer(buffer)
     119    , m_length(strlen(reinterpret_cast<char*>(buffer)))
     120    {
     121    }
     122
     123    unsigned length() { return m_length; }
     124
     125    void writeTo(UChar* destination)
     126    {
     127        for (unsigned i = 0; i < m_length; ++i)
     128            destination[i] = m_buffer[i];
     129    }
     130
     131private:
     132    const LChar* m_buffer;
     133    unsigned m_length;
     134};
     135
     136template<>
    100137class StringTypeAdapter<const UChar*> {
    101138public:
     
    150187
    151188template<>
     189class StringTypeAdapter<const LChar*> {
     190public:
     191    StringTypeAdapter<const LChar*>(const LChar* buffer)
     192        : m_buffer(buffer)
     193        , m_length(strlen(reinterpret_cast<const char*>(buffer)))
     194    {
     195    }
     196   
     197    unsigned length() { return m_length; }
     198   
     199    void writeTo(UChar* destination)
     200    {
     201        for (unsigned i = 0; i < m_length; ++i)
     202            destination[i] = m_buffer[i];
     203    }
     204   
     205private:
     206    const LChar* m_buffer;
     207    unsigned m_length;
     208};
     209
     210template<>
    152211class StringTypeAdapter<Vector<char> > {
    153212public:
     
    169228private:
    170229    const Vector<char>& m_buffer;
     230};
     231
     232template<>
     233class StringTypeAdapter<Vector<LChar> > {
     234public:
     235    StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer)
     236        : m_buffer(buffer)
     237    {
     238    }
     239
     240    size_t length() { return m_buffer.size(); }
     241
     242    void writeTo(UChar* destination)
     243    {
     244        for (size_t i = 0; i < m_buffer.size(); ++i)
     245            destination[i] = m_buffer[i];
     246    }
     247
     248private:
     249    const Vector<LChar>& m_buffer;
    171250};
    172251
  • trunk/Source/JavaScriptCore/wtf/text/StringHash.h

    r95090 r98624  
    5454                return false;
    5555
     56            if (a->is8Bit()) {
     57                if (b->is8Bit()) {
     58                    // Both a & b are 8 bit.
     59                    const LChar* aChars = a->characters8();
     60                    const LChar* bChars = b->characters8();
     61
     62                    unsigned i = 0;
     63
     64                    // FIXME: perhaps we should have a more abstract macro that indicates when
     65                    // going 4 bytes at a time is unsafe
     66#if (CPU(X86) || CPU(X86_64))
     67                    const unsigned charsPerInt = sizeof(uint32_t) / sizeof(char);
     68                   
     69                    if (aLength > charsPerInt) {
     70                        unsigned stopCount = aLength & ~(charsPerInt - 1);
     71                       
     72                        const uint32_t* aIntCharacters = reinterpret_cast<const uint32_t*>(aChars);
     73                        const uint32_t* bIntCharacters = reinterpret_cast<const uint32_t*>(bChars);
     74                        for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j) {
     75                            if (aIntCharacters[j] != bIntCharacters[j])
     76                                return false;
     77                        }
     78                    }
     79#endif
     80                    for (; i < aLength; ++i) {
     81                        if (aChars[i] != bChars[i])
     82                            return false;
     83                    }
     84                   
     85                    return true;
     86                }
     87
     88                // We know that a is 8 bit & b is 16 bit.
     89                const LChar* aChars = a->characters8();
     90                const UChar* bChars = b->characters16();
     91                for (unsigned i = 0; i != aLength; ++i) {
     92                    if (*aChars++ != *bChars++)
     93                        return false;
     94                }
     95
     96                return true;
     97            }
     98
     99            if (b->is8Bit()) {
     100                // We know that a is 8 bit and b is 16 bit.
     101                const UChar* aChars = a->characters16();
     102                const LChar* bChars = b->characters8();
     103                for (unsigned i = 0; i != aLength; ++i) {
     104                    if (*aChars++ != *bChars++)
     105                        return false;
     106                }
     107
     108                return true;
     109            }
     110
     111            // Both a & b are 16 bit.
    56112            // FIXME: perhaps we should have a more abstract macro that indicates when
    57113            // going 4 bytes at a time is unsafe
    58114#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
    59             const UChar* aChars = a->characters();
    60             const UChar* bChars = b->characters();
     115            const UChar* aChars = a->characters16();
     116            const UChar* bChars = b->characters16();
    61117            for (unsigned i = 0; i != aLength; ++i) {
    62118                if (*aChars++ != *bChars++)
     
    66122#else
    67123            /* Do it 4-bytes-at-a-time on architectures where it's safe */
    68             const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters());
    69             const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters());
     124            const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters16());
     125            const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters16());
    70126
    71127            unsigned halfLength = aLength >> 1;
     
    113169        }
    114170
    115         static unsigned hash(const char* data, unsigned length)
    116         {
    117             return StringHasher::computeHash<char, foldCase<char> >(data, length);
    118         }
    119 
     171        static unsigned hash(const LChar* data, unsigned length)
     172        {
     173            return StringHasher::computeHash<LChar, foldCase<LChar> >(data, length);
     174        }
     175
     176        static inline unsigned hash(const char* data, unsigned length)
     177        {
     178            return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), length);
     179        }
     180       
    120181        static bool equal(const StringImpl* a, const StringImpl* b)
    121182        {
  • trunk/Source/JavaScriptCore/wtf/text/StringImpl.cpp

    r98316 r98624  
    5656
    5757    BufferOwnership ownership = bufferOwnership();
     58
     59    if (has16BitShadow()) {
     60        ASSERT(m_copyData16);
     61        fastFree(m_copyData16);
     62    }
     63
    5864    if (ownership == BufferInternal)
    5965        return;
    6066    if (ownership == BufferOwned) {
    61         ASSERT(m_data);
    62         fastFree(const_cast<UChar*>(m_data));
     67        // We use m_data8, but since it is a union with m_data16 this works either way.
     68        ASSERT(m_data8);
     69        fastFree(const_cast<LChar*>(m_data8));
    6370        return;
    6471    }
     
    6774    ASSERT(m_substringBuffer);
    6875    m_substringBuffer->deref();
     76}
     77
     78PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data)
     79{
     80    if (!length) {
     81        data = 0;
     82        return empty();
     83    }
     84
     85    // Allocate a single buffer large enough to contain the StringImpl
     86    // struct as well as the data which it contains. This removes one
     87    // heap allocation from this call.
     88    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar)))
     89        CRASH();
     90    size_t size = sizeof(StringImpl) + length * sizeof(LChar);
     91    StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
     92
     93    data = reinterpret_cast<LChar*>(string + 1);
     94    return adoptRef(new (string) StringImpl(length, Force8BitConstructor));
    6995}
    7096
     
    119145}
    120146
    121 PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
     147PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length)
    122148{
    123149    if (!characters || !length)
     
    133159}
    134160
    135 PassRefPtr<StringImpl> StringImpl::create(const char* string)
     161PassRefPtr<StringImpl> StringImpl::create(const LChar* string)
    136162{
    137163    if (!string)
    138164        return empty();
    139     size_t length = strlen(string);
     165    size_t length = strlen(reinterpret_cast<const char*>(string));
    140166    if (length > numeric_limits<unsigned>::max())
    141167        CRASH();
     
    143169}
    144170
     171const UChar* StringImpl::getData16SlowCase() const
     172{
     173    if (has16BitShadow())
     174        return m_copyData16;
     175
     176    if (bufferOwnership() == BufferSubstring) {
     177        // If this is a substring, return a pointer into the parent string.
     178        // TODO: Consider severing this string from the parent string
     179        unsigned offset = m_data8 - m_substringBuffer->characters8();
     180        return m_substringBuffer->characters16() + offset;
     181    }
     182
     183    unsigned len = length();
     184    m_copyData16 = static_cast<UChar*>(fastMalloc(len * sizeof(UChar)));
     185    for (size_t i = 0; i < len; i++)
     186        m_copyData16[i] = m_data8[i];
     187
     188    m_hashAndFlags |= s_hashFlagHas16BitShadow;
     189
     190    return m_copyData16;
     191}
     192
    145193bool StringImpl::containsOnlyWhitespace()
    146194{
     
    148196    // that are not whitespace from the point of view of RenderText; I wonder if
    149197    // that's a problem in practice.
    150     for (unsigned i = 0; i < m_length; i++)
    151         if (!isASCIISpace(m_data[i]))
     198    if (is8Bit()) {
     199        for (unsigned i = 0; i < m_length; i++) {
     200            UChar c = m_data8[i];
     201            if (!isASCIISpace(c))
     202                return false;
     203        }
     204
     205        return true;
     206    }
     207
     208    for (unsigned i = 0; i < m_length; i++) {
     209        UChar c = m_data16[i];
     210        if (!isASCIISpace(c))
    152211            return false;
     212    }
    153213    return true;
    154214}
     
    164224        length = maxLength;
    165225    }
    166     return create(m_data + start, length);
     226    if (is8Bit())
     227        return create(m_data8 + start, length);
     228
     229    return create(m_data16 + start, length);
    167230}
    168231
    169232UChar32 StringImpl::characterStartingAt(unsigned i)
    170233{
    171     if (U16_IS_SINGLE(m_data[i]))
    172         return m_data[i];
    173     if (i + 1 < m_length && U16_IS_LEAD(m_data[i]) && U16_IS_TRAIL(m_data[i + 1]))
    174         return U16_GET_SUPPLEMENTARY(m_data[i], m_data[i + 1]);
     234    if (is8Bit())
     235        return m_data8[i];
     236    if (U16_IS_SINGLE(m_data16[i]))
     237        return m_data16[i];
     238    if (i + 1 < m_length && U16_IS_LEAD(m_data16[i]) && U16_IS_TRAIL(m_data16[i + 1]))
     239        return U16_GET_SUPPLEMENTARY(m_data16[i], m_data16[i + 1]);
    175240    return 0;
    176241}
     
    182247   
    183248    // First scan the string for uppercase and non-ASCII characters:
     249    bool noUpper = true;
    184250    UChar ored = 0;
    185     bool noUpper = true;
    186     const UChar *end = m_data + m_length;
    187     for (const UChar* chp = m_data; chp != end; chp++) {
     251    if (is8Bit()) {
     252        const LChar* end = m_data8 + m_length;
     253        for (const LChar* chp = m_data8; chp != end; chp++) {
     254            if (UNLIKELY(isASCIIUpper(*chp)))
     255                noUpper = false;
     256            ored |= *chp;
     257        }
     258        // Nothing to do if the string is all ASCII with no uppercase.
     259        if (noUpper && !(ored & ~0x7F))
     260            return this;
     261
     262        if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
     263            CRASH();
     264        int32_t length = m_length;
     265
     266        LChar* data8;
     267        RefPtr<StringImpl> newImpl = createUninitialized(length, data8);
     268
     269        if (!(ored & ~0x7F)) {
     270            for (int32_t i = 0; i < length; i++)
     271                data8[i] = toASCIILower(m_data8[i]);
     272
     273            return newImpl.release();
     274        }
     275
     276        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
     277        for (int32_t i = 0; i < length; i++)
     278            data8[i] = static_cast<LChar>(Unicode::toLower(m_data8[i]));
     279
     280        return newImpl.release();
     281    }
     282
     283    const UChar *end = m_data16 + m_length;
     284    for (const UChar* chp = m_data16; chp != end; chp++) {
    188285        if (UNLIKELY(isASCIIUpper(*chp)))
    189286            noUpper = false;
    190287        ored |= *chp;
    191288    }
    192    
    193289    // Nothing to do if the string is all ASCII with no uppercase.
    194290    if (noUpper && !(ored & ~0x7F))
     
    199295    int32_t length = m_length;
    200296
    201     UChar* data;
    202     RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
    203 
    204297    if (!(ored & ~0x7F)) {
    205         // Do a faster loop for the case where all the characters are ASCII.
    206         for (int i = 0; i < length; i++) {
    207             UChar c = m_data[i];
    208             data[i] = toASCIILower(c);
    209         }
    210         return newImpl;
     298        UChar* data16;
     299        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
     300       
     301        for (int32_t i = 0; i < length; i++) {
     302            UChar c = m_data16[i];
     303            data16[i] = toASCIILower(c);
     304        }
     305        return newImpl.release();
    211306    }
    212307   
    213308    // Do a slower implementation for cases that include non-ASCII characters.
     309    UChar* data16;
     310    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
     311
    214312    bool error;
    215     int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error);
     313    int32_t realLength = Unicode::toLower(data16, length, m_data16, m_length, &error);
    216314    if (!error && realLength == length)
    217         return newImpl;
    218     newImpl = createUninitialized(realLength, data);
    219     Unicode::toLower(data, realLength, m_data, m_length, &error);
     315        return newImpl.release();
     316
     317    newImpl = createUninitialized(realLength, data16);
     318    Unicode::toLower(data16, realLength, m_data16, m_length, &error);
    220319    if (error)
    221320        return this;
    222     return newImpl;
     321    return newImpl.release();
    223322}
    224323
     
    228327    // but in empirical testing, few actual calls to upper() are no-ops, so
    229328    // it wouldn't be worth the extra time for pre-scanning.
    230     UChar* data;
    231     RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
    232329
    233330    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
     
    235332    int32_t length = m_length;
    236333
     334    if (is8Bit()) {
     335        LChar* data8;
     336        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8);
     337       
     338        // Do a faster loop for the case where all the characters are ASCII.
     339        char ored = 0;
     340        for (int i = 0; i < length; i++) {
     341            char c = m_data8[i];
     342            ored |= c;
     343            data8[i] = toASCIIUpper(c);
     344        }
     345        if (!(ored & ~0x7F))
     346            return newImpl.release();
     347
     348        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
     349        for (int32_t i = 0; i < length; i++)
     350            data8[i] = static_cast<LChar>(Unicode::toUpper(m_data8[i]));
     351
     352        return newImpl.release();
     353    }
     354
     355    UChar* data16;
     356    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16);
     357   
    237358    // Do a faster loop for the case where all the characters are ASCII.
    238359    UChar ored = 0;
    239360    for (int i = 0; i < length; i++) {
    240         UChar c = m_data[i];
     361        UChar c = m_data16[i];
    241362        ored |= c;
    242         data[i] = toASCIIUpper(c);
     363        data16[i] = toASCIIUpper(c);
    243364    }
    244365    if (!(ored & ~0x7F))
     
    247368    // Do a slower implementation for cases that include non-ASCII characters.
    248369    bool error;
    249     int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error);
     370    newImpl = createUninitialized(m_length, data16);
     371    int32_t realLength = Unicode::toUpper(data16, length, m_data16, m_length, &error);
    250372    if (!error && realLength == length)
    251373        return newImpl;
    252     newImpl = createUninitialized(realLength, data);
    253     Unicode::toUpper(data, realLength, m_data, m_length, &error);
     374    newImpl = createUninitialized(realLength, data16);
     375    Unicode::toUpper(data16, realLength, m_data16, m_length, &error);
    254376    if (error)
    255377        return this;
     
    262384        return this;
    263385
     386    if (!(character & ~0x7F)) {
     387        LChar* data;
     388        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
     389        for (unsigned i = 0; i < m_length; ++i)
     390            data[i] = character;
     391        return newImpl.release();
     392    }
    264393    UChar* data;
    265394    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
     
    271400PassRefPtr<StringImpl> StringImpl::foldCase()
    272401{
    273     UChar* data;
    274     RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
    275 
    276402    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
    277403        CRASH();
    278404    int32_t length = m_length;
    279405
     406    if (is8Bit()) {
     407        // Do a faster loop for the case where all the characters are ASCII.
     408        LChar* data;
     409        RefPtr <StringImpl>newImpl = createUninitialized(m_length, data);
     410        LChar ored = 0;
     411
     412        for (int32_t i = 0; i < length; i++) {
     413            LChar c = m_data8[i];
     414            data[i] = toASCIILower(c);
     415            ored |= c;
     416        }
     417
     418        if (!(ored & ~0x7F))
     419            return newImpl.release();
     420
     421        // Do a slower implementation for cases that include non-ASCII Latin-1 characters.
     422        for (int32_t i = 0; i < length; i++)
     423            data[i] = static_cast<LChar>(Unicode::toLower(m_data8[i]));
     424    }
     425
    280426    // Do a faster loop for the case where all the characters are ASCII.
     427    UChar* data;
     428    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
    281429    UChar ored = 0;
    282430    for (int32_t i = 0; i < length; i++) {
    283         UChar c = m_data[i];
     431        UChar c = m_data16[i];
    284432        ored |= c;
    285433        data[i] = toASCIILower(c);
     
    290438    // Do a slower implementation for cases that include non-ASCII characters.
    291439    bool error;
    292     int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error);
     440    int32_t realLength = Unicode::foldCase(data, length, m_data16, m_length, &error);
    293441    if (!error && realLength == length)
    294442        return newImpl.release();
    295443    newImpl = createUninitialized(realLength, data);
    296     Unicode::foldCase(data, realLength, m_data, m_length, &error);
     444    Unicode::foldCase(data, realLength, m_data16, m_length, &error);
    297445    if (error)
    298446        return this;
     
    310458   
    311459    // skip white space from start
    312     while (start <= end && predicate(m_data[start]))
     460    while (start <= end && predicate(is8Bit() ? m_data8[start] : m_data16[start]))
    313461        start++;
    314462   
     
    318466
    319467    // skip white space from end
    320     while (end && predicate(m_data[end]))
     468    while (end && predicate(is8Bit() ? m_data8[end] : m_data16[end]))
    321469        end--;
    322470
    323471    if (!start && end == m_length - 1)
    324472        return this;
    325     return create(m_data + start, end + 1 - start);
     473    if (is8Bit())
     474        return create(m_data8 + start, end + 1 - start);
     475    return create(m_data16 + start, end + 1 - start);
    326476}
    327477
     
    357507}
    358508
     509// FIXME: Add 8-bit path. Likely requires templatized StringBuffer class
    359510PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
    360511{
    361     const UChar* from = m_data;
     512    const UChar* from = characters();
    362513    const UChar* fromend = from + m_length;
    363514
     
    370521    StringBuffer data(m_length);
    371522    UChar* to = data.characters();
    372     unsigned outc = from - m_data;
     523    unsigned outc = from - characters16();
    373524
    374525    if (outc)
    375         memcpy(to, m_data, outc * sizeof(UChar));
     526        memcpy(to, characters16(), outc * sizeof(UChar));
    376527
    377528    while (true) {
     
    389540}
    390541
     542// FIXME: Add 8-bit path. Likely requires templatized StringBuffer class
    391543template <class UCharPredicate>
    392544inline PassRefPtr<StringImpl> StringImpl::simplifyMatchedCharactersToSpace(UCharPredicate predicate)
     
    394546    StringBuffer data(m_length);
    395547
    396     const UChar* from = m_data;
     548    const UChar* from = characters16();
    397549    const UChar* fromend = from + m_length;
    398550    int outc = 0;
     
    438590int StringImpl::toIntStrict(bool* ok, int base)
    439591{
    440     return charactersToIntStrict(m_data, m_length, ok, base);
     592    return charactersToIntStrict(characters16(), m_length, ok, base);
    441593}
    442594
    443595unsigned StringImpl::toUIntStrict(bool* ok, int base)
    444596{
    445     return charactersToUIntStrict(m_data, m_length, ok, base);
     597    return charactersToUIntStrict(characters16(), m_length, ok, base);
    446598}
    447599
    448600int64_t StringImpl::toInt64Strict(bool* ok, int base)
    449601{
    450     return charactersToInt64Strict(m_data, m_length, ok, base);
     602    return charactersToInt64Strict(characters16(), m_length, ok, base);
     603
    451604}
    452605
    453606uint64_t StringImpl::toUInt64Strict(bool* ok, int base)
    454607{
    455     return charactersToUInt64Strict(m_data, m_length, ok, base);
     608    return charactersToUInt64Strict(characters16(), m_length, ok, base);
    456609}
    457610
    458611intptr_t StringImpl::toIntPtrStrict(bool* ok, int base)
    459612{
    460     return charactersToIntPtrStrict(m_data, m_length, ok, base);
     613    return charactersToIntPtrStrict(characters16(), m_length, ok, base);
    461614}
    462615
    463616int StringImpl::toInt(bool* ok)
    464617{
    465     return charactersToInt(m_data, m_length, ok);
     618    return charactersToInt(characters16(), m_length, ok);
    466619}
    467620
    468621unsigned StringImpl::toUInt(bool* ok)
    469622{
    470     return charactersToUInt(m_data, m_length, ok);
     623    return charactersToUInt(characters16(), m_length, ok);
    471624}
    472625
    473626int64_t StringImpl::toInt64(bool* ok)
    474627{
    475     return charactersToInt64(m_data, m_length, ok);
     628    return charactersToInt64(characters16(), m_length, ok);
    476629}
    477630
    478631uint64_t StringImpl::toUInt64(bool* ok)
    479632{
    480     return charactersToUInt64(m_data, m_length, ok);
     633    return charactersToUInt64(characters16(), m_length, ok);
    481634}
    482635
    483636intptr_t StringImpl::toIntPtr(bool* ok)
    484637{
    485     return charactersToIntPtr(m_data, m_length, ok);
     638    return charactersToIntPtr(characters16(), m_length, ok);
     639
    486640}
    487641
    488642double StringImpl::toDouble(bool* ok, bool* didReadNumber)
    489643{
    490     return charactersToDouble(m_data, m_length, ok, didReadNumber);
     644    return charactersToDouble(characters16(), m_length, ok, didReadNumber);
    491645}
    492646
    493647float StringImpl::toFloat(bool* ok, bool* didReadNumber)
    494648{
    495     return charactersToFloat(m_data, m_length, ok, didReadNumber);
    496 }
    497 
    498 static bool equal(const UChar* a, const char* b, int length)
     649    return charactersToFloat(characters16(), m_length, ok, didReadNumber);
     650}
     651
     652static bool equal(const UChar* a, const LChar* b, int length)
    499653{
    500654    ASSERT(length >= 0);
     
    507661}
    508662
    509 bool equalIgnoringCase(const UChar* a, const char* b, unsigned length)
     663bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
    510664{
    511665    while (length--) {
     
    548702size_t StringImpl::find(UChar c, unsigned start)
    549703{
    550     return WTF::find(m_data, m_length, c, start);
     704    return WTF::find(characters16(), m_length, c, start);
    551705}
    552706
    553707size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start)
    554708{
    555     return WTF::find(m_data, m_length, matchFunction, start);
    556 }
    557 
    558 size_t StringImpl::find(const char* matchString, unsigned index)
     709    return WTF::find(characters16(), m_length, matchFunction, start);
     710}
     711
     712size_t StringImpl::find(const LChar* matchString, unsigned index)
    559713{
    560714    // Check for null or empty string to match against
    561715    if (!matchString)
    562716        return notFound;
    563     size_t matchStringLength = strlen(matchString);
     717    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
    564718    if (matchStringLength > numeric_limits<unsigned>::max())
    565719        CRASH();
     
    570724    // Optimization 1: fast case for strings of length 1.
    571725    if (matchLength == 1)
    572         return WTF::find(characters(), length(), *(const unsigned char*)matchString, index);
     726        return WTF::find(characters16(), length(), *matchString, index);
    573727
    574728    // Check index & matchLength are in range.
     
    582736
    583737    const UChar* searchCharacters = characters() + index;
    584     const unsigned char* matchCharacters = (const unsigned char*)matchString;
    585738
    586739    // Optimization 2: keep a running hash of the strings,
     
    590743    for (unsigned i = 0; i < matchLength; ++i) {
    591744        searchHash += searchCharacters[i];
    592         matchHash += matchCharacters[i];
     745        matchHash += matchString[i];
    593746    }
    594747
     
    605758}
    606759
    607 size_t StringImpl::findIgnoringCase(const char* matchString, unsigned index)
     760size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
    608761{
    609762    // Check for null or empty string to match against
    610763    if (!matchString)
    611764        return notFound;
    612     size_t matchStringLength = strlen(matchString);
     765    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
    613766    if (matchStringLength > numeric_limits<unsigned>::max())
    614767        CRASH();
     
    649802    // Optimization 1: fast case for strings of length 1.
    650803    if (matchLength == 1)
    651         return WTF::find(characters(), length(), matchString->characters()[0], index);
     804        return WTF::find(characters16(), length(), matchString->characters16()[0], index);
    652805
    653806    // Check index & matchLength are in range.
     
    717870size_t StringImpl::reverseFind(UChar c, unsigned index)
    718871{
    719     return WTF::reverseFind(m_data, m_length, c, index);
     872    return WTF::reverseFind(characters16(), m_length, c, index);
    720873}
    721874
     
    731884    // Optimization 1: fast case for strings of length 1.
    732885    if (matchLength == 1)
    733         return WTF::reverseFind(characters(), length(), matchString->characters()[0], index);
     886        return WTF::reverseFind(characters16(), length(), matchString->characters()[0], index);
    734887
    735888    // Check index & matchLength are in range.
     
    804957        return this;
    805958    unsigned i;
    806     for (i = 0; i != m_length; ++i)
    807         if (m_data[i] == oldC)
     959    for (i = 0; i != m_length; ++i) {
     960        UChar c = is8Bit() ? m_data8[i] : m_data16[i];
     961        if (c == oldC)
    808962            break;
     963    }
    809964    if (i == m_length)
    810965        return this;
    811966
     967    if (is8Bit()) {
     968        if (oldC > 0xff)
     969            // Looking for a 16 bit char in an 8 bit string, we're done.
     970            return this;
     971
     972        if (newC <= 0xff) {
     973            LChar* data;
     974            LChar oldChar = static_cast<LChar>(oldC);
     975            LChar newChar = static_cast<LChar>(newC);
     976
     977            RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
     978
     979            for (i = 0; i != m_length; ++i) {
     980                char ch = m_data8[i];
     981                if (ch == oldChar)
     982                    ch = newChar;
     983                data[i] = ch;
     984            }
     985            return newImpl.release();
     986        }
     987
     988        // There is the possibility we need to up convert from 8 to 16 bit,
     989        // create a 16 bit string for the result.
     990        UChar* data;
     991        RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
     992
     993        for (i = 0; i != m_length; ++i) {
     994            UChar ch = m_data8[i];
     995            if (ch == oldC)
     996                ch = newC;
     997            data[i] = ch;
     998        }
     999
     1000        return newImpl.release();
     1001    }
     1002
    8121003    UChar* data;
    8131004    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
    8141005
    8151006    for (i = 0; i != m_length; ++i) {
    816         UChar ch = m_data[i];
     1007        UChar ch = m_data16[i];
    8171008        if (ch == oldC)
    8181009            ch = newC;
     
    8291020    if (!lengthToReplace && !lengthToInsert)
    8301021        return this;
    831     UChar* data;
    8321022
    8331023    if ((length() - lengthToReplace) >= (numeric_limits<unsigned>::max() - lengthToInsert))
    8341024        CRASH();
    8351025
     1026    if (is8Bit() && (!str || str->is8Bit())) {
     1027        LChar* data;
     1028        RefPtr<StringImpl> newImpl =
     1029        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
     1030        memcpy(data, m_data8, position * sizeof(LChar));
     1031        if (str)
     1032            memcpy(data + position, str->m_data8, lengthToInsert * sizeof(LChar));
     1033        memcpy(data + position + lengthToInsert, m_data8 + position + lengthToReplace,
     1034               (length() - position - lengthToReplace) * sizeof(LChar));
     1035        return newImpl.release();
     1036    }
     1037    UChar* data;
    8361038    RefPtr<StringImpl> newImpl =
    8371039        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
    838     memcpy(data, characters(), position * sizeof(UChar));
    839     if (str)
    840         memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar));
    841     memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace,
    842         (length() - position - lengthToReplace) * sizeof(UChar));
     1040    if (is8Bit())
     1041        for (unsigned i = 0; i < position; i++)
     1042            data[i] = m_data8[i];
     1043    else
     1044        memcpy(data, m_data16, position * sizeof(UChar));
     1045    if (str) {
     1046        if (str->is8Bit())
     1047            for (unsigned i = 0; i < lengthToInsert; i++)
     1048                data[i + position] = str->m_data8[i];
     1049        else
     1050            memcpy(data + position, str->m_data16, lengthToInsert * sizeof(UChar));
     1051    }
     1052    if (is8Bit()) {
     1053        for (unsigned i = 0; i < length() - position - lengthToReplace; i++)
     1054            data[i + position + lengthToInsert] = m_data8[i + position + lengthToReplace];
     1055    } else {
     1056        memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace,
     1057            (length() - position - lengthToReplace) * sizeof(UChar));
     1058    }
    8431059    return newImpl.release();
    8441060}
     
    8531069    unsigned matchCount = 0;
    8541070   
    855     // Count the matches
     1071    // Count the matches.
    8561072    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
    8571073        ++matchCount;
     
    8591075    }
    8601076   
    861     // If we have 0 matches, we don't have to do any more work
     1077    // If we have 0 matches then we don't have to do any more work to do.
    8621078    if (!matchCount)
    8631079        return this;
     
    8731089    newSize += replaceSize;
    8741090
    875     UChar* data;
    876     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
    877 
    878     // Construct the new data
     1091    // Construct the new data.
    8791092    size_t srcSegmentEnd;
    8801093    unsigned srcSegmentLength;
    8811094    srcSegmentStart = 0;
    8821095    unsigned dstOffset = 0;
    883    
     1096    bool srcIs8Bit = is8Bit();
     1097    bool replacementIs8Bit = replacement->is8Bit();
     1098   
     1099    // There are 4 cases:
     1100    // 1. This and replacement are both 8 bit.
     1101    // 2. This and replacement are both 16 bit.
     1102    // 3. This is 8 bit and replacement is 16 bit.
     1103    // 4. This is 16 bit and replacement is 8 bit.
     1104    if (srcIs8Bit && replacementIs8Bit) {
     1105        // Case 1
     1106        LChar* data;
     1107        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
     1108
     1109        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
     1110            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
     1111            memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar));
     1112            dstOffset += srcSegmentLength;
     1113            memcpy(data + dstOffset, replacement->m_data8, repStrLength * sizeof(LChar));
     1114            dstOffset += repStrLength;
     1115            srcSegmentStart = srcSegmentEnd + 1;
     1116        }
     1117
     1118        srcSegmentLength = m_length - srcSegmentStart;
     1119        memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar));
     1120
     1121        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
     1122
     1123        return newImpl.release();
     1124    }
     1125
     1126    UChar* data;
     1127    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
     1128
    8841129    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
    8851130        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
    886         memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1131        if (srcIs8Bit) {
     1132            // Case 3.
     1133            for (unsigned i = 0; i < srcSegmentLength; i++)
     1134                data[i + dstOffset] = m_data8[i + srcSegmentStart];
     1135        } else {
     1136            // Cases 2 & 4.
     1137            memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1138        }
    8871139        dstOffset += srcSegmentLength;
    888         memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
     1140        if (replacementIs8Bit) {
     1141            // Case 4.
     1142            for (unsigned i = 0; i < repStrLength; i++)
     1143                data[i + dstOffset] = replacement->m_data8[i];
     1144        } else {
     1145            // Cases 2 & 3.
     1146            memcpy(data + dstOffset, replacement->m_data16, repStrLength * sizeof(UChar));
     1147        }
    8891148        dstOffset += repStrLength;
    8901149        srcSegmentStart = srcSegmentEnd + 1;
     
    8921151
    8931152    srcSegmentLength = m_length - srcSegmentStart;
    894     memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1153    if (srcIs8Bit) {
     1154        // Case 3.
     1155        for (unsigned i = 0; i < srcSegmentLength; i++)
     1156            data[i + dstOffset] = m_data8[i + srcSegmentStart];
     1157    } else {
     1158        // Cases 2 & 4.
     1159        memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1160    }
    8951161
    8961162    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
     
    9121178    unsigned matchCount = 0;
    9131179   
    914     // Count the matches
     1180    // Count the matches.
    9151181    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
    9161182        ++matchCount;
     
    9311197    newSize += matchCount * repStrLength;
    9321198
    933     UChar* data;
    934     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
    9351199   
    9361200    // Construct the new data
     
    9391203    srcSegmentStart = 0;
    9401204    unsigned dstOffset = 0;
    941    
     1205    bool srcIs8Bit = is8Bit();
     1206    bool replacementIs8Bit = replacement->is8Bit();
     1207   
     1208    // There are 4 cases:
     1209    // 1. This and replacement are both 8 bit.
     1210    // 2. This and replacement are both 16 bit.
     1211    // 3. This is 8 bit and replacement is 16 bit.
     1212    // 4. This is 16 bit and replacement is 8 bit.
     1213    if (srcIs8Bit && replacementIs8Bit) {
     1214        // Case 1
     1215        LChar* data;
     1216        RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
     1217        while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
     1218            srcSegmentLength = srcSegmentEnd - srcSegmentStart;
     1219            memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar));
     1220            dstOffset += srcSegmentLength;
     1221            memcpy(data + dstOffset, replacement->m_data8, repStrLength * sizeof(LChar));
     1222            dstOffset += repStrLength;
     1223            srcSegmentStart = srcSegmentEnd + patternLength;
     1224        }
     1225
     1226        srcSegmentLength = m_length - srcSegmentStart;
     1227        memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar));
     1228
     1229        ASSERT(dstOffset + srcSegmentLength == newImpl->length());
     1230
     1231        return newImpl.release();
     1232    }
     1233
     1234    UChar* data;
     1235    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
    9421236    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
    9431237        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
    944         memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1238        if (srcIs8Bit) {
     1239            // Case 3.
     1240            for (unsigned i = 0; i < srcSegmentLength; i++)
     1241                data[i + dstOffset] = m_data8[i + srcSegmentStart];
     1242        } else {
     1243            // Case 2 & 4.
     1244            memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1245        }
    9451246        dstOffset += srcSegmentLength;
    946         memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
     1247        if (replacementIs8Bit) {
     1248            // Cases 2 & 3.
     1249            for (unsigned i = 0; i < repStrLength; i++)
     1250                data[i + dstOffset] = replacement->m_data8[i];
     1251        } else {
     1252            // Case 4
     1253            memcpy(data + dstOffset, replacement->m_data16, repStrLength * sizeof(UChar));
     1254        }
    9471255        dstOffset += repStrLength;
    9481256        srcSegmentStart = srcSegmentEnd + patternLength;
     
    9501258
    9511259    srcSegmentLength = m_length - srcSegmentStart;
    952     memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1260    if (srcIs8Bit) {
     1261        // Case 3.
     1262        for (unsigned i = 0; i < srcSegmentLength; i++)
     1263            data[i + dstOffset] = m_data8[i + srcSegmentStart];
     1264    } else {
     1265        // Cases 2 & 4.
     1266        memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar));
     1267    }
    9531268
    9541269    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
     
    9621277}
    9631278
    964 bool equal(const StringImpl* a, const char* b)
     1279bool equal(const StringImpl* a, const LChar* b, unsigned length)
    9651280{
    9661281    if (!a)
     
    9691284        return !a;
    9701285
     1286    if (length != a->length())
     1287        return false;
     1288
     1289    if (a->is8Bit()) {
     1290        const LChar* aChars = a->characters8();
     1291
     1292        for (unsigned i = 0; i != length; ++i) {
     1293            unsigned char bc = b[i];
     1294            unsigned char ac = aChars[i];
     1295            if (!bc)
     1296                return false;
     1297            if (ac != bc)
     1298                return false;
     1299        }
     1300
     1301        return true;
     1302    }
     1303
     1304    const UChar* aChars = a->characters16();
     1305
     1306    for (unsigned i = 0; i != length; ++i) {
     1307        UChar bc = b[i];
     1308        UChar ac = aChars[i];
     1309        if (!bc)
     1310            return false;
     1311        if (ac != bc)
     1312            return false;
     1313    }
     1314
     1315    return true;
     1316}
     1317
     1318bool equal(const StringImpl* a, const LChar* b)
     1319{
     1320    if (!a)
     1321        return !b;
     1322    if (!b)
     1323        return !a;
     1324
    9711325    unsigned length = a->length();
    972     const UChar* as = a->characters();
     1326
     1327    if (a->is8Bit()) {
     1328        const LChar* aPtr = a->characters8();
     1329        for (unsigned i = 0; i != length; ++i) {
     1330            unsigned char bc = b[i];
     1331            unsigned char ac = aPtr[i];
     1332            if (!bc)
     1333                return false;
     1334            if (ac != bc)
     1335                return false;
     1336        }
     1337
     1338        return !b[length];
     1339    }
     1340
     1341    const UChar* aPtr = a->characters16();
    9731342    for (unsigned i = 0; i != length; ++i) {
    9741343        unsigned char bc = b[i];
    9751344        if (!bc)
    9761345            return false;
    977         if (as[i] != bc)
     1346        if (aPtr[i] != bc)
    9781347            return false;
    9791348    }
     
    10001369    return true;
    10011370#else
    1002     /* Do it 4-bytes-at-a-time on architectures where it's safe */
    1003    
    1004     const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a->characters());
     1371    if (a->is8Bit()) {
     1372        const LChar* as = a->characters8();
     1373        for (unsigned i = 0; i != length; ++i)
     1374            if (as[i] != b[i])
     1375                return false;
     1376        return true;
     1377    }
     1378
     1379    // Do comparison 4-bytes-at-a-time on architectures where it's safe.
     1380
     1381    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a->characters16());
    10051382    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
    1006    
     1383
    10071384    unsigned halfLength = length >> 1;
    10081385    for (unsigned i = 0; i != halfLength; ++i) {
     
    10101387            return false;
    10111388    }
    1012    
     1389
    10131390    if (length & 1 &&  *reinterpret_cast<const uint16_t*>(aCharacters) != *reinterpret_cast<const uint16_t*>(bCharacters))
    10141391        return false;
    1015    
     1392
    10161393    return true;
    10171394#endif
     
    10231400}
    10241401
    1025 bool equalIgnoringCase(StringImpl* a, const char* b)
     1402bool equalIgnoringCase(StringImpl* a, const LChar* b)
    10261403{
    10271404    if (!a)
     
    10311408
    10321409    unsigned length = a->length();
    1033     const UChar* as = a->characters();
    10341410
    10351411    // Do a faster loop for the case where all the characters are ASCII.
    10361412    UChar ored = 0;
    10371413    bool equal = true;
     1414    if (a->is8Bit()) {
     1415        const LChar* as = a->characters8();
     1416        for (unsigned i = 0; i != length; ++i) {
     1417            LChar bc = b[i];
     1418            if (!bc)
     1419                return false;
     1420            UChar ac = as[i];
     1421            ored |= ac;
     1422            equal = equal && (toASCIILower(ac) == toASCIILower(bc));
     1423        }
     1424       
     1425        // Do a slower implementation for cases that include non-ASCII characters.
     1426        if (ored & ~0x7F) {
     1427            equal = true;
     1428            for (unsigned i = 0; i != length; ++i)
     1429                equal = equal && (foldCase(as[i]) == foldCase(b[i]));
     1430        }
     1431       
     1432        return equal && !b[length];       
     1433    }
     1434
     1435    const UChar* as = a->characters16();
    10381436    for (unsigned i = 0; i != length; ++i) {
    1039         char bc = b[i];
     1437        LChar bc = b[i];
    10401438        if (!bc)
    10411439            return false;
     
    10491447        equal = true;
    10501448        for (unsigned i = 0; i != length; ++i) {
    1051             unsigned char bc = b[i];
    1052             equal = equal && (foldCase(as[i]) == foldCase(bc));
     1449            equal = equal && (foldCase(as[i]) == foldCase(b[i]));
    10531450        }
    10541451    }
     
    10721469{
    10731470    for (unsigned i = 0; i < m_length; ++i) {
    1074         WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]);
     1471        WTF::Unicode::Direction charDirection = WTF::Unicode::direction(is8Bit() ? m_data8[i] : m_data16[i]);
    10751472        if (charDirection == WTF::Unicode::LeftToRight) {
    10761473            if (hasStrongDirectionality)
     
    10911488PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer& buffer)
    10921489{
     1490    // FIXME: handle 8-bit StringBuffer when it exists.
    10931491    unsigned length = buffer.length();
    10941492    if (length == 0)
     
    11011499    // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
    11021500    // get allocated in a single memory block.
    1103     UChar* data;
    11041501    unsigned length = string.m_length;
    11051502    if (length >= numeric_limits<unsigned>::max())
    11061503        CRASH();
    1107     RefPtr<StringImpl> terminatedString = createUninitialized(length + 1, data);
    1108     memcpy(data, string.m_data, length * sizeof(UChar));
    1109     data[length] = 0;
     1504    RefPtr<StringImpl> terminatedString;
     1505    if (string.is8Bit()) {
     1506        LChar* data;
     1507        terminatedString = createUninitialized(length + 1, data);
     1508        memcpy(data, string.m_data8, length * sizeof(LChar));
     1509        data[length] = 0;
     1510    } else {
     1511        UChar* data;
     1512        terminatedString = createUninitialized(length + 1, data);
     1513        memcpy(data, string.m_data16, length * sizeof(UChar));
     1514        data[length] = 0;
     1515    }
    11101516    terminatedString->m_length--;
    11111517    terminatedString->m_hashAndFlags = (string.m_hashAndFlags & ~s_flagMask) | s_hashFlagHasTerminatingNullCharacter;
  • trunk/Source/JavaScriptCore/wtf/text/StringImpl.h

    r98495 r98624  
    4545namespace JSC {
    4646struct IdentifierCStringTranslator;
     47struct IdentifierCharBufferTranslator;
    4748struct IdentifierUCharBufferTranslator;
    4849}
     
    6364    WTF_MAKE_NONCOPYABLE(StringImpl); WTF_MAKE_FAST_ALLOCATED;
    6465    friend struct JSC::IdentifierCStringTranslator;
     66    friend struct JSC::IdentifierCharBufferTranslator;
    6567    friend struct JSC::IdentifierUCharBufferTranslator;
    6668    friend struct WTF::CStringTranslator;
     
    8486        : m_refCount(s_refCountFlagIsStaticString)
    8587        , m_length(length)
    86         , m_data(characters)
     88        , m_data16(characters)
    8789        , m_buffer(0)
    8890        , m_hashAndFlags(s_hashFlagIsIdentifier | BufferOwned)
     
    9496    }
    9597
    96     // Create a normal string with internal storage (BufferInternal)
     98    // Used to construct static strings, which have an special refCount that can never hit zero.
     99    // This means that the static string will never be destroyed, which is important because
     100    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
     101    StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTag)
     102        : m_refCount(s_refCountFlagIsStaticString)
     103        , m_length(length)
     104        , m_data8(characters)
     105        , m_buffer(0)
     106        , m_hashAndFlags(s_hashFlag8BitBuffer | s_hashFlagIsIdentifier | BufferOwned)
     107    {
     108        // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
     109        // with impunity. The empty string is special because it is never entered into
     110        // AtomicString's HashKey, but still needs to compare correctly.
     111        hash();
     112    }
     113
     114    // FIXME: there has to be a less hacky way to do this.
     115    enum Force8Bit { Force8BitConstructor };
     116    // Create a normal 8-bit string with internal storage (BufferInternal)
     117    StringImpl(unsigned length, Force8Bit)
     118        : m_refCount(s_refCountIncrement)
     119        , m_length(length)
     120        , m_data8(reinterpret_cast<const LChar*>(this + 1))
     121        , m_buffer(0)
     122        , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal)
     123    {
     124        ASSERT(m_data8);
     125        ASSERT(m_length);
     126    }
     127
     128    // Create a normal 16-bit string with internal storage (BufferInternal)
    97129    StringImpl(unsigned length)
    98130        : m_refCount(s_refCountIncrement)
    99131        , m_length(length)
    100         , m_data(reinterpret_cast<const UChar*>(this + 1))
     132        , m_data16(reinterpret_cast<const UChar*>(this + 1))
    101133        , m_buffer(0)
    102134        , m_hashAndFlags(BufferInternal)
    103135    {
    104         ASSERT(m_data);
     136        ASSERT(m_data16);
    105137        ASSERT(m_length);
    106138    }
     
    110142        : m_refCount(s_refCountIncrement)
    111143        , m_length(length)
    112         , m_data(characters)
     144        , m_data16(characters)
    113145        , m_buffer(0)
    114146        , m_hashAndFlags(BufferOwned)
    115147    {
    116         ASSERT(m_data);
     148        ASSERT(m_data16);
    117149        ASSERT(m_length);
    118150    }
    119151
    120     // Used to create new strings that are a substring of an existing StringImpl (BufferSubstring)
     152    // Used to create new strings that are a substring of an existing 8-bit StringImpl (BufferSubstring)
     153    StringImpl(const LChar* characters, unsigned length, PassRefPtr<StringImpl> base)
     154        : m_refCount(s_refCountIncrement)
     155        , m_length(length)
     156        , m_data8(characters)
     157        , m_substringBuffer(base.leakRef())
     158        , m_hashAndFlags(s_hashFlag8BitBuffer | BufferSubstring)
     159    {
     160        ASSERT(is8Bit());
     161        ASSERT(m_data8);
     162        ASSERT(m_length);
     163        ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
     164    }
     165
     166    // Used to create new strings that are a substring of an existing 16-bit StringImpl (BufferSubstring)
    121167    StringImpl(const UChar* characters, unsigned length, PassRefPtr<StringImpl> base)
    122168        : m_refCount(s_refCountIncrement)
    123169        , m_length(length)
    124         , m_data(characters)
     170        , m_data16(characters)
    125171        , m_substringBuffer(base.leakRef())
    126172        , m_hashAndFlags(BufferSubstring)
    127173    {
    128         ASSERT(m_data);
     174        ASSERT(!is8Bit());
     175        ASSERT(m_data16);
    129176        ASSERT(m_length);
    130177        ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
     
    135182
    136183    static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
    137     static PassRefPtr<StringImpl> create(const char*, unsigned length);
    138     static PassRefPtr<StringImpl> create(const char*);
    139     static ALWAYS_INLINE PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
     184    static PassRefPtr<StringImpl> create(const LChar*, unsigned length);
     185    ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned length) { return create(s, length); };
     186    static PassRefPtr<StringImpl> create(const LChar*);
     187    ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s) { return create(reinterpret_cast<const LChar*>(s)); };
     188
     189    static ALWAYS_INLINE PassRefPtr<StringImpl> create8(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
    140190    {
    141191        ASSERT(rep);
     
    145195            return empty();
    146196
     197        ASSERT(rep->is8Bit());
    147198        StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
    148         return adoptRef(new StringImpl(rep->m_data + offset, length, ownerRep));
    149     }
    150 
     199        return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep));
     200    }
     201
     202    static ALWAYS_INLINE PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
     203    {
     204        ASSERT(rep);
     205        ASSERT(length <= rep->length());
     206
     207        if (!length)
     208            return empty();
     209
     210        StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
     211        if (rep->is8Bit())
     212            return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep));
     213        return adoptRef(new StringImpl(rep->m_data16 + offset, length, ownerRep));
     214    }
     215
     216    static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data);
    151217    static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
    152     static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
     218    template <typename T> static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, T*& output)
    153219    {
    154220        if (!length) {
     
    157223        }
    158224
    159         if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) {
     225        if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(T))) {
    160226            output = 0;
    161227            return 0;
    162228        }
    163229        StringImpl* resultImpl;
    164         if (!tryFastMalloc(sizeof(UChar) * length + sizeof(StringImpl)).getValue(resultImpl)) {
     230        if (!tryFastMalloc(sizeof(T) * length + sizeof(StringImpl)).getValue(resultImpl)) {
    165231            output = 0;
    166232            return 0;
    167233        }
    168         output = reinterpret_cast<UChar*>(resultImpl + 1);
     234        output = reinterpret_cast<T*>(resultImpl + 1);
     235
     236        if (sizeof(T) == sizeof(char))
     237            return adoptRef(new(resultImpl) StringImpl(length, Force8BitConstructor));
     238
    169239        return adoptRef(new(resultImpl) StringImpl(length));
    170240    }
     
    175245    static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data);
    176246
    177     static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data); }
     247    static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); }
     248    static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; }
     249    static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
    178250    static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
    179251
     
    192264
    193265    unsigned length() const { return m_length; }
    194     const UChar* characters() const { return m_data; }
     266    bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; }
     267
     268    // FIXME: Remove all unnecessary usages of characters()
     269    ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); ASSERT_NOT_REACHED(); return m_data8; }
     270    ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; }
     271    ALWAYS_INLINE const UChar* characters() const
     272    {
     273        if (!is8Bit())
     274            return m_data16;
     275
     276        return getData16SlowCase();
     277    }
    195278
    196279    size_t cost()
     
    207290    }
    208291
     292    bool has16BitShadow() const { return m_hashAndFlags & s_hashFlagHas16BitShadow; }
    209293    bool isIdentifier() const { return m_hashAndFlags & s_hashFlagIsIdentifier; }
    210294    void setIsIdentifier(bool isIdentifier)
     
    236320    {
    237321        ASSERT(!hasHash());
    238         ASSERT(hash == StringHasher::computeHash(m_data, m_length)); // Multiple clients assume that StringHasher is the canonical string hash function.
     322        // Multiple clients assume that StringHasher is the canonical string hash function.
     323        ASSERT(hash == (is8Bit() ? StringHasher::computeHash(m_data8, m_length) : StringHasher::computeHash(m_data16, m_length)));
    239324        ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // Verify that enough high bits are empty.
    240325       
     
    265350    unsigned hash() const
    266351    {
    267         if (!hasHash())
    268             setHash(StringHasher::computeHash(m_data, m_length));
     352        if (!hasHash()) {
     353            if (is8Bit())
     354                setHash(StringHasher::computeHash(m_data8, m_length));
     355            else
     356                setHash(StringHasher::computeHash(m_data16, m_length));
     357        }
    269358        return existingHash();
    270359    }
     
    292381    static StringImpl* empty();
    293382
    294     static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
    295     {
     383    // FIXME: Does this really belong in StringImpl?
     384    template <typename T> static void copyChars(T* destination, const T* source, unsigned numCharacters)
     385    {
     386        if (numCharacters == 1) {
     387            *destination = *source;
     388            return;
     389        }
     390
    296391        if (numCharacters <= s_copyCharsInlineCutOff) {
    297             for (unsigned i = 0; i < numCharacters; ++i)
     392            unsigned i = 0;
     393#if (CPU(X86) || CPU(X86_64))
     394            const unsigned charsPerInt = sizeof(uint32_t) / sizeof(T);
     395
     396            if (numCharacters > charsPerInt) {
     397                unsigned stopCount = numCharacters & ~(charsPerInt - 1);
     398
     399                const uint32_t* srcCharacters = reinterpret_cast<const uint32_t*>(source);
     400                uint32_t* destCharacters = reinterpret_cast<uint32_t*>(destination);
     401                for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j)
     402                    destCharacters[j] = srcCharacters[j];
     403            }
     404#endif
     405            for (; i < numCharacters; ++i)
    298406                destination[i] = source[i];
    299407        } else
    300             memcpy(destination, source, numCharacters * sizeof(UChar));
     408            memcpy(destination, source, numCharacters * sizeof(T));
    301409    }
    302410
     
    308416    PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
    309417
    310     UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; }
     418    UChar operator[](unsigned i) const
     419    {
     420        ASSERT(i < m_length);
     421        if (is8Bit())
     422            return m_data8[i];
     423        return m_data16[i];
     424    }
    311425    UChar32 characterStartingAt(unsigned);
    312426
     
    332446
    333447    PassRefPtr<StringImpl> fill(UChar);
     448    // FIXME: Do we need fill(char) or can we just do the right thing if UChar is ASCII?
    334449    PassRefPtr<StringImpl> foldCase();
    335450
     
    341456    PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
    342457
     458    // FIXME: Do we need char version, or is it okay to just pass in an ASCII char for 8-bit? Same for reverseFind, replace
    343459    size_t find(UChar, unsigned index = 0);
    344460    size_t find(CharacterMatchFunctionPtr, unsigned index = 0);
    345     size_t find(const char*, unsigned index = 0);
     461    size_t find(const LChar*, unsigned index = 0);
     462    ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); };
    346463    size_t find(StringImpl*, unsigned index = 0);
    347     size_t findIgnoringCase(const char*, unsigned index = 0);
     464    size_t findIgnoringCase(const LChar*, unsigned index = 0);
     465    ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); };
    348466    size_t findIgnoringCase(StringImpl*, unsigned index = 0);
    349467
     
    377495    template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacters(UCharPredicate);
    378496    template <class UCharPredicate> PassRefPtr<StringImpl> simplifyMatchedCharactersToSpace(UCharPredicate);
     497    NEVER_INLINE const UChar* getData16SlowCase() const;
    379498
    380499    // The bottom bit in the ref count indicates a static (immortal) string.
     
    387506    COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
    388507
     508    static const unsigned s_hashFlagHas16BitShadow = 1u << 7;
     509    static const unsigned s_hashFlag8BitBuffer = 1u << 6;
    389510    static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5;
    390511    static const unsigned s_hashFlagIsAtomic = 1u << 4;
     
    395516    unsigned m_refCount;
    396517    unsigned m_length;
    397     const UChar* m_data;
     518    union {
     519        const LChar* m_data8;
     520        const UChar* m_data16;
     521    };
    398522    union {
    399523        void* m_buffer;
    400524        StringImpl* m_substringBuffer;
     525        mutable UChar* m_copyData16;
    401526    };
    402527    mutable unsigned m_hashAndFlags;
     
    404529
    405530bool equal(const StringImpl*, const StringImpl*);
    406 bool equal(const StringImpl*, const char*);
    407 inline bool equal(const char* a, StringImpl* b) { return equal(b, a); }
     531bool equal(const StringImpl*, const LChar*);
     532inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast<const LChar*>(b)); }
     533bool equal(const StringImpl*, const LChar*, unsigned);
     534inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); }
     535inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); }
    408536bool equal(const StringImpl*, const UChar*, unsigned);
    409537
    410538bool equalIgnoringCase(StringImpl*, StringImpl*);
    411 bool equalIgnoringCase(StringImpl*, const char*);
    412 inline bool equalIgnoringCase(const char* a, StringImpl* b) { return equalIgnoringCase(b, a); }
    413 bool equalIgnoringCase(const UChar* a, const char* b, unsigned length);
    414 inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); }
     539bool equalIgnoringCase(StringImpl*, const LChar*);
     540inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); }
     541bool equalIgnoringCase(const UChar*, const LChar*, unsigned);
     542inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast<const LChar*>(b), length); }
     543inline bool equalIgnoringCase(const LChar* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); }
     544inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, reinterpret_cast<const LChar*>(a), length); }
    415545
    416546bool equalIgnoringNullity(StringImpl*, StringImpl*);
     
    437567inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const
    438568{
    439     return create(m_data, m_length);
     569    if (is8Bit())
     570        return create(m_data8, m_length);
     571    return create(m_data16, m_length);
    440572}
    441573
  • trunk/Source/JavaScriptCore/wtf/text/WTFString.cpp

    r98316 r98624  
    6262
    6363// Construct a string with latin1 data.
     64String::String(const LChar* characters, unsigned length)
     65    : m_impl(characters ? StringImpl::create(characters, length) : 0)
     66{
     67}
     68
    6469String::String(const char* characters, unsigned length)
    65     : m_impl(characters ? StringImpl::create(characters, length) : 0)
     70    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters), length) : 0)
    6671{
    6772}
    6873
    6974// Construct a string with latin1 data, from a null-terminated source.
     75String::String(const LChar* characters)
     76    : m_impl(characters ? StringImpl::create(characters) : 0)
     77{
     78}
     79
    7080String::String(const char* characters)
    71     : m_impl(characters ? StringImpl::create(characters) : 0)
     81    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters)) : 0)
    7282{
    7383}
     
    96106}
    97107
    98 void String::append(char c)
     108void String::append(LChar c)
    99109{
    100110    // FIXME: This is extremely inefficient. So much so that we might want to take this
     
    339349
    340350    QByteArray ba = buffer.toUtf8();
    341     return StringImpl::create(ba.constData(), ba.length());
     351    return StringImpl::create(reinterpret_cast<const LChar*>(ba.constData()), ba.length());
    342352
    343353#elif OS(WINCE)
     
    356366            return String("");
    357367        if (written > 0)
    358             return StringImpl::create(buffer.data(), written);
     368            return StringImpl::create(reinterpret_cast<const LChar*>(buffer.data()), written);
    359369       
    360370        bufferSize <<= 1;
     
    397407    va_end(args);
    398408   
    399     return StringImpl::create(buffer.data(), len);
     409    return StringImpl::create(reinterpret_cast<const LChar*>(buffer.data()), len);
    400410#endif
    401411}
     
    718728}
    719729
    720 String String::fromUTF8(const char* stringStart, size_t length)
     730String String::fromUTF8(const LChar* stringStart, size_t length)
    721731{
    722732    if (length > numeric_limits<unsigned>::max())
     
    733743
    734744    // Try converting into the buffer.
    735     const char* stringCurrent = stringStart;
    736     if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &buffer, bufferEnd) != conversionOK)
     745    const char* stringCurrent = reinterpret_cast<const char*>(stringStart);
     746    if (convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + length), &buffer, bufferEnd) != conversionOK)
    737747        return String();
    738748
     
    747757}
    748758
    749 String String::fromUTF8(const char* string)
     759String String::fromUTF8(const LChar* string)
    750760{
    751761    if (!string)
    752762        return String();
    753     return fromUTF8(string, strlen(string));
    754 }
    755 
    756 String String::fromUTF8WithLatin1Fallback(const char* string, size_t size)
     763    return fromUTF8(string, strlen(reinterpret_cast<const char*>(string)));
     764}
     765
     766String String::fromUTF8WithLatin1Fallback(const LChar* string, size_t size)
    757767{
    758768    String utf8 = fromUTF8(string, size);
  • trunk/Source/JavaScriptCore/wtf/text/WTFString.h

    r98316 r98624  
    9090
    9191    // Construct a string with latin1 data.
     92    WTF_EXPORT_PRIVATE String(const LChar* characters, unsigned length);
    9293    WTF_EXPORT_PRIVATE String(const char* characters, unsigned length);
    9394
    9495    // Construct a string with latin1 data, from a null-terminated source.
     96    WTF_EXPORT_PRIVATE String(const LChar* characters);
    9597    WTF_EXPORT_PRIVATE String(const char* characters);
    9698
     
    156158    size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
    157159        { return m_impl ? m_impl->find(matchFunction, start) : notFound; }
    158     size_t find(const char* str, unsigned start = 0) const
     160    size_t find(const LChar* str, unsigned start = 0) const
    159161        { return m_impl ? m_impl->find(str, start) : notFound; }
    160162
     
    166168
    167169    // Case insensitive string matching.
    168     WTF_EXPORT_PRIVATE size_t findIgnoringCase(const char* str, unsigned start = 0) const
     170    WTF_EXPORT_PRIVATE size_t findIgnoringCase(const LChar* str, unsigned start = 0) const
    169171        { return m_impl ? m_impl->findIgnoringCase(str, start) : notFound; }
    170172    WTF_EXPORT_PRIVATE size_t findIgnoringCase(const String& str, unsigned start = 0) const
     
    174176
    175177    // Wrappers for find & reverseFind adding dynamic sensitivity check.
    176     size_t find(const char* str, unsigned start, bool caseSensitive) const
     178    size_t find(const LChar* str, unsigned start, bool caseSensitive) const
    177179        { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); }
    178180    size_t find(const String& str, unsigned start, bool caseSensitive) const
     
    186188   
    187189    bool contains(UChar c) const { return find(c) != notFound; }
    188     bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
     190    bool contains(const LChar* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
    189191    bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
    190192
     
    195197
    196198    WTF_EXPORT_PRIVATE void append(const String&);
    197     WTF_EXPORT_PRIVATE void append(char);
     199    WTF_EXPORT_PRIVATE void append(LChar);
     200    inline WTF_EXPORT_PRIVATE void append(char c) { append(static_cast<LChar>(c)); };
    198201    WTF_EXPORT_PRIVATE void append(UChar);
    199202    WTF_EXPORT_PRIVATE void append(const UChar*, unsigned length);
     
    300303    // String::fromUTF8 will return a null string if
    301304    // the input data contains invalid UTF-8 sequences.
    302     WTF_EXPORT_PRIVATE static String fromUTF8(const char*, size_t);
    303     WTF_EXPORT_PRIVATE static String fromUTF8(const char*);
     305    WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*, size_t);
     306    WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*);
     307    inline WTF_EXPORT_PRIVATE static String fromUTF8(const char* s, size_t length) { return fromUTF8(reinterpret_cast<const LChar*>(s), length); };
     308    inline WTF_EXPORT_PRIVATE static String fromUTF8(const char* s) { return fromUTF8(reinterpret_cast<const LChar*>(s)); };
    304309
    305310    // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8.
    306     WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const char*, size_t);
     311    WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const LChar*, size_t);
     312    inline WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const char* s, size_t length) { return fromUTF8WithLatin1Fallback(reinterpret_cast<const LChar*>(s), length); };
    307313   
    308314    // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3.
     
    339345
    340346inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); }
    341 inline bool operator==(const String& a, const char* b) { return equal(a.impl(), b); }
    342 inline bool operator==(const char* a, const String& b) { return equal(a, b.impl()); }
     347inline bool operator==(const String& a, const LChar* b) { return equal(a.impl(), b); }
     348inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
     349inline bool operator==(const LChar* a, const String& b) { return equal(a, b.impl()); }
     350inline bool operator==(const char* a, const String& b) { return equal(reinterpret_cast<const LChar*>(a), b.impl()); }
    343351
    344352inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); }
    345 inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), b); }
    346 inline bool operator!=(const char* a, const String& b) { return !equal(a, b.impl()); }
     353inline bool operator!=(const String& a, const LChar* b) { return !equal(a.impl(), b); }
     354inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
     355inline bool operator!=(const LChar* a, const String& b) { return !equal(a, b.impl()); }
     356inline bool operator!=(const char* a, const String& b) { return !equal(reinterpret_cast<const LChar*>(a), b.impl()); }
    347357
    348358inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    349 inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
    350 inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(a, b.impl()); }
     359inline bool equalIgnoringCase(const String& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); }
     360inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); }
     361inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); }
     362inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
    351363
    352364inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase)
  • trunk/Source/JavaScriptCore/wtf/unicode/Unicode.h

    r95555 r98624  
    4040COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes);
    4141
     42// Define platform neutral 8 bit character type (L is for Latin-1).
     43typedef unsigned char LChar;
     44
    4245#endif // WTF_UNICODE_H
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp

    r96169 r98624  
    25012501}
    25022502
    2503 int execute(YarrCodeBlock& jitObject, const char* input, unsigned start, unsigned length, int* output)
     2503int execute(YarrCodeBlock& jitObject, const LChar* input, unsigned start, unsigned length, int* output)
    25042504{
    25052505    return jitObject.execute(input, start, length, output);
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.h

    r95901 r98624  
    4949
    5050class YarrCodeBlock {
    51     typedef int (*YarrJITCode8)(const char* input, unsigned start, unsigned length, int* output) YARR_CALL;
     51    typedef int (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
    5252    typedef int (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
    5353
     
    6969    void set16BitCode(MacroAssembler::CodeRef ref) { m_ref16 = ref; }
    7070
    71     int execute(const char* input, unsigned start, unsigned length, int* output)
     71    int execute(const LChar* input, unsigned start, unsigned length, int* output)
    7272    {
    7373        ASSERT(has8BitCode());
     
    9292void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject);
    9393int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output);
    94 int execute(YarrCodeBlock& jitObject, const char* input, unsigned start, unsigned length, int* output);
     94int execute(YarrCodeBlock& jitObject, const LChar* input, unsigned start, unsigned length, int* output);
    9595
    9696} } // namespace JSC::Yarr
  • trunk/Source/JavaScriptCore/yarr/YarrParser.h

    r95901 r98624  
    232232        , m_backReferenceLimit(backReferenceLimit)
    233233        , m_err(NoError)
    234         , m_data(pattern)
     234        , m_data(pattern.characters16())
    235235        , m_size(pattern.length())
    236236        , m_index(0)
     
    794794    unsigned m_backReferenceLimit;
    795795    ErrorCode m_err;
    796     const UString& m_data;
     796    const UChar* m_data;
    797797    unsigned m_size;
    798798    unsigned m_index;
  • trunk/Source/WebCore/ChangeLog

    r98618 r98624  
     12011-10-27  Michael Saboff  <msaboff@apple.com>
     2
     3        Investigate storing strings in 8-bit buffers when possible
     4        https://bugs.webkit.org/show_bug.cgi?id=66161
     5
     6        Changes to support 8 bit StringImpl changes.
     7       
     8        Reviewed by Geoffrey Garen.
     9       
     10        No new tests, refactored StringImpl for 8 bit strings.
     11
     12        * platform/text/cf/StringImplCF.cpp:
     13        (WTF::StringImpl::createCFString):
     14
    1152011-10-27  Nat Duca  <nduca@chromium.org>
    216
  • trunk/Source/WebCore/platform/text/cf/StringImplCF.cpp

    r93012 r98624  
    137137    CFAllocatorRef allocator = (m_length && isMainThread()) ? StringWrapperCFAllocator::allocator() : 0;
    138138    if (!allocator)
    139         return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(m_data), m_length);
     139        return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(characters()), m_length);
    140140
    141141    // Put pointer to the StringImpl in a global so the allocator can store it with the CFString.
     
    143143    StringWrapperCFAllocator::currentString = this;
    144144
    145     CFStringRef string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(m_data), m_length, kCFAllocatorNull);
     145    CFStringRef string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(characters()), m_length, kCFAllocatorNull);
    146146
    147147    // The allocator cleared the global when it read it, but also clear it here just in case.
  • trunk/Source/WebKit2/ChangeLog

    r98622 r98624  
     12011-10-27  Michael Saboff  <msaboff@apple.com>
     2
     3        Investigate storing strings in 8-bit buffers when possible
     4        https://bugs.webkit.org/show_bug.cgi?id=66161
     5
     6        Added export of StringImpl::getData16SlowCase for linking tests.
     7
     8        Reviewed by Geoffrey Garen.
     9
     10        * win/WebKit2.def:
     11
    1122011-10-27  Sam Weinig  <sam@webkit.org>
    213
  • trunk/Source/WebKit2/win/WebKit2.def

    r98598 r98624  
    147147        ?absoluteBoundingBoxRectIgnoringTransforms@RenderObject@WebCore@@QBE?AVIntRect@2@XZ
    148148        ?add@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PBD@Z
     149        ?add@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PBE@Z
    149150        ?addSlowCase@AtomicString@WTF@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@2@PAVStringImpl@2@@Z
    150151        ?cacheDOMStructure@WebCore@@YAPAVStructure@JSC@@PAVJSDOMGlobalObject@1@PAV23@PBUClassInfo@3@@Z
     
    153154        ?createWrapper@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVNode@1@@Z
    154155        ?ensureShadowRoot@Element@WebCore@@QAEPAVShadowRoot@2@XZ
    155         ?equal@WTF@@YA_NPBVStringImpl@1@PBD@Z
     156        ?equal@WTF@@YA_NPBVStringImpl@1@PBE@Z
    156157        ?externalRepresentation@WebCore@@YA?AVString@WTF@@PAVElement@1@I@Z
    157158        ?getCachedDOMStructure@WebCore@@YAPAVStructure@JSC@@PAVJSDOMGlobalObject@1@PBUClassInfo@3@@Z
     159        ?getData16SlowCase@StringImpl@WTF@@ABEPB_WXZ
    158160        ?getElementById@TreeScope@WebCore@@QBEPAVElement@2@ABVAtomicString@WTF@@@Z
    159161        ?getLocationAndLengthFromRange@TextIterator@WebCore@@SA_NPAVElement@2@PBVRange@2@AAI2@Z
Note: See TracChangeset for help on using the changeset viewer.