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