Changeset 194017 in webkit


Ignore:
Timestamp:
Dec 13, 2015 12:03:24 PM (8 years ago)
Author:
akling@apple.com
Message:

CachedScript could have a copy-free path for all-ASCII scripts.
<https://webkit.org/b/152203>

Source/JavaScriptCore:

Reviewed by Antti Koivisto.

Make SourceProvider vend a StringView instead of a String.
This relaxes the promises that providers have to make about string lifetimes.

This means that on the WebCore side, CachedScript is free to cache a String
internally, while only ever exposing it as a temporary StringView.

A few extra copies (CPU, not memory) are introduced, none of them on hot paths.

  • API/JSScriptRef.cpp:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::sourceCodeForTools):
(JSC::CodeBlock::dumpSource):

  • inspector/ScriptDebugServer.cpp:

(Inspector::ScriptDebugServer::dispatchDidParseSource):
(Inspector::ScriptDebugServer::dispatchFailedToParseSource):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::execute):

  • jsc.cpp:

(functionFindTypeForExpression):
(functionHasBasicBlockExecuted):
(functionBasicBlockExecutionCount):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::setCode):

  • parser/Lexer.h:

(JSC::Lexer<LChar>::setCodeStart):
(JSC::Lexer<UChar>::setCodeStart):

  • parser/Parser.h:

(JSC::Parser::getToken):

  • parser/SourceCode.cpp:

(JSC::SourceCode::toUTF8):

  • parser/SourceCode.h:

(JSC::SourceCode::hash):
(JSC::SourceCode::view):
(JSC::SourceCode::toString): Deleted.

  • parser/SourceCodeKey.h:

(JSC::SourceCodeKey::SourceCodeKey):
(JSC::SourceCodeKey::string):

  • parser/SourceProvider.h:

(JSC::SourceProvider::getRange):

  • runtime/Completion.cpp:

(JSC::loadAndEvaluateModule):
(JSC::loadModule):

  • runtime/ErrorInstance.cpp:

(JSC::appendSourceToError):

  • runtime/FunctionPrototype.cpp:

(JSC::functionProtoFuncToString):

  • tools/FunctionOverrides.cpp:

(JSC::initializeOverrideInfo):
(JSC::FunctionOverrides::initializeOverrideFor):

Source/WebCore:

Reviewed by ANtti Koivisto.

Many (if not most) of script resources on the web contain nothing but ASCII characters.
Such resources, when streamed through a text decoder, will yield the exact same byte
sequence, except in anonymous heap memory instead of delicious file-backed pages.

Care is taken to ensure that the wrapper StringImpl is updated to target newly cached
resource data if an asynchronous caching notification comes in.

  • loader/cache/CachedResource.cpp:

(WebCore::CachedResource::tryReplaceEncodedData):

  • loader/cache/CachedResource.h:

(WebCore::CachedResource::didReplaceSharedBufferContents):

  • loader/cache/CachedScript.cpp:

(WebCore::encodingMayBeAllASCII):
(WebCore::CachedScript::script):
(WebCore::CachedScript::didReplaceSharedBufferContents):

  • loader/cache/CachedScript.h:
  • platform/SharedBuffer.h:
  • platform/cf/SharedBufferCF.cpp:

(WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer):

Location:
trunk/Source
Files:
31 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSScriptRef.cpp

    r192937 r194017  
    4747    }
    4848
    49     virtual const String& source() const override
     49    unsigned hash() const override
     50    {
     51        return m_source.impl()->hash();
     52    }
     53
     54    StringView source() const override
    5055    {
    5156        return m_source;
  • trunk/Source/JavaScriptCore/ChangeLog

    r194011 r194017  
     12015-12-13  Andreas Kling  <akling@apple.com>
     2
     3        CachedScript could have a copy-free path for all-ASCII scripts.
     4        <https://webkit.org/b/152203>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Make SourceProvider vend a StringView instead of a String.
     9        This relaxes the promises that providers have to make about string lifetimes.
     10
     11        This means that on the WebCore side, CachedScript is free to cache a String
     12        internally, while only ever exposing it as a temporary StringView.
     13
     14        A few extra copies (CPU, not memory) are introduced, none of them on hot paths.
     15
     16        * API/JSScriptRef.cpp:
     17        * bytecode/CodeBlock.cpp:
     18        (JSC::CodeBlock::sourceCodeForTools):
     19        (JSC::CodeBlock::dumpSource):
     20        * inspector/ScriptDebugServer.cpp:
     21        (Inspector::ScriptDebugServer::dispatchDidParseSource):
     22        (Inspector::ScriptDebugServer::dispatchFailedToParseSource):
     23        * interpreter/Interpreter.cpp:
     24        (JSC::Interpreter::execute):
     25        * jsc.cpp:
     26        (functionFindTypeForExpression):
     27        (functionHasBasicBlockExecuted):
     28        (functionBasicBlockExecutionCount):
     29        * parser/Lexer.cpp:
     30        (JSC::Lexer<T>::setCode):
     31        * parser/Lexer.h:
     32        (JSC::Lexer<LChar>::setCodeStart):
     33        (JSC::Lexer<UChar>::setCodeStart):
     34        * parser/Parser.h:
     35        (JSC::Parser::getToken):
     36        * parser/SourceCode.cpp:
     37        (JSC::SourceCode::toUTF8):
     38        * parser/SourceCode.h:
     39        (JSC::SourceCode::hash):
     40        (JSC::SourceCode::view):
     41        (JSC::SourceCode::toString): Deleted.
     42        * parser/SourceCodeKey.h:
     43        (JSC::SourceCodeKey::SourceCodeKey):
     44        (JSC::SourceCodeKey::string):
     45        * parser/SourceProvider.h:
     46        (JSC::SourceProvider::getRange):
     47        * runtime/Completion.cpp:
     48        (JSC::loadAndEvaluateModule):
     49        (JSC::loadModule):
     50        * runtime/ErrorInstance.cpp:
     51        (JSC::appendSourceToError):
     52        * runtime/FunctionPrototype.cpp:
     53        (JSC::functionProtoFuncToString):
     54        * tools/FunctionOverrides.cpp:
     55        (JSC::initializeOverrideInfo):
     56        (JSC::FunctionOverrides::initializeOverrideFor):
     57
    1582015-12-12  Benjamin Poulain  <benjamin@webkit.org>
    259
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r193974 r194017  
    197197    return toCString(
    198198        "function ",
    199         provider->source().impl()->utf8ForRange(rangeStart, rangeEnd - rangeStart));
     199        provider->source().substring(rangeStart, rangeEnd - rangeStart).utf8());
    200200}
    201201
     
    555555    if (executable->isFunctionExecutable()) {
    556556        FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
    557         String source = functionExecutable->source().provider()->getRange(
     557        StringView source = functionExecutable->source().provider()->getRange(
    558558            functionExecutable->parametersStartOffset(),
    559559            functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
     
    562562        return;
    563563    }
    564     out.print(executable->source().toString());
     564    out.print(executable->source().view());
    565565}
    566566
  • trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp

    r193426 r194017  
    200200    ScriptDebugListener::Script script;
    201201    script.url = sourceProvider->url();
    202     script.source = sourceProvider->source();
     202    script.source = sourceProvider->source().toString();
    203203    script.startLine = sourceProvider->startPosition().m_line.zeroBasedInt();
    204204    script.startColumn = sourceProvider->startPosition().m_column.zeroBasedInt();
     
    232232{
    233233    String url = sourceProvider->url();
    234     const String& data = sourceProvider->source();
     234    String data = sourceProvider->source().toString();
    235235    int firstLine = sourceProvider->startPosition().m_line.oneBasedInt();
    236236
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r193939 r194017  
    850850    Vector<JSONPData> JSONPData;
    851851    bool parseResult;
    852     const String programSource = program->source().toString();
     852    StringView programSource = program->source().view();
    853853    if (programSource.isNull())
    854854        return jsUndefined();
  • trunk/Source/JavaScriptCore/jsc.cpp

    r192693 r194017  
    14651465    RELEASE_ASSERT(exec->argument(1).isString());
    14661466    String substring = exec->argument(1).getString(exec);
    1467     String sourceCodeText = executable->source().toString();
     1467    String sourceCodeText = executable->source().view().toString();
    14681468    unsigned offset = static_cast<unsigned>(sourceCodeText.find(substring) + executable->source().startOffset());
    14691469   
     
    15031503    RELEASE_ASSERT(exec->argument(1).isString());
    15041504    String substring = exec->argument(1).getString(exec);
    1505     String sourceCodeText = executable->source().toString();
     1505    String sourceCodeText = executable->source().view().toString();
    15061506    RELEASE_ASSERT(sourceCodeText.contains(substring));
    15071507    int offset = sourceCodeText.find(substring) + executable->source().startOffset();
     
    15211521    RELEASE_ASSERT(exec->argument(1).isString());
    15221522    String substring = exec->argument(1).getString(exec);
    1523     String sourceCodeText = executable->source().toString();
     1523    String sourceCodeText = executable->source().view().toString();
    15241524    RELEASE_ASSERT(sourceCodeText.contains(substring));
    15251525    int offset = sourceCodeText.find(substring) + executable->source().startOffset();
  • trunk/Source/JavaScriptCore/parser/Lexer.cpp

    r192141 r194017  
    544544    m_lastToken = -1;
    545545   
    546     const String& sourceString = source.provider()->source();
     546    StringView sourceString = source.provider()->source();
    547547
    548548    if (!sourceString.isNull())
    549         setCodeStart(sourceString.impl());
     549        setCodeStart(sourceString);
    550550    else
    551551        m_codeStart = 0;
  • trunk/Source/JavaScriptCore/parser/Lexer.h

    r192141 r194017  
    140140    ALWAYS_INLINE void setOffsetFromSourcePtr(const T* sourcePtr, unsigned lineStartOffset) { setOffset(offsetFromSourcePtr(sourcePtr), lineStartOffset); }
    141141
    142     ALWAYS_INLINE void setCodeStart(const StringImpl*);
     142    ALWAYS_INLINE void setCodeStart(const StringView&);
    143143
    144144    ALWAYS_INLINE const Identifier* makeIdentifier(const LChar* characters, size_t length);
     
    290290
    291291template <>
    292 ALWAYS_INLINE void Lexer<LChar>::setCodeStart(const StringImpl* sourceString)
    293 {
    294     ASSERT(sourceString->is8Bit());
    295     m_codeStart = sourceString->characters8();
    296 }
    297 
    298 template <>
    299 ALWAYS_INLINE void Lexer<UChar>::setCodeStart(const StringImpl* sourceString)
    300 {
    301     ASSERT(!sourceString->is8Bit());
    302     m_codeStart = sourceString->characters16();
     292ALWAYS_INLINE void Lexer<LChar>::setCodeStart(const StringView& sourceString)
     293{
     294    ASSERT(sourceString.is8Bit());
     295    m_codeStart = sourceString.characters8();
     296}
     297
     298template <>
     299ALWAYS_INLINE void Lexer<UChar>::setCodeStart(const StringView& sourceString)
     300{
     301    ASSERT(!sourceString.is8Bit());
     302    m_codeStart = sourceString.characters16();
    303303}
    304304
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r192937 r194017  
    991991
    992992    void printUnexpectedTokenText(WTF::PrintStream&);
    993     ALWAYS_INLINE String getToken() {
     993    ALWAYS_INLINE StringView getToken() {
    994994        SourceProvider* sourceProvider = m_source->provider();
    995995        return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset);
  • trunk/Source/JavaScriptCore/parser/SourceCode.cpp

    r163844 r194017  
    3737        return CString("", 0);
    3838   
    39     return m_provider->source().impl()->utf8ForRange(m_startChar, m_endChar - m_startChar);
     39    return m_provider->source().substring(m_startChar, m_endChar - m_startChar).utf8();
    4040}
    4141
  • trunk/Source/JavaScriptCore/parser/SourceCode.h

    r186959 r194017  
    8080        bool isHashTableDeletedValue() const { return m_provider.isHashTableDeletedValue(); }
    8181
    82         String toString() const
     82        unsigned hash() const
     83        {
     84            ASSERT(m_provider);
     85            return m_provider->hash();
     86        }
     87
     88        StringView view() const
    8389        {
    8490            if (!m_provider)
    85                 return String();
     91                return StringView();
    8692            return m_provider->getRange(m_startChar, m_endChar);
    8793        }
  • trunk/Source/JavaScriptCore/parser/SourceCodeKey.h

    r192937 r194017  
    4646        , m_name(name)
    4747        , m_flags((static_cast<unsigned>(codeType) << 3) | (static_cast<unsigned>(builtinMode) << 2) | (static_cast<unsigned>(strictMode) << 1) | static_cast<unsigned>(thisTDZMode))
    48         , m_hash(string().impl()->hash())
     48        , m_hash(sourceCode.hash())
    4949    {
    5050    }
     
    6565    // To save memory, we compute our string on demand. It's expected that source
    6666    // providers cache their strings to make this efficient.
    67     String string() const { return m_sourceCode.toString(); }
     67    StringView string() const { return m_sourceCode.view(); }
    6868
    6969    bool operator==(const SourceCodeKey& other) const
  • trunk/Source/JavaScriptCore/parser/SourceProvider.h

    r191973 r194017  
    4444        JS_EXPORT_PRIVATE virtual ~SourceProvider();
    4545
    46         virtual const String& source() const = 0;
    47         String getRange(int start, int end) const
     46        virtual unsigned hash() const = 0;
     47        virtual StringView source() const = 0;
     48        StringView getRange(int start, int end) const
    4849        {
    49             return source().substringSharingImpl(start, end - start);
     50            return source().substring(start, end - start);
    5051        }
    5152
     
    8788            return adoptRef(*new StringSourceProvider(source, url, startPosition));
    8889        }
     90       
     91        unsigned hash() const override
     92        {
     93            return m_source.impl()->hash();
     94        }
    8995
    90         virtual const String& source() const override
     96        virtual StringView source() const override
    9197        {
    9298            return m_source;
     
    111117        }
    112118
    113         virtual const String& source() const override
     119        unsigned hash() const override
     120        {
     121            return m_source.impl()->hash();
     122        }
     123
     124        virtual StringView source() const override
    114125        {
    115126            return m_source;
  • trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r192937 r194017  
    168168
    169169    // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
    170     globalObject->moduleLoader()->provide(exec, key, ModuleLoaderObject::Status::Fetch, source.toString());
     170    globalObject->moduleLoader()->provide(exec, key, ModuleLoaderObject::Status::Fetch, source.view().toString());
    171171    if (exec->hadException())
    172172        return rejectPromise(exec, globalObject);
     
    205205
    206206    // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
    207     globalObject->moduleLoader()->provide(exec, key, ModuleLoaderObject::Status::Fetch, source.toString());
     207    globalObject->moduleLoader()->provide(exec, key, ModuleLoaderObject::Status::Fetch, source.view().toString());
    208208    if (exec->hadException())
    209209        return rejectPromise(exec, globalObject);
  • trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp

    r190555 r194017  
    6161    int expressionStop = divotPoint + endOffset;
    6262
    63     const String& sourceString = codeBlock->source()->source();
     63    StringView sourceString = codeBlock->source()->source();
    6464    if (!expressionStop || expressionStart > static_cast<int>(sourceString.length()))
    6565        return;
     
    7272    String message = asString(jsMessage)->value(callFrame);
    7373    if (expressionStart < expressionStop)
    74         message = appender(message, codeBlock->source()->getRange(expressionStart, expressionStop) , type, ErrorInstance::FoundExactSource);
     74        message = appender(message, codeBlock->source()->getRange(expressionStart, expressionStop).toString(), type, ErrorInstance::FoundExactSource);
    7575    else {
    7676        // No range information, so give a few characters of context.
    77         const StringImpl* data = sourceString.impl();
    7877        int dataLength = sourceString.length();
    7978        int start = expressionStart;
     
    8180        // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
    8281        // Then strip whitespace.
    83         while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
     82        while (start > 0 && (expressionStart - start < 20) && sourceString[start - 1] != '\n')
    8483            start--;
    85         while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
     84        while (start < (expressionStart - 1) && isStrWhiteSpace(sourceString[start]))
    8685            start++;
    87         while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
     86        while (stop < dataLength && (stop - expressionStart < 20) && sourceString[stop] != '\n')
    8887            stop++;
    89         while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
     88        while (stop > expressionStart && isStrWhiteSpace(sourceString[stop - 1]))
    9089            stop--;
    91         message = appender(message, codeBlock->source()->getRange(start, stop), type, ErrorInstance::FoundApproximateSource);
     90        message = appender(message, codeBlock->source()->getRange(start, stop).toString(), type, ErrorInstance::FoundApproximateSource);
    9291    }
    9392    exception->putDirect(*vm, vm->propertyNames->message, jsString(vm, message));
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp

    r193974 r194017  
    9393        String functionHeader = executable->isArrowFunction() ? "" : "function ";
    9494       
    95         String source = executable->source().provider()->getRange(
     95        StringView source = executable->source().provider()->getRange(
    9696            executable->parametersStartOffset(),
    9797            executable->parametersStartOffset() + executable->source().length());
  • trunk/Source/JavaScriptCore/tools/FunctionOverrides.cpp

    r184325 r194017  
    107107static void initializeOverrideInfo(const SourceCode& origCode, const String& newBody, FunctionOverrides::OverrideInfo& info)
    108108{
    109     String origProviderStr = origCode.provider()->source();
     109    String origProviderStr = origCode.provider()->source().toString();
    110110    unsigned origBraceStart = origCode.startOffset();
    111111    unsigned origFunctionStart = origProviderStr.reverseFind("function", origBraceStart);
     
    136136    FunctionOverrides& overrides = FunctionOverrides::overrides();
    137137
    138     auto it = overrides.m_entries.find(origCode.toString());
     138    auto it = overrides.m_entries.find(origCode.view().toString());
    139139    if (it == overrides.m_entries.end())
    140140        return false;
  • trunk/Source/WTF/wtf/PrintStream.cpp

    r184828 r194017  
    5252{
    5353    out.printf("%s", string);
     54}
     55
     56void printInternal(PrintStream& out, const StringView& string)
     57{
     58    out.print(string.utf8());
    5459}
    5560
  • trunk/Source/WTF/wtf/PrintStream.h

    r190076 r194017  
    4141class String;
    4242class StringImpl;
     43class StringView;
    4344class UniquedStringImpl;
    4445
     
    7172
    7273WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const char*);
     74WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringView&);
    7375WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const CString&);
    7476WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&);
  • trunk/Source/WebCore/ChangeLog

    r194016 r194017  
     12015-12-13  Andreas Kling  <akling@apple.com>
     2
     3        CachedScript could have a copy-free path for all-ASCII scripts.
     4        <https://webkit.org/b/152203>
     5
     6        Reviewed by ANtti Koivisto.
     7
     8        Many (if not most) of script resources on the web contain nothing but ASCII characters.
     9        Such resources, when streamed through a text decoder, will yield the exact same byte
     10        sequence, except in anonymous heap memory instead of delicious file-backed pages.
     11
     12        Care is taken to ensure that the wrapper StringImpl is updated to target newly cached
     13        resource data if an asynchronous caching notification comes in.
     14
     15        * loader/cache/CachedResource.cpp:
     16        (WebCore::CachedResource::tryReplaceEncodedData):
     17        * loader/cache/CachedResource.h:
     18        (WebCore::CachedResource::didReplaceSharedBufferContents):
     19        * loader/cache/CachedScript.cpp:
     20        (WebCore::encodingMayBeAllASCII):
     21        (WebCore::CachedScript::script):
     22        (WebCore::CachedScript::didReplaceSharedBufferContents):
     23        * loader/cache/CachedScript.h:
     24        * platform/SharedBuffer.h:
     25        * platform/cf/SharedBufferCF.cpp:
     26        (WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer):
     27
    1282015-12-13  Zalan Bujtas  <zalan@apple.com>
    229
  • trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h

    r177733 r194017  
    4545    }
    4646
    47     const String& source() const { return m_cachedScript->script(); }
     47    unsigned hash() const override { return m_cachedScript->scriptHash(); }
     48    StringView source() const override { return m_cachedScript->script(); }
    4849
    4950private:
  • trunk/Source/WebCore/bindings/js/ScriptSourceCode.h

    r156550 r194017  
    6262    const JSC::SourceCode& jsSourceCode() const { return m_code; }
    6363
    64     const String& source() const { return m_provider->source(); }
     64    StringView source() const { return m_provider->source(); }
    6565
    6666    int startLine() const { return m_code.firstLine(); }
  • trunk/Source/WebCore/inspector/InspectorPageAgent.cpp

    r192592 r194017  
    162162            return !result->isNull();
    163163        case CachedResource::Script:
    164             *result = downcast<CachedScript>(*cachedResource).script();
     164            *result = downcast<CachedScript>(*cachedResource).script().toString();
    165165            return true;
    166166        case CachedResource::RawResource: {
  • trunk/Source/WebCore/loader/cache/CachedResource.cpp

    r192995 r194017  
    788788        return;
    789789
    790     m_data->tryReplaceContentsWithPlatformBuffer(newBuffer);
    791 }
    792 
    793 #endif
    794 
    795 }
     790    if (m_data->tryReplaceContentsWithPlatformBuffer(newBuffer)) {
     791        didReplaceSharedBufferContents();
     792        // FIXME: Should we call checkNotify() here to move already-decoded images to the new data source?
     793    }
     794}
     795
     796#endif
     797
     798}
  • trunk/Source/WebCore/loader/cache/CachedResource.h

    r188468 r194017  
    268268    void didAccessDecodedData(double timeStamp);
    269269
     270    virtual void didReplaceSharedBufferContents() { }
     271
    270272    // FIXME: Make the rest of these data members private and use functions in derived classes instead.
    271273    HashCountedSet<CachedResourceClient*> m_clients;
  • trunk/Source/WebCore/loader/cache/CachedScript.cpp

    r185057 r194017  
    7070}
    7171
    72 const String& CachedScript::script()
     72static bool encodingMayBeAllASCII(const String& encoding)
     73{
     74    return encoding == "UTF-8" || encoding == "ISO-8859-1" || encoding == "ASCII";
     75}
     76
     77StringView CachedScript::script()
    7378{
    7479    if (!m_script && m_data) {
     80        if (m_ASCIIOptimizationState == Unknown
     81            && encodingMayBeAllASCII(encoding())
     82            && m_data->size()
     83            && charactersAreAllASCII(reinterpret_cast<const LChar*>(m_data->data()), m_data->size())) {
     84
     85            m_script = StringImpl::createWithoutCopying(reinterpret_cast<const LChar*>(m_data->data()), m_data->size());
     86            m_ASCIIOptimizationState = DataAndDecodedStringHaveSameBytes;
     87
     88            // If the encoded and decoded data are the same, there is no decoded data cost!
     89            setDecodedSize(0);
     90            m_decodedDataDeletionTimer.stop();
     91            return m_script;
     92        }
    7593        m_script = m_decoder->decodeAndFlush(m_data->data(), encodedSize());
     94        m_ASCIIOptimizationState = DataAndDecodedStringHaveDifferentBytes;
    7695        setDecodedSize(m_script.sizeInBytes());
    7796    }
    78     m_decodedDataDeletionTimer.restart();
     97    if (m_ASCIIOptimizationState == DataAndDecodedStringHaveDifferentBytes)
     98        m_decodedDataDeletionTimer.restart();
    7999    return m_script;
     100}
     101
     102unsigned CachedScript::scriptHash()
     103{
     104    script();
     105    return m_script.impl()->hash();
     106}
     107
     108void CachedScript::didReplaceSharedBufferContents()
     109{
     110    // We receive this callback when the CachedResource's internal SharedBuffer has had its contents
     111    // replaced by the memory-mapping-of-file-backed-resources optimization. If m_script is just a
     112    // non-copying wrapper around the old SharedBuffer contents, we have to retarget it.
     113    if (m_ASCIIOptimizationState == DataAndDecodedStringHaveSameBytes)
     114        m_script = StringImpl::createWithoutCopying(reinterpret_cast<const LChar*>(m_data->data()), m_data->size());
     115    CachedResource::didReplaceSharedBufferContents();
    80116}
    81117
  • trunk/Source/WebCore/loader/cache/CachedScript.h

    r175549 r194017  
    3838    virtual ~CachedScript();
    3939
    40     const String& script();
     40    StringView script();
     41    unsigned scriptHash();
    4142
    4243    String mimeType() const;
     
    4546    bool mimeTypeAllowedByNosniff() const;
    4647#endif
     48
     49    void didReplaceSharedBufferContents() override;
    4750
    4851private:
     
    5861
    5962    String m_script;
     63
     64    enum ASCIIResourceOptimizationState { Unknown, DataAndDecodedStringHaveSameBytes, DataAndDecodedStringHaveDifferentBytes };
     65    ASCIIResourceOptimizationState m_ASCIIOptimizationState { Unknown };
     66
    6067    RefPtr<TextResourceDecoder> m_decoder;
    6168};
  • trunk/Source/WebCore/platform/SharedBuffer.h

    r185273 r194017  
    120120    WEBCORE_EXPORT unsigned getSomeData(const char*& data, unsigned position = 0) const;
    121121
    122     void tryReplaceContentsWithPlatformBuffer(SharedBuffer&);
     122    bool tryReplaceContentsWithPlatformBuffer(SharedBuffer&);
    123123    WEBCORE_EXPORT bool hasPlatformData() const;
    124124
  • trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp

    r185273 r194017  
    9393}
    9494
    95 void SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
     95bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
    9696{
    9797    if (!newContents.m_cfData)
    98         return;
     98        return false;
    9999
    100100    clear();
    101101    m_cfData = newContents.m_cfData;
     102    return true;
    102103}
    103104
  • trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp

    r184620 r194017  
    7979}
    8080
    81 void SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
     81bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
    8282{
    8383    if (!newContents.hasPlatformData())
    84         return;
     84        return false;
    8585
    8686    clear();
    8787    // FIXME: Use GRefPtr instead of GUniquePtr for the SoupBuffer.
    8888    m_soupBuffer.swap(newContents.m_soupBuffer);
     89    return true;
    8990}
    9091
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm

    r191887 r194017  
    5252static NSString *toNSString(SourceProvider* sourceProvider)
    5353{
    54     const String& sourceString = sourceProvider->source();
     54    const String& sourceString = sourceProvider->source().toString();
    5555    if (sourceString.isEmpty())
    5656        return nil;
Note: See TracChangeset for help on using the changeset viewer.