WebKit Bugzilla
Attachment 362778 Details for
Bug 194912
: Make JSScript:cacheBytecodeWithError update the cache when the script changes
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
b-backup.diff (text/plain), 20.72 KB, created by
Saam Barati
on 2019-02-22 16:10:46 PST
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-02-22 16:10:46 PST
Size:
20.72 KB
patch
obsolete
>Index: Source/JavaScriptCore/API/JSScript.mm >=================================================================== >--- Source/JavaScriptCore/API/JSScript.mm (revision 241963) >+++ Source/JavaScriptCore/API/JSScript.mm (working copy) >@@ -27,6 +27,8 @@ > #import "JSScriptInternal.h" > > #import "APICast.h" >+#import "CachedTypes.h" >+#import "CodeCache.h" > #import "Identifier.h" > #import "JSContextInternal.h" > #import "JSScriptSourceProvider.h" >@@ -201,7 +203,17 @@ - (void)readCache > void* buffer = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); > close(fd); > >+ dataLogLn("Read cache on creation!"); > m_cachedBytecode = JSC::CachedBytecode { buffer, size }; >+ >+ JSC::VM& vm = m_virtualMachine.vm; >+ >+ const JSC::SourceCode& sourceCode = [self jsSourceCode]->sourceCode(); >+ JSC::SourceCodeKey key = m_type == kJSScriptTypeProgram ? sourceCodeKeyForSerializedProgram(vm, sourceCode) : sourceCodeKeyForSerializedModule(vm, sourceCode); >+ if (!isCachedBytecodeStillValid(vm, m_cachedBytecode, key, m_type == kJSScriptTypeProgram ? JSC::SourceCodeType::ProgramType : JSC::SourceCodeType::ModuleType)) { >+ m_cachedBytecode = { }; >+ dataLogLn("No longer valid cache, clearing entry!"); >+ } > } > > - (BOOL)cacheBytecodeWithError:(NSError **)error >@@ -255,8 +267,10 @@ - (JSC::JSSourceCode*)jsSourceCode > > - (BOOL)writeCache:(String&)error > { >- if (m_cachedBytecode.size()) >+ if (m_cachedBytecode.size()) { >+ dataLogLn("Already have cache"); > return YES; >+ } > > if (!m_cachePath) { > error = "No cache was path provided during construction of this JSScript."_s; >@@ -269,7 +283,7 @@ - (BOOL)writeCache:(String&)error > m_cachedBytecode = JSC::generateModuleBytecode(m_virtualMachine.vm, [self jsSourceCode]->sourceCode(), parserError); > break; > case kJSScriptTypeProgram: >- m_cachedBytecode = JSC::generateBytecode(m_virtualMachine.vm, [self jsSourceCode]->sourceCode(), parserError); >+ m_cachedBytecode = JSC::generateProgramBytecode(m_virtualMachine.vm, [self jsSourceCode]->sourceCode(), parserError); > break; > } > >Index: Source/JavaScriptCore/API/tests/testapi.mm >=================================================================== >--- Source/JavaScriptCore/API/tests/testapi.mm (revision 241963) >+++ Source/JavaScriptCore/API/tests/testapi.mm (working copy) >@@ -2094,6 +2094,50 @@ static void testBytecodeCacheWithSyntaxE > } > } > >+static void testBytecodeCacheWithSameCacheFileAndDifferentScript(bool forceDiskCache) >+{ >+ NSURL *cachePath = tempFile(@"cachePath.cache"); >+ NSURL *sourceURL = [NSURL URLWithString:@"my-path"]; >+ >+ @autoreleasepool { >+ JSVirtualMachine *vm = [[JSVirtualMachine alloc] init]; >+ NSString *source = @"function foo() { return 42; }; function bar() { return 40; }; foo() + bar();"; >+ JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm]; >+ JSScript *script = [JSScript scriptOfType:kJSScriptTypeProgram withSource:source andSourceURL:sourceURL andBytecodeCache:cachePath inVirtualMachine:vm error:nil]; >+ RELEASE_ASSERT(script); >+ if (![script cacheBytecodeWithError:nil]) >+ CRASH(); >+ >+ JSC::Options::forceDiskCache() = forceDiskCache; >+ JSValue *result = [context evaluateJSScript:script]; >+ RELEASE_ASSERT(result); >+ RELEASE_ASSERT([result isNumber]); >+ checkResult(@"Expected 82 as result", [[result toNumber] intValue] == 82); >+ } >+ >+ @autoreleasepool { >+ JSVirtualMachine *vm = [[JSVirtualMachine alloc] init]; >+ NSString *source = @"function foo() { return 10; }; function bar() { return 20; }; foo() + bar();"; >+ JSContext *context = [[JSContext alloc] initWithVirtualMachine:vm]; >+ JSScript *script = [JSScript scriptOfType:kJSScriptTypeProgram withSource:source andSourceURL:sourceURL andBytecodeCache:cachePath inVirtualMachine:vm error:nil]; >+ RELEASE_ASSERT(script); >+ if (![script cacheBytecodeWithError:nil]) >+ CRASH(); >+ >+ JSC::Options::forceDiskCache() = forceDiskCache; >+ JSValue *result = [context evaluateJSScript:script]; >+ RELEASE_ASSERT(result); >+ RELEASE_ASSERT([result isNumber]); >+ checkResult(@"Expected 30 as result", [[result toNumber] intValue] == 30); >+ } >+ >+ JSC::Options::forceDiskCache() = false; >+ >+ NSFileManager* fileManager = [NSFileManager defaultManager]; >+ BOOL removedAll = [fileManager removeItemAtURL:cachePath error:nil]; >+ checkResult(@"Removed all temp files created", removedAll); >+} >+ > static void testProgramJSScriptException() > { > @autoreleasepool { >@@ -2319,6 +2363,8 @@ void testObjectiveCAPI(const char* filte > RUN(testProgramBytecodeCache()); > RUN(testBytecodeCacheWithSyntaxError(kJSScriptTypeProgram)); > RUN(testBytecodeCacheWithSyntaxError(kJSScriptTypeModule)); >+ RUN(testBytecodeCacheWithSameCacheFileAndDifferentScript(false)); >+ RUN(testBytecodeCacheWithSameCacheFileAndDifferentScript(true)); > RUN(testProgramJSScriptException()); > > RUN(testLoaderRejectsNilScriptURL()); >Index: Source/JavaScriptCore/runtime/CachedTypes.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CachedTypes.cpp (revision 241963) >+++ Source/JavaScriptCore/runtime/CachedTypes.cpp (working copy) >@@ -33,6 +33,7 @@ > #include "JSTemplateObjectDescriptor.h" > #include "ScopedArgumentsTable.h" > #include "SourceCodeKey.h" >+#include "SourceProvider.h" > #include "UnlinkedEvalCodeBlock.h" > #include "UnlinkedFunctionCodeBlock.h" > #include "UnlinkedMetadataTableInlines.h" >@@ -217,7 +218,7 @@ class Decoder { > public: > Decoder(VM& vm, const void* baseAddress, size_t size) > : m_vm(vm) >- , m_baseAddress(reinterpret_cast<const uint8_t*>(baseAddress)) >+ , m_baseAddress(bitwise_cast<const uint8_t*>(baseAddress)) > #ifndef NDEBUG > , m_size(size) > #endif >@@ -334,13 +335,13 @@ protected: > const uint8_t* buffer() const > { > ASSERT(m_offset != s_invalidOffset); >- return reinterpret_cast<const uint8_t*>(this) + m_offset; >+ return bitwise_cast<const uint8_t*>(this) + m_offset; > } > > template<typename T> > const T* buffer() const > { >- return reinterpret_cast<const T*>(buffer()); >+ return bitwise_cast<const T*>(buffer()); > } > > uint8_t* allocate(Encoder& encoder, size_t size) >@@ -398,7 +399,7 @@ public: > ptrdiff_t bufferOffset = decoder.offsetOf(this->buffer()); > if (WTF::Optional<void*> ptr = decoder.cachedPtrForOffset(bufferOffset)) { > isNewAllocation = false; >- return reinterpret_cast<Source*>(*ptr); >+ return bitwise_cast<Source*>(*ptr); > } > > isNewAllocation = true; >@@ -1800,6 +1801,21 @@ enum CachedCodeBlockTag { > CachedEvalCodeBlockTag, > }; > >+static constexpr CachedCodeBlockTag tagFromSourceCodeType(SourceCodeType type) >+{ >+ switch (type) { >+ case SourceCodeType::ProgramType: >+ return CachedProgramCodeBlockTag; >+ case SourceCodeType::EvalType: >+ return CachedEvalCodeBlockTag; >+ case SourceCodeType::ModuleType: >+ return CachedModuleCodeBlockTag; >+ case SourceCodeType::FunctionType: >+ ASSERT_NOT_REACHED(); >+ return static_cast<CachedCodeBlockTag>(-1); >+ } >+} >+ > template<> > struct CachedCodeBlockTypeImpl<UnlinkedProgramCodeBlock> { > using type = CachedProgramCodeBlock; >@@ -2063,6 +2079,7 @@ private: > class GenericCacheEntry { > public: > bool decode(Decoder&, std::pair<SourceCodeKey, UnlinkedCodeBlock*>&) const; >+ bool isStillValid(Decoder&, const SourceCodeKey&, CachedCodeBlockTag) const; > > protected: > GenericCacheEntry(Encoder& encoder, CachedCodeBlockTag tag) >@@ -2096,6 +2113,13 @@ public: > private: > friend GenericCacheEntry; > >+ bool isStillValid(Decoder& decoder, const SourceCodeKey& key) const >+ { >+ SourceCodeKey decodedKey; >+ m_key.decode(decoder, decodedKey); >+ return decodedKey == key; >+ } >+ > bool decode(Decoder& decoder, std::pair<SourceCodeKey, UnlinkedCodeBlockType*>& result) const > { > ASSERT(tag() == CachedCodeBlockTypeImpl<UnlinkedCodeBlockType>::tag); >@@ -2118,9 +2142,9 @@ bool GenericCacheEntry::decode(Decoder& > > switch (m_tag) { > case CachedProgramCodeBlockTag: >- return reinterpret_cast<const CacheEntry<UnlinkedProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedProgramCodeBlock*>&>(result)); >+ return bitwise_cast<const CacheEntry<UnlinkedProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedProgramCodeBlock*>&>(result)); > case CachedModuleCodeBlockTag: >- return reinterpret_cast<const CacheEntry<UnlinkedModuleProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedModuleProgramCodeBlock*>&>(result)); >+ return bitwise_cast<const CacheEntry<UnlinkedModuleProgramCodeBlock>*>(this)->decode(decoder, reinterpret_cast<std::pair<SourceCodeKey, UnlinkedModuleProgramCodeBlock*>&>(result)); > case CachedEvalCodeBlockTag: > // We do not cache eval code blocks > RELEASE_ASSERT_NOT_REACHED(); >@@ -2132,11 +2156,31 @@ bool GenericCacheEntry::decode(Decoder& > #endif > } > >+bool GenericCacheEntry::isStillValid(Decoder& decoder, const SourceCodeKey& key, CachedCodeBlockTag tag) const >+{ >+ if (m_cacheVersion != JSC_BYTECODE_CACHE_VERSION) >+ return false; >+ if (m_bootSessionUUID.decode(decoder) != bootSessionUUIDString()) >+ return false; >+ >+ switch (tag) { >+ case CachedProgramCodeBlockTag: >+ return bitwise_cast<const CacheEntry<UnlinkedProgramCodeBlock>*>(this)->isStillValid(decoder, key); >+ case CachedModuleCodeBlockTag: >+ return bitwise_cast<const CacheEntry<UnlinkedModuleProgramCodeBlock>*>(this)->isStillValid(decoder, key); >+ case CachedEvalCodeBlockTag: >+ // We do not cache eval code blocks >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+ return false; >+} >+ > template<typename UnlinkedCodeBlockType> > void encodeCodeBlock(Encoder& encoder, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock) > { > auto* entry = encoder.template malloc<CacheEntry<UnlinkedCodeBlockType>>(encoder); >- entry->encode(encoder, { key, jsCast<const UnlinkedCodeBlockType*>(codeBlock) }); >+ entry->encode(encoder, { key, jsCast<const UnlinkedCodeBlockType*>(codeBlock) }); > } > > std::pair<MallocPtr<uint8_t>, size_t> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock) >@@ -2156,18 +2200,32 @@ std::pair<MallocPtr<uint8_t>, size_t> en > > UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size) > { >- const auto* cachedEntry = reinterpret_cast<const GenericCacheEntry*>(buffer); >+ const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(buffer); > Decoder decoder(vm, buffer, size); > std::pair<SourceCodeKey, UnlinkedCodeBlock*> entry; > { > DeferGC deferGC(vm.heap); >- if (!cachedEntry->decode(decoder, entry)) >+ if (!cachedEntry->decode(decoder, entry)) { >+ dataLogLn("returning nullptr decodeCodeBlockImpl"); > return nullptr; >+ } > } > >- if (entry.first != key) >+ if (entry.first != key) { >+ dataLogLn("returning nullptr decodeCodeBlockImpl different keys"); > return nullptr; >+ } > return entry.second; > } > >+bool isCachedBytecodeStillValid(VM& vm, const CachedBytecode& cachedBytecode, const SourceCodeKey& key, SourceCodeType type) >+{ >+ const void* buffer = cachedBytecode.data(); >+ size_t size = cachedBytecode.size(); >+ const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(buffer); >+ Decoder decoder(vm, buffer, size); >+ >+ return cachedEntry->isStillValid(decoder, key, tagFromSourceCodeType(type)); >+} >+ > } // namespace JSC >Index: Source/JavaScriptCore/runtime/CachedTypes.h >=================================================================== >--- Source/JavaScriptCore/runtime/CachedTypes.h (revision 241963) >+++ Source/JavaScriptCore/runtime/CachedTypes.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * Copyright (C) 2018-2019 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -30,9 +30,12 @@ > > namespace JSC { > >+class CachedBytecode; > class SourceCodeKey; > class UnlinkedCodeBlock; > >+enum class SourceCodeType; >+ > std::pair<MallocPtr<uint8_t>, size_t> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*); > UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, const void*, size_t); > >@@ -43,4 +46,6 @@ UnlinkedCodeBlockType* decodeCodeBlock(V > return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, buffer, size)); > } > >+bool isCachedBytecodeStillValid(VM&, const CachedBytecode&, const SourceCodeKey&, SourceCodeType); >+ > } // namespace JSC >Index: Source/JavaScriptCore/runtime/CodeCache.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CodeCache.cpp (revision 241963) >+++ Source/JavaScriptCore/runtime/CodeCache.cpp (working copy) >@@ -205,15 +205,36 @@ void writeCodeBlock(VM& vm, const Source > }); > } > >-CachedBytecode serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode) >+static SourceCodeKey sourceCodeKeyForSerializedBytecode(VM& vm, const SourceCode& sourceCode, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode) > { >- SourceCodeKey key( >- source, String(), codeType, strictMode, scriptMode, >+ return SourceCodeKey( >+ sourceCode, String(), codeType, strictMode, scriptMode, > DerivedContextType::None, EvalContextType::None, false, debuggerMode, > vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, > vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No, > WTF::nullopt); >- std::pair<MallocPtr<uint8_t>, size_t> result = encodeCodeBlock(vm, key, codeBlock); >+} >+ >+SourceCodeKey sourceCodeKeyForSerializedProgram(VM& vm, const SourceCode& sourceCode) >+{ >+ JSParserStrictMode strictMode = JSParserStrictMode::NotStrict; >+ JSParserScriptMode scriptMode = JSParserScriptMode::Classic; >+ DebuggerMode debuggerMode = DebuggerOff; >+ return sourceCodeKeyForSerializedBytecode(vm, sourceCode, SourceCodeType::ProgramType, strictMode, scriptMode, debuggerMode); >+} >+ >+SourceCodeKey sourceCodeKeyForSerializedModule(VM& vm, const SourceCode& sourceCode) >+{ >+ JSParserStrictMode strictMode = JSParserStrictMode::Strict; >+ JSParserScriptMode scriptMode = JSParserScriptMode::Module; >+ DebuggerMode debuggerMode = DebuggerOff; >+ return sourceCodeKeyForSerializedBytecode(vm, sourceCode, SourceCodeType::ModuleType, strictMode, scriptMode, debuggerMode); >+} >+ >+CachedBytecode serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode) >+{ >+ std::pair<MallocPtr<uint8_t>, size_t> result = encodeCodeBlock(vm, >+ sourceCodeKeyForSerializedBytecode(vm, source, codeType, strictMode, scriptMode, debuggerMode), codeBlock); > return CachedBytecode { WTFMove(result.first), result.second }; > } > >Index: Source/JavaScriptCore/runtime/CodeCache.h >=================================================================== >--- Source/JavaScriptCore/runtime/CodeCache.h (revision 241963) >+++ Source/JavaScriptCore/runtime/CodeCache.h (working copy) >@@ -104,33 +104,6 @@ public: > iterator end() { return m_map.end(); } > > template<typename UnlinkedCodeBlockType> >- UnlinkedCodeBlockType* fetchFromDiskImpl(VM& vm, const SourceCodeKey& key) >- { >- const CachedBytecode* cachedBytecode = key.source().provider().cachedBytecode(); >- if (cachedBytecode && cachedBytecode->size()) { >- VERBOSE_LOG("Found cached CodeBlock in the SourceProvider"); >- UnlinkedCodeBlockType* unlinkedCodeBlock = decodeCodeBlock<UnlinkedCodeBlockType>(vm, key, cachedBytecode->data(), cachedBytecode->size()); >- if (unlinkedCodeBlock) >- return unlinkedCodeBlock; >- } >- return nullptr; >- } >- >- template<typename UnlinkedCodeBlockType> >- std::enable_if_t<std::is_base_of<UnlinkedCodeBlock, UnlinkedCodeBlockType>::value && !std::is_same<UnlinkedCodeBlockType, UnlinkedEvalCodeBlock>::value, UnlinkedCodeBlockType*> >- fetchFromDisk(VM& vm, const SourceCodeKey& key) >- { >- UnlinkedCodeBlockType* codeBlock = fetchFromDiskImpl<UnlinkedCodeBlockType>(vm, key); >- if (UNLIKELY(Options::forceDiskCache())) >- RELEASE_ASSERT(codeBlock); >- return codeBlock; >- } >- >- template<typename T> >- std::enable_if_t<!std::is_base_of<UnlinkedCodeBlock, T>::value || std::is_same<T, UnlinkedEvalCodeBlock>::value, T*> >- fetchFromDisk(VM&, const SourceCodeKey&) { return nullptr; } >- >- template<typename UnlinkedCodeBlockType> > UnlinkedCodeBlockType* findCacheAndUpdateAge(VM& vm, const SourceCodeKey& key) > { > prune(); >@@ -190,6 +163,33 @@ public: > int64_t age() { return m_age; } > > private: >+ template<typename UnlinkedCodeBlockType> >+ UnlinkedCodeBlockType* fetchFromDiskImpl(VM& vm, const SourceCodeKey& key) >+ { >+ const CachedBytecode* cachedBytecode = key.source().provider().cachedBytecode(); >+ if (cachedBytecode && cachedBytecode->size()) { >+ VERBOSE_LOG("Found cached CodeBlock in the SourceProvider"); >+ UnlinkedCodeBlockType* unlinkedCodeBlock = decodeCodeBlock<UnlinkedCodeBlockType>(vm, key, cachedBytecode->data(), cachedBytecode->size()); >+ if (unlinkedCodeBlock) >+ return unlinkedCodeBlock; >+ } >+ return nullptr; >+ } >+ >+ template<typename UnlinkedCodeBlockType> >+ std::enable_if_t<std::is_base_of<UnlinkedCodeBlock, UnlinkedCodeBlockType>::value && !std::is_same<UnlinkedCodeBlockType, UnlinkedEvalCodeBlock>::value, UnlinkedCodeBlockType*> >+ fetchFromDisk(VM& vm, const SourceCodeKey& key) >+ { >+ UnlinkedCodeBlockType* codeBlock = fetchFromDiskImpl<UnlinkedCodeBlockType>(vm, key); >+ if (UNLIKELY(Options::forceDiskCache())) >+ RELEASE_ASSERT(codeBlock); >+ return codeBlock; >+ } >+ >+ template<typename T> >+ std::enable_if_t<!std::is_base_of<UnlinkedCodeBlock, T>::value || std::is_same<T, UnlinkedEvalCodeBlock>::value, T*> >+ fetchFromDisk(VM&, const SourceCodeKey&) { return nullptr; } >+ > // This constant factor biases cache capacity toward allowing a minimum > // working set to enter the cache before it starts evicting. > static const Seconds workingSetTime; >@@ -330,5 +330,7 @@ recursivelyGenerateUnlinkedCodeBlock(VM& > > void writeCodeBlock(VM&, const SourceCodeKey&, const SourceCodeValue&); > CachedBytecode serializeBytecode(VM&, UnlinkedCodeBlock*, const SourceCode&, SourceCodeType, JSParserStrictMode, JSParserScriptMode, DebuggerMode); >+SourceCodeKey sourceCodeKeyForSerializedProgram(VM&, const SourceCode&); >+SourceCodeKey sourceCodeKeyForSerializedModule(VM&, const SourceCode&); > > } // namespace JSC >Index: Source/JavaScriptCore/runtime/Completion.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/Completion.cpp (revision 241963) >+++ Source/JavaScriptCore/runtime/Completion.cpp (working copy) >@@ -91,7 +91,7 @@ bool checkModuleSyntax(ExecState* exec, > return true; > } > >-CachedBytecode generateBytecode(VM& vm, const SourceCode& source, ParserError& error) >+CachedBytecode generateProgramBytecode(VM& vm, const SourceCode& source, ParserError& error) > { > JSLockHolder lock(vm); > RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable()); >Index: Source/JavaScriptCore/runtime/Completion.h >=================================================================== >--- Source/JavaScriptCore/runtime/Completion.h (revision 241963) >+++ Source/JavaScriptCore/runtime/Completion.h (working copy) >@@ -42,7 +42,7 @@ JS_EXPORT_PRIVATE bool checkSyntax(VM&, > JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0); > JS_EXPORT_PRIVATE bool checkModuleSyntax(ExecState*, const SourceCode&, ParserError&); > >-JS_EXPORT_PRIVATE CachedBytecode generateBytecode(VM&, const SourceCode&, ParserError&); >+JS_EXPORT_PRIVATE CachedBytecode generateProgramBytecode(VM&, const SourceCode&, ParserError&); > JS_EXPORT_PRIVATE CachedBytecode generateModuleBytecode(VM&, const SourceCode&, ParserError&); > > JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, const SourceCode&, JSValue thisValue, NakedPtr<Exception>& returnedException);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194912
:
362778
|
362785