<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[194017] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/194017">194017</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2015-12-13 12:03:24 -0800 (Sun, 13 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>CachedScript could have a copy-free path for all-ASCII scripts.
&lt;https://webkit.org/b/152203&gt;

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&lt;T&gt;::setCode):
* parser/Lexer.h:
(JSC::Lexer&lt;LChar&gt;::setCodeStart):
(JSC::Lexer&lt;UChar&gt;::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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreAPIJSScriptRefcpp">trunk/Source/JavaScriptCore/API/JSScriptRef.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorScriptDebugServercpp">trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserLexercpp">trunk/Source/JavaScriptCore/parser/Lexer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserLexerh">trunk/Source/JavaScriptCore/parser/Lexer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSourceCodecpp">trunk/Source/JavaScriptCore/parser/SourceCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSourceCodeh">trunk/Source/JavaScriptCore/parser/SourceCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSourceCodeKeyh">trunk/Source/JavaScriptCore/parser/SourceCodeKey.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSourceProviderh">trunk/Source/JavaScriptCore/parser/SourceProvider.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCompletioncpp">trunk/Source/JavaScriptCore/runtime/Completion.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeErrorInstancecpp">trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeFunctionPrototypecpp">trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsFunctionOverridescpp">trunk/Source/JavaScriptCore/tools/FunctionOverrides.cpp</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamcpp">trunk/Source/WTF/wtf/PrintStream.cpp</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamh">trunk/Source/WTF/wtf/PrintStream.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsCachedScriptSourceProviderh">trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsScriptSourceCodeh">trunk/Source/WebCore/bindings/js/ScriptSourceCode.h</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorPageAgentcpp">trunk/Source/WebCore/inspector/InspectorPageAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedResourcecpp">trunk/Source/WebCore/loader/cache/CachedResource.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedResourceh">trunk/Source/WebCore/loader/cache/CachedResource.h</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedScriptcpp">trunk/Source/WebCore/loader/cache/CachedScript.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedScripth">trunk/Source/WebCore/loader/cache/CachedScript.h</a></li>
<li><a href="#trunkSourceWebCoreplatformSharedBufferh">trunk/Source/WebCore/platform/SharedBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformcfSharedBufferCFcpp">trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformsoupSharedBufferSoupcpp">trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebScriptDebuggermm">trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreAPIJSScriptRefcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSScriptRef.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSScriptRef.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/API/JSScriptRef.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -46,8 +46,13 @@
</span><span class="cx">         return WTF::adoptRef(*new OpaqueJSScript(vm, url, startingLineNumber, source));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    virtual const String&amp; source() const override
</del><ins>+    unsigned hash() const override
</ins><span class="cx">     {
</span><ins>+        return m_source.impl()-&gt;hash();
+    }
+
+    StringView source() const override
+    {
</ins><span class="cx">         return m_source;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2015-12-13  Andreas Kling  &lt;akling@apple.com&gt;
+
+        CachedScript could have a copy-free path for all-ASCII scripts.
+        &lt;https://webkit.org/b/152203&gt;
+
+        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&lt;T&gt;::setCode):
+        * parser/Lexer.h:
+        (JSC::Lexer&lt;LChar&gt;::setCodeStart):
+        (JSC::Lexer&lt;UChar&gt;::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):
+
</ins><span class="cx"> 2015-12-12  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Add lowering for B3's Store8 opcode
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -196,7 +196,7 @@
</span><span class="cx">     unsigned rangeEnd = delta + unlinked-&gt;startOffset() + unlinked-&gt;sourceLength();
</span><span class="cx">     return toCString(
</span><span class="cx">         &quot;function &quot;,
</span><del>-        provider-&gt;source().impl()-&gt;utf8ForRange(rangeStart, rangeEnd - rangeStart));
</del><ins>+        provider-&gt;source().substring(rangeStart, rangeEnd - rangeStart).utf8());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CString CodeBlock::sourceCodeOnOneLine() const
</span><span class="lines">@@ -554,14 +554,14 @@
</span><span class="cx">     ScriptExecutable* executable = ownerScriptExecutable();
</span><span class="cx">     if (executable-&gt;isFunctionExecutable()) {
</span><span class="cx">         FunctionExecutable* functionExecutable = reinterpret_cast&lt;FunctionExecutable*&gt;(executable);
</span><del>-        String source = functionExecutable-&gt;source().provider()-&gt;getRange(
</del><ins>+        StringView source = functionExecutable-&gt;source().provider()-&gt;getRange(
</ins><span class="cx">             functionExecutable-&gt;parametersStartOffset(),
</span><span class="cx">             functionExecutable-&gt;typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
</span><span class="cx">         
</span><span class="cx">         out.print(&quot;function &quot;, inferredName(), source);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    out.print(executable-&gt;source().toString());
</del><ins>+    out.print(executable-&gt;source().view());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::dumpBytecode()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorScriptDebugServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -199,7 +199,7 @@
</span><span class="cx"> 
</span><span class="cx">     ScriptDebugListener::Script script;
</span><span class="cx">     script.url = sourceProvider-&gt;url();
</span><del>-    script.source = sourceProvider-&gt;source();
</del><ins>+    script.source = sourceProvider-&gt;source().toString();
</ins><span class="cx">     script.startLine = sourceProvider-&gt;startPosition().m_line.zeroBasedInt();
</span><span class="cx">     script.startColumn = sourceProvider-&gt;startPosition().m_column.zeroBasedInt();
</span><span class="cx">     script.isContentScript = isContentScript;
</span><span class="lines">@@ -231,7 +231,7 @@
</span><span class="cx"> void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet&amp; listeners, SourceProvider* sourceProvider, int errorLine, const String&amp; errorMessage)
</span><span class="cx"> {
</span><span class="cx">     String url = sourceProvider-&gt;url();
</span><del>-    const String&amp; data = sourceProvider-&gt;source();
</del><ins>+    String data = sourceProvider-&gt;source().toString();
</ins><span class="cx">     int firstLine = sourceProvider-&gt;startPosition().m_line.oneBasedInt();
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;ScriptDebugListener*&gt; copy;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -849,7 +849,7 @@
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;JSONPData&gt; JSONPData;
</span><span class="cx">     bool parseResult;
</span><del>-    const String programSource = program-&gt;source().toString();
</del><ins>+    StringView programSource = program-&gt;source().view();
</ins><span class="cx">     if (programSource.isNull())
</span><span class="cx">         return jsUndefined();
</span><span class="cx">     if (programSource.is8Bit()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -1464,7 +1464,7 @@
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(exec-&gt;argument(1).isString());
</span><span class="cx">     String substring = exec-&gt;argument(1).getString(exec);
</span><del>-    String sourceCodeText = executable-&gt;source().toString();
</del><ins>+    String sourceCodeText = executable-&gt;source().view().toString();
</ins><span class="cx">     unsigned offset = static_cast&lt;unsigned&gt;(sourceCodeText.find(substring) + executable-&gt;source().startOffset());
</span><span class="cx">     
</span><span class="cx">     String jsonString = exec-&gt;vm().typeProfiler()-&gt;typeInformationForExpressionAtOffset(TypeProfilerSearchDescriptorNormal, offset, executable-&gt;sourceID(), exec-&gt;vm());
</span><span class="lines">@@ -1502,7 +1502,7 @@
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(exec-&gt;argument(1).isString());
</span><span class="cx">     String substring = exec-&gt;argument(1).getString(exec);
</span><del>-    String sourceCodeText = executable-&gt;source().toString();
</del><ins>+    String sourceCodeText = executable-&gt;source().view().toString();
</ins><span class="cx">     RELEASE_ASSERT(sourceCodeText.contains(substring));
</span><span class="cx">     int offset = sourceCodeText.find(substring) + executable-&gt;source().startOffset();
</span><span class="cx">     
</span><span class="lines">@@ -1520,7 +1520,7 @@
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(exec-&gt;argument(1).isString());
</span><span class="cx">     String substring = exec-&gt;argument(1).getString(exec);
</span><del>-    String sourceCodeText = executable-&gt;source().toString();
</del><ins>+    String sourceCodeText = executable-&gt;source().view().toString();
</ins><span class="cx">     RELEASE_ASSERT(sourceCodeText.contains(substring));
</span><span class="cx">     int offset = sourceCodeText.find(substring) + executable-&gt;source().startOffset();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserLexercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Lexer.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Lexer.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/Lexer.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -543,10 +543,10 @@
</span><span class="cx">     m_lineNumber = source.firstLine();
</span><span class="cx">     m_lastToken = -1;
</span><span class="cx">     
</span><del>-    const String&amp; sourceString = source.provider()-&gt;source();
</del><ins>+    StringView sourceString = source.provider()-&gt;source();
</ins><span class="cx"> 
</span><span class="cx">     if (!sourceString.isNull())
</span><del>-        setCodeStart(sourceString.impl());
</del><ins>+        setCodeStart(sourceString);
</ins><span class="cx">     else
</span><span class="cx">         m_codeStart = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserLexerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Lexer.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Lexer.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/Lexer.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">     ALWAYS_INLINE const T* currentSourcePtr() const;
</span><span class="cx">     ALWAYS_INLINE void setOffsetFromSourcePtr(const T* sourcePtr, unsigned lineStartOffset) { setOffset(offsetFromSourcePtr(sourcePtr), lineStartOffset); }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE void setCodeStart(const StringImpl*);
</del><ins>+    ALWAYS_INLINE void setCodeStart(const StringView&amp;);
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE const Identifier* makeIdentifier(const LChar* characters, size_t length);
</span><span class="cx">     ALWAYS_INLINE const Identifier* makeIdentifier(const UChar* characters, size_t length);
</span><span class="lines">@@ -289,17 +289,17 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;&gt;
</span><del>-ALWAYS_INLINE void Lexer&lt;LChar&gt;::setCodeStart(const StringImpl* sourceString)
</del><ins>+ALWAYS_INLINE void Lexer&lt;LChar&gt;::setCodeStart(const StringView&amp; sourceString)
</ins><span class="cx"> {
</span><del>-    ASSERT(sourceString-&gt;is8Bit());
-    m_codeStart = sourceString-&gt;characters8();
</del><ins>+    ASSERT(sourceString.is8Bit());
+    m_codeStart = sourceString.characters8();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;&gt;
</span><del>-ALWAYS_INLINE void Lexer&lt;UChar&gt;::setCodeStart(const StringImpl* sourceString)
</del><ins>+ALWAYS_INLINE void Lexer&lt;UChar&gt;::setCodeStart(const StringView&amp; sourceString)
</ins><span class="cx"> {
</span><del>-    ASSERT(!sourceString-&gt;is8Bit());
-    m_codeStart = sourceString-&gt;characters16();
</del><ins>+    ASSERT(!sourceString.is8Bit());
+    m_codeStart = sourceString.characters16();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename T&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -990,7 +990,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void printUnexpectedTokenText(WTF::PrintStream&amp;);
</span><del>-    ALWAYS_INLINE String getToken() {
</del><ins>+    ALWAYS_INLINE StringView getToken() {
</ins><span class="cx">         SourceProvider* sourceProvider = m_source-&gt;provider();
</span><span class="cx">         return sourceProvider-&gt;getRange(tokenStart(), tokenEndPosition().offset);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSourceCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SourceCode.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SourceCode.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/SourceCode.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx">     if (!m_provider)
</span><span class="cx">         return CString(&quot;&quot;, 0);
</span><span class="cx">     
</span><del>-    return m_provider-&gt;source().impl()-&gt;utf8ForRange(m_startChar, m_endChar - m_startChar);
</del><ins>+    return m_provider-&gt;source().substring(m_startChar, m_endChar - m_startChar).utf8();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSourceCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SourceCode.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SourceCode.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/SourceCode.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -79,10 +79,16 @@
</span><span class="cx"> 
</span><span class="cx">         bool isHashTableDeletedValue() const { return m_provider.isHashTableDeletedValue(); }
</span><span class="cx"> 
</span><del>-        String toString() const
</del><ins>+        unsigned hash() const
</ins><span class="cx">         {
</span><ins>+            ASSERT(m_provider);
+            return m_provider-&gt;hash();
+        }
+
+        StringView view() const
+        {
</ins><span class="cx">             if (!m_provider)
</span><del>-                return String();
</del><ins>+                return StringView();
</ins><span class="cx">             return m_provider-&gt;getRange(m_startChar, m_endChar);
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSourceCodeKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SourceCodeKey.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SourceCodeKey.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/SourceCodeKey.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">         : m_sourceCode(sourceCode)
</span><span class="cx">         , m_name(name)
</span><span class="cx">         , m_flags((static_cast&lt;unsigned&gt;(codeType) &lt;&lt; 3) | (static_cast&lt;unsigned&gt;(builtinMode) &lt;&lt; 2) | (static_cast&lt;unsigned&gt;(strictMode) &lt;&lt; 1) | static_cast&lt;unsigned&gt;(thisTDZMode))
</span><del>-        , m_hash(string().impl()-&gt;hash())
</del><ins>+        , m_hash(sourceCode.hash())
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx"> 
</span><span class="cx">     // To save memory, we compute our string on demand. It's expected that source
</span><span class="cx">     // providers cache their strings to make this efficient.
</span><del>-    String string() const { return m_sourceCode.toString(); }
</del><ins>+    StringView string() const { return m_sourceCode.view(); }
</ins><span class="cx"> 
</span><span class="cx">     bool operator==(const SourceCodeKey&amp; other) const
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSourceProviderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SourceProvider.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SourceProvider.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/parser/SourceProvider.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -43,10 +43,11 @@
</span><span class="cx"> 
</span><span class="cx">         JS_EXPORT_PRIVATE virtual ~SourceProvider();
</span><span class="cx"> 
</span><del>-        virtual const String&amp; source() const = 0;
-        String getRange(int start, int end) const
</del><ins>+        virtual unsigned hash() const = 0;
+        virtual StringView source() const = 0;
+        StringView getRange(int start, int end) const
</ins><span class="cx">         {
</span><del>-            return source().substringSharingImpl(start, end - start);
</del><ins>+            return source().substring(start, end - start);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         const String&amp; url() const { return m_url; }
</span><span class="lines">@@ -86,8 +87,13 @@
</span><span class="cx">         {
</span><span class="cx">             return adoptRef(*new StringSourceProvider(source, url, startPosition));
</span><span class="cx">         }
</span><ins>+        
+        unsigned hash() const override
+        {
+            return m_source.impl()-&gt;hash();
+        }
</ins><span class="cx"> 
</span><del>-        virtual const String&amp; source() const override
</del><ins>+        virtual StringView source() const override
</ins><span class="cx">         {
</span><span class="cx">             return m_source;
</span><span class="cx">         }
</span><span class="lines">@@ -110,8 +116,13 @@
</span><span class="cx">             return adoptRef(*new WebAssemblySourceProvider(data, url));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        virtual const String&amp; source() const override
</del><ins>+        unsigned hash() const override
</ins><span class="cx">         {
</span><ins>+            return m_source.impl()-&gt;hash();
+        }
+
+        virtual StringView source() const override
+        {
</ins><span class="cx">             return m_source;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCompletioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Completion.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Completion.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/runtime/Completion.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -167,7 +167,7 @@
</span><span class="cx">     JSGlobalObject* globalObject = exec-&gt;vmEntryGlobalObject();
</span><span class="cx"> 
</span><span class="cx">     // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
</span><del>-    globalObject-&gt;moduleLoader()-&gt;provide(exec, key, ModuleLoaderObject::Status::Fetch, source.toString());
</del><ins>+    globalObject-&gt;moduleLoader()-&gt;provide(exec, key, ModuleLoaderObject::Status::Fetch, source.view().toString());
</ins><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return rejectPromise(exec, globalObject);
</span><span class="cx"> 
</span><span class="lines">@@ -204,7 +204,7 @@
</span><span class="cx">     JSGlobalObject* globalObject = exec-&gt;vmEntryGlobalObject();
</span><span class="cx"> 
</span><span class="cx">     // Insert the given source code to the ModuleLoader registry as the fetched registry entry.
</span><del>-    globalObject-&gt;moduleLoader()-&gt;provide(exec, key, ModuleLoaderObject::Status::Fetch, source.toString());
</del><ins>+    globalObject-&gt;moduleLoader()-&gt;provide(exec, key, ModuleLoaderObject::Status::Fetch, source.view().toString());
</ins><span class="cx">     if (exec-&gt;hadException())
</span><span class="cx">         return rejectPromise(exec, globalObject);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeErrorInstancecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/runtime/ErrorInstance.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">     int expressionStart = divotPoint - startOffset;
</span><span class="cx">     int expressionStop = divotPoint + endOffset;
</span><span class="cx"> 
</span><del>-    const String&amp; sourceString = codeBlock-&gt;source()-&gt;source();
</del><ins>+    StringView sourceString = codeBlock-&gt;source()-&gt;source();
</ins><span class="cx">     if (!expressionStop || expressionStart &gt; static_cast&lt;int&gt;(sourceString.length()))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="lines">@@ -71,24 +71,23 @@
</span><span class="cx">     
</span><span class="cx">     String message = asString(jsMessage)-&gt;value(callFrame);
</span><span class="cx">     if (expressionStart &lt; expressionStop)
</span><del>-        message = appender(message, codeBlock-&gt;source()-&gt;getRange(expressionStart, expressionStop) , type, ErrorInstance::FoundExactSource);
</del><ins>+        message = appender(message, codeBlock-&gt;source()-&gt;getRange(expressionStart, expressionStop).toString(), type, ErrorInstance::FoundExactSource);
</ins><span class="cx">     else {
</span><span class="cx">         // No range information, so give a few characters of context.
</span><del>-        const StringImpl* data = sourceString.impl();
</del><span class="cx">         int dataLength = sourceString.length();
</span><span class="cx">         int start = expressionStart;
</span><span class="cx">         int stop = expressionStart;
</span><span class="cx">         // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
</span><span class="cx">         // Then strip whitespace.
</span><del>-        while (start &gt; 0 &amp;&amp; (expressionStart - start &lt; 20) &amp;&amp; (*data)[start - 1] != '\n')
</del><ins>+        while (start &gt; 0 &amp;&amp; (expressionStart - start &lt; 20) &amp;&amp; sourceString[start - 1] != '\n')
</ins><span class="cx">             start--;
</span><del>-        while (start &lt; (expressionStart - 1) &amp;&amp; isStrWhiteSpace((*data)[start]))
</del><ins>+        while (start &lt; (expressionStart - 1) &amp;&amp; isStrWhiteSpace(sourceString[start]))
</ins><span class="cx">             start++;
</span><del>-        while (stop &lt; dataLength &amp;&amp; (stop - expressionStart &lt; 20) &amp;&amp; (*data)[stop] != '\n')
</del><ins>+        while (stop &lt; dataLength &amp;&amp; (stop - expressionStart &lt; 20) &amp;&amp; sourceString[stop] != '\n')
</ins><span class="cx">             stop++;
</span><del>-        while (stop &gt; expressionStart &amp;&amp; isStrWhiteSpace((*data)[stop - 1]))
</del><ins>+        while (stop &gt; expressionStart &amp;&amp; isStrWhiteSpace(sourceString[stop - 1]))
</ins><span class="cx">             stop--;
</span><del>-        message = appender(message, codeBlock-&gt;source()-&gt;getRange(start, stop), type, ErrorInstance::FoundApproximateSource);
</del><ins>+        message = appender(message, codeBlock-&gt;source()-&gt;getRange(start, stop).toString(), type, ErrorInstance::FoundApproximateSource);
</ins><span class="cx">     }
</span><span class="cx">     exception-&gt;putDirect(*vm, vm-&gt;propertyNames-&gt;message, jsString(vm, message));
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeFunctionPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx">         
</span><span class="cx">         String functionHeader = executable-&gt;isArrowFunction() ? &quot;&quot; : &quot;function &quot;;
</span><span class="cx">         
</span><del>-        String source = executable-&gt;source().provider()-&gt;getRange(
</del><ins>+        StringView source = executable-&gt;source().provider()-&gt;getRange(
</ins><span class="cx">             executable-&gt;parametersStartOffset(),
</span><span class="cx">             executable-&gt;parametersStartOffset() + executable-&gt;source().length());
</span><span class="cx">         return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function-&gt;name(exec), source));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsFunctionOverridescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tools/FunctionOverrides.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/FunctionOverrides.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/JavaScriptCore/tools/FunctionOverrides.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -106,7 +106,7 @@
</span><span class="cx"> 
</span><span class="cx"> static void initializeOverrideInfo(const SourceCode&amp; origCode, const String&amp; newBody, FunctionOverrides::OverrideInfo&amp; info)
</span><span class="cx"> {
</span><del>-    String origProviderStr = origCode.provider()-&gt;source();
</del><ins>+    String origProviderStr = origCode.provider()-&gt;source().toString();
</ins><span class="cx">     unsigned origBraceStart = origCode.startOffset();
</span><span class="cx">     unsigned origFunctionStart = origProviderStr.reverseFind(&quot;function&quot;, origBraceStart);
</span><span class="cx">     unsigned headerLength = origBraceStart - origFunctionStart;
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">     ASSERT(Options::functionOverrides());
</span><span class="cx">     FunctionOverrides&amp; overrides = FunctionOverrides::overrides();
</span><span class="cx"> 
</span><del>-    auto it = overrides.m_entries.find(origCode.toString());
</del><ins>+    auto it = overrides.m_entries.find(origCode.view().toString());
</ins><span class="cx">     if (it == overrides.m_entries.end())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WTF/wtf/PrintStream.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -53,6 +53,11 @@
</span><span class="cx">     out.printf(&quot;%s&quot;, string);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void printInternal(PrintStream&amp; out, const StringView&amp; string)
+{
+    out.print(string.utf8());
+}
+
</ins><span class="cx"> void printInternal(PrintStream&amp; out, const CString&amp; string)
</span><span class="cx"> {
</span><span class="cx">     out.print(string.data());
</span></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WTF/wtf/PrintStream.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> class CString;
</span><span class="cx"> class String;
</span><span class="cx"> class StringImpl;
</span><ins>+class StringView;
</ins><span class="cx"> class UniquedStringImpl;
</span><span class="cx"> 
</span><span class="cx"> class PrintStream {
</span><span class="lines">@@ -70,6 +71,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const char*);
</span><ins>+WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const StringView&amp;);
</ins><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const CString&amp;);
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const String&amp;);
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const StringImpl*);
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/ChangeLog        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-12-13  Andreas Kling  &lt;akling@apple.com&gt;
+
+        CachedScript could have a copy-free path for all-ASCII scripts.
+        &lt;https://webkit.org/b/152203&gt;
+
+        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):
+
</ins><span class="cx"> 2015-12-13  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clean up absolute positioned map properly.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsCachedScriptSourceProviderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/bindings/js/CachedScriptSourceProvider.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -44,7 +44,8 @@
</span><span class="cx">         m_cachedScript-&gt;removeClient(this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    const String&amp; source() const { return m_cachedScript-&gt;script(); }
</del><ins>+    unsigned hash() const override { return m_cachedScript-&gt;scriptHash(); }
+    StringView source() const override { return m_cachedScript-&gt;script(); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     CachedScriptSourceProvider(CachedScript* cachedScript)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsScriptSourceCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/ScriptSourceCode.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/ScriptSourceCode.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/bindings/js/ScriptSourceCode.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx"> 
</span><span class="cx">     const JSC::SourceCode&amp; jsSourceCode() const { return m_code; }
</span><span class="cx"> 
</span><del>-    const String&amp; source() const { return m_provider-&gt;source(); }
</del><ins>+    StringView source() const { return m_provider-&gt;source(); }
</ins><span class="cx"> 
</span><span class="cx">     int startLine() const { return m_code.firstLine(); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorPageAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorPageAgent.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorPageAgent.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/inspector/InspectorPageAgent.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx">             *result = downcast&lt;CachedCSSStyleSheet&gt;(*cachedResource).sheetText();
</span><span class="cx">             return !result-&gt;isNull();
</span><span class="cx">         case CachedResource::Script:
</span><del>-            *result = downcast&lt;CachedScript&gt;(*cachedResource).script();
</del><ins>+            *result = downcast&lt;CachedScript&gt;(*cachedResource).script().toString();
</ins><span class="cx">             return true;
</span><span class="cx">         case CachedResource::RawResource: {
</span><span class="cx">             auto* buffer = cachedResource-&gt;resourceBuffer();
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedResourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedResource.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -787,7 +787,10 @@
</span><span class="cx">     if (m_data-&gt;size() != newBuffer.size() || memcmp(m_data-&gt;data(), newBuffer.data(), m_data-&gt;size()))
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_data-&gt;tryReplaceContentsWithPlatformBuffer(newBuffer);
</del><ins>+    if (m_data-&gt;tryReplaceContentsWithPlatformBuffer(newBuffer)) {
+        didReplaceSharedBufferContents();
+        // FIXME: Should we call checkNotify() here to move already-decoded images to the new data source?
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedResourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedResource.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -267,6 +267,8 @@
</span><span class="cx">     void setDecodedSize(unsigned);
</span><span class="cx">     void didAccessDecodedData(double timeStamp);
</span><span class="cx"> 
</span><ins>+    virtual void didReplaceSharedBufferContents() { }
+
</ins><span class="cx">     // FIXME: Make the rest of these data members private and use functions in derived classes instead.
</span><span class="cx">     HashCountedSet&lt;CachedResourceClient*&gt; m_clients;
</span><span class="cx">     ResourceRequest m_resourceRequest;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedScriptcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedScript.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedScript.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/loader/cache/CachedScript.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -69,16 +69,52 @@
</span><span class="cx">     return extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)).lower();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const String&amp; CachedScript::script()
</del><ins>+static bool encodingMayBeAllASCII(const String&amp; encoding)
</ins><span class="cx"> {
</span><ins>+    return encoding == &quot;UTF-8&quot; || encoding == &quot;ISO-8859-1&quot; || encoding == &quot;ASCII&quot;;
+}
+
+StringView CachedScript::script()
+{
</ins><span class="cx">     if (!m_script &amp;&amp; m_data) {
</span><ins>+        if (m_ASCIIOptimizationState == Unknown
+            &amp;&amp; encodingMayBeAllASCII(encoding())
+            &amp;&amp; m_data-&gt;size()
+            &amp;&amp; charactersAreAllASCII(reinterpret_cast&lt;const LChar*&gt;(m_data-&gt;data()), m_data-&gt;size())) {
+
+            m_script = StringImpl::createWithoutCopying(reinterpret_cast&lt;const LChar*&gt;(m_data-&gt;data()), m_data-&gt;size());
+            m_ASCIIOptimizationState = DataAndDecodedStringHaveSameBytes;
+
+            // If the encoded and decoded data are the same, there is no decoded data cost!
+            setDecodedSize(0);
+            m_decodedDataDeletionTimer.stop();
+            return m_script;
+        }
</ins><span class="cx">         m_script = m_decoder-&gt;decodeAndFlush(m_data-&gt;data(), encodedSize());
</span><ins>+        m_ASCIIOptimizationState = DataAndDecodedStringHaveDifferentBytes;
</ins><span class="cx">         setDecodedSize(m_script.sizeInBytes());
</span><span class="cx">     }
</span><del>-    m_decodedDataDeletionTimer.restart();
</del><ins>+    if (m_ASCIIOptimizationState == DataAndDecodedStringHaveDifferentBytes)
+        m_decodedDataDeletionTimer.restart();
</ins><span class="cx">     return m_script;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned CachedScript::scriptHash()
+{
+    script();
+    return m_script.impl()-&gt;hash();
+}
+
+void CachedScript::didReplaceSharedBufferContents()
+{
+    // We receive this callback when the CachedResource's internal SharedBuffer has had its contents
+    // replaced by the memory-mapping-of-file-backed-resources optimization. If m_script is just a
+    // non-copying wrapper around the old SharedBuffer contents, we have to retarget it.
+    if (m_ASCIIOptimizationState == DataAndDecodedStringHaveSameBytes)
+        m_script = StringImpl::createWithoutCopying(reinterpret_cast&lt;const LChar*&gt;(m_data-&gt;data()), m_data-&gt;size());
+    CachedResource::didReplaceSharedBufferContents();
+}
+
</ins><span class="cx"> void CachedScript::finishLoading(SharedBuffer* data)
</span><span class="cx"> {
</span><span class="cx">     m_data = data;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedScripth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedScript.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedScript.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/loader/cache/CachedScript.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -37,7 +37,8 @@
</span><span class="cx">     CachedScript(const ResourceRequest&amp;, const String&amp; charset, SessionID);
</span><span class="cx">     virtual ~CachedScript();
</span><span class="cx"> 
</span><del>-    const String&amp; script();
</del><ins>+    StringView script();
+    unsigned scriptHash();
</ins><span class="cx"> 
</span><span class="cx">     String mimeType() const;
</span><span class="cx"> 
</span><span class="lines">@@ -45,6 +46,8 @@
</span><span class="cx">     bool mimeTypeAllowedByNosniff() const;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void didReplaceSharedBufferContents() override;
+
</ins><span class="cx"> private:
</span><span class="cx">     virtual bool mayTryReplaceEncodedData() const override { return true; }
</span><span class="cx"> 
</span><span class="lines">@@ -57,6 +60,10 @@
</span><span class="cx">     virtual void destroyDecodedData() override;
</span><span class="cx"> 
</span><span class="cx">     String m_script;
</span><ins>+
+    enum ASCIIResourceOptimizationState { Unknown, DataAndDecodedStringHaveSameBytes, DataAndDecodedStringHaveDifferentBytes };
+    ASCIIResourceOptimizationState m_ASCIIOptimizationState { Unknown };
+
</ins><span class="cx">     RefPtr&lt;TextResourceDecoder&gt; m_decoder;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformSharedBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/SharedBuffer.h (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/SharedBuffer.h        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/platform/SharedBuffer.h        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -119,7 +119,7 @@
</span><span class="cx">     //      }
</span><span class="cx">     WEBCORE_EXPORT unsigned getSomeData(const char*&amp; data, unsigned position = 0) const;
</span><span class="cx"> 
</span><del>-    void tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp;);
</del><ins>+    bool tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp;);
</ins><span class="cx">     WEBCORE_EXPORT bool hasPlatformData() const;
</span><span class="cx"> 
</span><span class="cx">     struct DataBuffer : public ThreadSafeRefCounted&lt;DataBuffer&gt; {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcfSharedBufferCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -92,13 +92,14 @@
</span><span class="cx">     m_cfData = 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp; newContents)
</del><ins>+bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp; newContents)
</ins><span class="cx"> {
</span><span class="cx">     if (!newContents.m_cfData)
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx"> 
</span><span class="cx">     clear();
</span><span class="cx">     m_cfData = newContents.m_cfData;
</span><ins>+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SharedBuffer::maybeAppendPlatformData(SharedBuffer* newContents)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformsoupSharedBufferSoupcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -78,14 +78,15 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp; newContents)
</del><ins>+bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer&amp; newContents)
</ins><span class="cx"> {
</span><span class="cx">     if (!newContents.hasPlatformData())
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx"> 
</span><span class="cx">     clear();
</span><span class="cx">     // FIXME: Use GRefPtr instead of GUniquePtr for the SoupBuffer.
</span><span class="cx">     m_soupBuffer.swap(newContents.m_soupBuffer);
</span><ins>+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebScriptDebuggermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm (194016 => 194017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm        2015-12-13 16:18:07 UTC (rev 194016)
+++ trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm        2015-12-13 20:03:24 UTC (rev 194017)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> 
</span><span class="cx"> static NSString *toNSString(SourceProvider* sourceProvider)
</span><span class="cx"> {
</span><del>-    const String&amp; sourceString = sourceProvider-&gt;source();
</del><ins>+    const String&amp; sourceString = sourceProvider-&gt;source().toString();
</ins><span class="cx">     if (sourceString.isEmpty())
</span><span class="cx">         return nil;
</span><span class="cx">     return sourceString;
</span></span></pre>
</div>
</div>

</body>
</html>