Changeset 244143 in webkit


Ignore:
Timestamp:
Apr 10, 2019 12:18:20 PM (5 years ago)
Author:
Tadeu Zagallo
Message:

Add support for incremental bytecode cache updates
https://bugs.webkit.org/show_bug.cgi?id=195000

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Add support for incremental updates to the bytecode cache. The cache
is constructed as follows:

  • When the cache is empty, the initial payload can be added to the BytecodeCache

by calling BytecodeCache::addGlobalUpdate. This represents the encoded
top-level UnlinkedCodeBlock.

  • Afterwards, updates can be added by calling BytecodeCache::addFunctionUpdate.

The update is applied by appending the encoded UnlinkedFunctionCodeBlock
to the existing cache and updating the CachedFunctionExecutableMetadata
and the offset of the new CachedFunctionCodeBlock in the owner CachedFunctionExecutable.

  • API/JSScript.mm:

(-[JSScript readCache]):
(-[JSScript isUsingBytecodeCache]):
(-[JSScript init]):
(-[JSScript cachedBytecode]):
(-[JSScript writeCache:]):

  • API/JSScriptInternal.h:
  • API/JSScriptSourceProvider.h:
  • API/JSScriptSourceProvider.mm:

(JSScriptSourceProvider::cachedBytecode const):

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::generateUnlinkedFunctionCodeBlock):

  • jsc.cpp:

(ShellSourceProvider::~ShellSourceProvider):
(ShellSourceProvider::cachePath const):
(ShellSourceProvider::loadBytecode const):
(ShellSourceProvider::ShellSourceProvider):
(ShellSourceProvider::cacheEnabled):

  • parser/SourceProvider.h:

(JSC::SourceProvider::cachedBytecode const):
(JSC::SourceProvider::updateCache const):
(JSC::SourceProvider::commitCachedBytecode const):

  • runtime/CachePayload.cpp: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.

(JSC::CachePayload::makeMappedPayload):
(JSC::CachePayload::makeMallocPayload):
(JSC::CachePayload::makeEmptyPayload):
(JSC::CachePayload::CachePayload):
(JSC::CachePayload::~CachePayload):
(JSC::CachePayload::operator=):
(JSC::CachePayload::freeData):

  • runtime/CachePayload.h: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.

(JSC::CachePayload::data const):
(JSC::CachePayload::size const):
(JSC::CachePayload::CachePayload):

  • runtime/CacheUpdate.cpp: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.

(JSC::CacheUpdate::CacheUpdate):
(JSC::CacheUpdate::operator=):
(JSC::CacheUpdate::isGlobal const):
(JSC::CacheUpdate::asGlobal const):
(JSC::CacheUpdate::asFunction const):

  • runtime/CacheUpdate.h: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.
  • runtime/CachedBytecode.cpp: Added.

(JSC::CachedBytecode::addGlobalUpdate):
(JSC::CachedBytecode::addFunctionUpdate):
(JSC::CachedBytecode::copyLeafExecutables):
(JSC::CachedBytecode::commitUpdates const):

  • runtime/CachedBytecode.h: Added.

(JSC::CachedBytecode::create):
(JSC::CachedBytecode::leafExecutables):
(JSC::CachedBytecode::data const):
(JSC::CachedBytecode::size const):
(JSC::CachedBytecode::hasUpdates const):
(JSC::CachedBytecode::sizeForUpdate const):
(JSC::CachedBytecode::CachedBytecode):

  • runtime/CachedTypes.cpp:

(JSC::Encoder::addLeafExecutable):
(JSC::Encoder::release):
(JSC::Decoder::Decoder):
(JSC::Decoder::create):
(JSC::Decoder::size const):
(JSC::Decoder::offsetOf):
(JSC::Decoder::ptrForOffsetFromBase):
(JSC::Decoder::addLeafExecutable):
(JSC::VariableLengthObject::VariableLengthObject):
(JSC::VariableLengthObject::buffer const):
(JSC::CachedPtrOffsets::offsetOffset):
(JSC::CachedWriteBarrierOffsets::ptrOffset):
(JSC::CachedFunctionExecutable::features const):
(JSC::CachedFunctionExecutable::hasCapturedVariables const):
(JSC::CachedFunctionExecutableOffsets::codeBlockForCallOffset):
(JSC::CachedFunctionExecutableOffsets::codeBlockForConstructOffset):
(JSC::CachedFunctionExecutableOffsets::metadataOffset):
(JSC::CachedFunctionExecutable::encode):
(JSC::CachedFunctionExecutable::decode const):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::encodeCodeBlock):
(JSC::encodeFunctionCodeBlock):
(JSC::decodeCodeBlockImpl):
(JSC::isCachedBytecodeStillValid):

  • runtime/CachedTypes.h:

(JSC::VariableLengthObjectBase::VariableLengthObjectBase):
(JSC::decodeCodeBlock):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getUnlinkedGlobalCodeBlock):
(JSC::CodeCache::updateCache):
(JSC::CodeCache::write):
(JSC::writeCodeBlock):
(JSC::serializeBytecode):

  • runtime/CodeCache.h:

(JSC::SourceCodeValue::SourceCodeValue):
(JSC::CodeCacheMap::findCacheAndUpdateAge):
(JSC::CodeCacheMap::fetchFromDiskImpl):

  • runtime/Completion.cpp:

(JSC::generateProgramBytecode):
(JSC::generateModuleBytecode):

  • runtime/Completion.h:
  • runtime/LeafExecutable.cpp: Copied from Source/JavaScriptCore/API/JSScriptSourceProvider.mm.

(JSC::LeafExecutable::operator+ const):

  • runtime/LeafExecutable.h: Copied from Source/JavaScriptCore/API/JSScriptSourceProvider.mm.

(JSC::LeafExecutable::LeafExecutable):
(JSC::LeafExecutable::base const):

Tools:

Exit when the initial run to generate bytecode fails.

  • Scripts/jsc-stress-test-helpers/bytecode-cache-test-helper.sh:
Location:
trunk
Files:
2 added
19 edited
6 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSScript.mm

    r242982 r244143  
    5151    RetainPtr<NSURL> m_sourceURL;
    5252    RetainPtr<NSURL> m_cachePath;
    53     JSC::CachedBytecode m_cachedBytecode;
     53    RefPtr<JSC::CachedBytecode> m_cachedBytecode;
    5454}
    5555
     
    170170}
    171171
    172 - (void)dealloc
    173 {
    174     if (m_cachedBytecode.size() && !m_cachedBytecode.owned())
    175         munmap(const_cast<void*>(m_cachedBytecode.data()), m_cachedBytecode.size());
    176 
    177     [super dealloc];
    178 }
    179 
    180172- (void)readCache
    181173{
     
    198190    void* buffer = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
    199191
    200     JSC::CachedBytecode cachedBytecode { buffer, size };
     192    Ref<JSC::CachedBytecode> cachedBytecode = JSC::CachedBytecode::create(buffer, size);
    201193
    202194    JSC::VM& vm = m_virtualMachine.vm;
    203195    JSC::SourceCode sourceCode = [self sourceCode];
    204196    JSC::SourceCodeKey key = m_type == kJSScriptTypeProgram ? sourceCodeKeyForSerializedProgram(vm, sourceCode) : sourceCodeKeyForSerializedModule(vm, sourceCode);
    205     if (isCachedBytecodeStillValid(vm, cachedBytecode, key, m_type == kJSScriptTypeProgram ? JSC::SourceCodeType::ProgramType : JSC::SourceCodeType::ModuleType))
     197    if (isCachedBytecodeStillValid(vm, cachedBytecode.copyRef(), key, m_type == kJSScriptTypeProgram ? JSC::SourceCodeType::ProgramType : JSC::SourceCodeType::ModuleType))
    206198        m_cachedBytecode = WTFMove(cachedBytecode);
    207199    else
     
    223215- (BOOL)isUsingBytecodeCache
    224216{
    225     return !!m_cachedBytecode.size();
     217    return !!m_cachedBytecode->size();
    226218}
    227219
     
    246238        return nil;
    247239
     240    self->m_cachedBytecode = JSC::CachedBytecode::create();
     241
    248242    return self;
    249243}
     
    259253}
    260254
    261 - (const JSC::CachedBytecode*)cachedBytecode
    262 {
    263     return &m_cachedBytecode;
     255- (RefPtr<JSC::CachedBytecode>)cachedBytecode
     256{
     257    return m_cachedBytecode;
    264258}
    265259
     
    287281- (BOOL)writeCache:(String&)error
    288282{
    289     if (m_cachedBytecode.size()) {
     283    if (self.isUsingBytecodeCache) {
    290284        error = "Cache for JSScript is already non-empty. Can not override it."_s;
    291285        return NO;
     
    318312
    319313    if (parserError.isValid()) {
    320         m_cachedBytecode = { };
     314        m_cachedBytecode = JSC::CachedBytecode::create();
    321315        error = makeString("Unable to generate bytecode for this JSScript because of a parser error: ", parserError.message());
    322316        return NO;
    323317    }
    324318
    325     ssize_t bytesWritten = write(fd, m_cachedBytecode.data(), m_cachedBytecode.size());
     319    ssize_t bytesWritten = write(fd, m_cachedBytecode->data(), m_cachedBytecode->size());
    326320    if (bytesWritten == -1) {
    327321        error = makeString("Could not write cache file to disk: ", strerror(errno));
     
    329323    }
    330324
    331     if (static_cast<size_t>(bytesWritten) != m_cachedBytecode.size()) {
     325    if (static_cast<size_t>(bytesWritten) != m_cachedBytecode->size()) {
    332326        ftruncate(fd, 0);
    333         error = makeString("Could not write the full cache file to disk. Only wrote ", String::number(bytesWritten), " of the expected ", String::number(m_cachedBytecode.size()), " bytes.");
     327        error = makeString("Could not write the full cache file to disk. Only wrote ", String::number(bytesWritten), " of the expected ", String::number(m_cachedBytecode->size()), " bytes.");
    334328        return NO;
    335329    }
  • trunk/Source/JavaScriptCore/API/JSScriptInternal.h

    r242980 r244143  
    2828#import "JSScript.h"
    2929#import "SourceCode.h"
     30#import <wtf/RefPtr.h>
    3031
    3132#if JSC_OBJC_API_ENABLED
     
    4849- (unsigned)hash;
    4950- (const WTF::String&)source;
    50 - (nullable const JSC::CachedBytecode*)cachedBytecode;
     51- (RefPtr<JSC::CachedBytecode>)cachedBytecode;
    5152- (JSC::JSSourceCode*)jsSourceCode;
    5253- (JSC::SourceCode)sourceCode;
  • trunk/Source/JavaScriptCore/API/JSScriptSourceProvider.h

    r240511 r244143  
    4040    unsigned hash() const override;
    4141    StringView source() const override;
    42     const JSC::CachedBytecode* cachedBytecode() const override;
     42    RefPtr<JSC::CachedBytecode> cachedBytecode() const override;
    4343
    4444private:
  • trunk/Source/JavaScriptCore/API/JSScriptSourceProvider.mm

    r240511 r244143  
    4141}
    4242
    43 const JSC::CachedBytecode* JSScriptSourceProvider::cachedBytecode() const
     43RefPtr<JSC::CachedBytecode> JSScriptSourceProvider::cachedBytecode() const
    4444{
    4545    return [m_script.get() cachedBytecode];
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r244065 r244143  
    762762    runtime/Butterfly.h
    763763    runtime/ButterflyInlines.h
     764    runtime/CachePayload.h
     765    runtime/CacheUpdate.h
     766    runtime/CachedBytecode.h
     767    runtime/CachedTypes.h
    764768    runtime/CagedBarrierPtr.h
    765769    runtime/CallData.h
     
    897901    runtime/LazyClassStructure.h
    898902    runtime/LazyProperty.h
     903    runtime/LeafExecutable.h
    899904    runtime/Lookup.h
    900905    runtime/MatchResult.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r244138 r244143  
     12019-04-10  Tadeu Zagallo  <tzagallo@apple.com>
     2
     3        Add support for incremental bytecode cache updates
     4        https://bugs.webkit.org/show_bug.cgi?id=195000
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Add support for incremental updates to the bytecode cache. The cache
     9        is constructed as follows:
     10        - When the cache is empty, the initial payload can be added to the BytecodeCache
     11        by calling BytecodeCache::addGlobalUpdate. This represents the encoded
     12        top-level UnlinkedCodeBlock.
     13        - Afterwards, updates can be added by calling BytecodeCache::addFunctionUpdate.
     14        The update is applied by appending the encoded UnlinkedFunctionCodeBlock
     15        to the existing cache and updating the CachedFunctionExecutableMetadata
     16        and the offset of the new CachedFunctionCodeBlock in the owner CachedFunctionExecutable.
     17
     18        * API/JSScript.mm:
     19        (-[JSScript readCache]):
     20        (-[JSScript isUsingBytecodeCache]):
     21        (-[JSScript init]):
     22        (-[JSScript cachedBytecode]):
     23        (-[JSScript writeCache:]):
     24        * API/JSScriptInternal.h:
     25        * API/JSScriptSourceProvider.h:
     26        * API/JSScriptSourceProvider.mm:
     27        (JSScriptSourceProvider::cachedBytecode const):
     28        * CMakeLists.txt:
     29        * JavaScriptCore.xcodeproj/project.pbxproj:
     30        * Sources.txt:
     31        * bytecode/UnlinkedFunctionExecutable.cpp:
     32        (JSC::generateUnlinkedFunctionCodeBlock):
     33        * jsc.cpp:
     34        (ShellSourceProvider::~ShellSourceProvider):
     35        (ShellSourceProvider::cachePath const):
     36        (ShellSourceProvider::loadBytecode const):
     37        (ShellSourceProvider::ShellSourceProvider):
     38        (ShellSourceProvider::cacheEnabled):
     39        * parser/SourceProvider.h:
     40        (JSC::SourceProvider::cachedBytecode const):
     41        (JSC::SourceProvider::updateCache const):
     42        (JSC::SourceProvider::commitCachedBytecode const):
     43        * runtime/CachePayload.cpp: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.
     44        (JSC::CachePayload::makeMappedPayload):
     45        (JSC::CachePayload::makeMallocPayload):
     46        (JSC::CachePayload::makeEmptyPayload):
     47        (JSC::CachePayload::CachePayload):
     48        (JSC::CachePayload::~CachePayload):
     49        (JSC::CachePayload::operator=):
     50        (JSC::CachePayload::freeData):
     51        * runtime/CachePayload.h: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.
     52        (JSC::CachePayload::data const):
     53        (JSC::CachePayload::size const):
     54        (JSC::CachePayload::CachePayload):
     55        * runtime/CacheUpdate.cpp: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.
     56        (JSC::CacheUpdate::CacheUpdate):
     57        (JSC::CacheUpdate::operator=):
     58        (JSC::CacheUpdate::isGlobal const):
     59        (JSC::CacheUpdate::asGlobal const):
     60        (JSC::CacheUpdate::asFunction const):
     61        * runtime/CacheUpdate.h: Copied from Source/JavaScriptCore/API/JSScriptInternal.h.
     62        * runtime/CachedBytecode.cpp: Added.
     63        (JSC::CachedBytecode::addGlobalUpdate):
     64        (JSC::CachedBytecode::addFunctionUpdate):
     65        (JSC::CachedBytecode::copyLeafExecutables):
     66        (JSC::CachedBytecode::commitUpdates const):
     67        * runtime/CachedBytecode.h: Added.
     68        (JSC::CachedBytecode::create):
     69        (JSC::CachedBytecode::leafExecutables):
     70        (JSC::CachedBytecode::data const):
     71        (JSC::CachedBytecode::size const):
     72        (JSC::CachedBytecode::hasUpdates const):
     73        (JSC::CachedBytecode::sizeForUpdate const):
     74        (JSC::CachedBytecode::CachedBytecode):
     75        * runtime/CachedTypes.cpp:
     76        (JSC::Encoder::addLeafExecutable):
     77        (JSC::Encoder::release):
     78        (JSC::Decoder::Decoder):
     79        (JSC::Decoder::create):
     80        (JSC::Decoder::size const):
     81        (JSC::Decoder::offsetOf):
     82        (JSC::Decoder::ptrForOffsetFromBase):
     83        (JSC::Decoder::addLeafExecutable):
     84        (JSC::VariableLengthObject::VariableLengthObject):
     85        (JSC::VariableLengthObject::buffer const):
     86        (JSC::CachedPtrOffsets::offsetOffset):
     87        (JSC::CachedWriteBarrierOffsets::ptrOffset):
     88        (JSC::CachedFunctionExecutable::features const):
     89        (JSC::CachedFunctionExecutable::hasCapturedVariables const):
     90        (JSC::CachedFunctionExecutableOffsets::codeBlockForCallOffset):
     91        (JSC::CachedFunctionExecutableOffsets::codeBlockForConstructOffset):
     92        (JSC::CachedFunctionExecutableOffsets::metadataOffset):
     93        (JSC::CachedFunctionExecutable::encode):
     94        (JSC::CachedFunctionExecutable::decode const):
     95        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
     96        (JSC::encodeCodeBlock):
     97        (JSC::encodeFunctionCodeBlock):
     98        (JSC::decodeCodeBlockImpl):
     99        (JSC::isCachedBytecodeStillValid):
     100        * runtime/CachedTypes.h:
     101        (JSC::VariableLengthObjectBase::VariableLengthObjectBase):
     102        (JSC::decodeCodeBlock):
     103        * runtime/CodeCache.cpp:
     104        (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
     105        (JSC::CodeCache::updateCache):
     106        (JSC::CodeCache::write):
     107        (JSC::writeCodeBlock):
     108        (JSC::serializeBytecode):
     109        * runtime/CodeCache.h:
     110        (JSC::SourceCodeValue::SourceCodeValue):
     111        (JSC::CodeCacheMap::findCacheAndUpdateAge):
     112        (JSC::CodeCacheMap::fetchFromDiskImpl):
     113        * runtime/Completion.cpp:
     114        (JSC::generateProgramBytecode):
     115        (JSC::generateModuleBytecode):
     116        * runtime/Completion.h:
     117        * runtime/LeafExecutable.cpp: Copied from Source/JavaScriptCore/API/JSScriptSourceProvider.mm.
     118        (JSC::LeafExecutable::operator+ const):
     119        * runtime/LeafExecutable.h: Copied from Source/JavaScriptCore/API/JSScriptSourceProvider.mm.
     120        (JSC::LeafExecutable::LeafExecutable):
     121        (JSC::LeafExecutable::base const):
     122
    11232019-04-10  Michael Catanzaro  <mcatanzaro@igalia.com>
    2124
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r243925 r244143  
    751751                0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */; };
    752752                0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */; };
     753                1409ECBF225E177400BEDD54 /* LeafExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = 148B1417225DD1D700D6E998 /* LeafExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
     754                1409ECC0225E178100BEDD54 /* CacheUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 148B1418225DD1D700D6E998 /* CacheUpdate.h */; settings = {ATTRIBUTES = (Private, ); }; };
     755                1409ECC1225E178C00BEDD54 /* CachePayload.h in Headers */ = {isa = PBXBuildFile; fileRef = 148B1416225DD1D700D6E998 /* CachePayload.h */; settings = {ATTRIBUTES = (Private, ); }; };
    753756                140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
    754757                141211310A48794D00480255 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
     
    784787                1442566215EDE98D0066A49B /* JSWithScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1442566015EDE98D0066A49B /* JSWithScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
    785788                144836E7132DA7BE005BE785 /* ConservativeRoots.h in Headers */ = {isa = PBXBuildFile; fileRef = 149DAAF212EB559D0083B12B /* ConservativeRoots.h */; settings = {ATTRIBUTES = (Private, ); }; };
     789                144CA3502224180100817789 /* CachedBytecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 144CA34F221F037900817789 /* CachedBytecode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    786790                145722861437E140005FDE26 /* StrongInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 145722851437E140005FDE26 /* StrongInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    787791                146C384B2177ACDF0079F6D9 /* UnlinkedMetadataTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 142D52BE21762958002DB086 /* UnlinkedMetadataTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    832836                14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9C14EE1ACC00D6D5D4 /* WeakSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    833837                14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
     838                14F09C2A2231923100CF88EB /* CachedTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 143BE26521C857770020CD17 /* CachedTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
    834839                14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F7256414EE265E00B1652B /* WeakHandleOwner.h */; settings = {ATTRIBUTES = (Private, ); }; };
    835840                14F79F70216EAFD200046D39 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    31893194                1442565F15EDE98D0066A49B /* JSWithScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWithScope.cpp; sourceTree = "<group>"; };
    31903195                1442566015EDE98D0066A49B /* JSWithScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWithScope.h; sourceTree = "<group>"; };
     3196                144CA34F221F037900817789 /* CachedBytecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedBytecode.h; sourceTree = "<group>"; };
    31913197                145722851437E140005FDE26 /* StrongInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StrongInlines.h; sourceTree = "<group>"; };
    31923198                145C507F0D9DF63B0088F6B9 /* CallData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallData.h; sourceTree = "<group>"; };
     
    32283234                148A7BED1B82975A002D9157 /* InlineCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineCallFrame.cpp; sourceTree = "<group>"; };
    32293235                148A7BEE1B82975A002D9157 /* InlineCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineCallFrame.h; sourceTree = "<group>"; };
     3236                148B1416225DD1D700D6E998 /* CachePayload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachePayload.h; sourceTree = "<group>"; };
     3237                148B1417225DD1D700D6E998 /* LeafExecutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LeafExecutable.h; sourceTree = "<group>"; };
     3238                148B1418225DD1D700D6E998 /* CacheUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheUpdate.h; sourceTree = "<group>"; };
     3239                148B1419225DD1E900D6E998 /* CachedBytecode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CachedBytecode.cpp; sourceTree = "<group>"; };
     3240                148B141A225DD1E900D6E998 /* CacheUpdate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CacheUpdate.cpp; sourceTree = "<group>"; };
     3241                148B141B225DD1EA00D6E998 /* CachePayload.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CachePayload.cpp; sourceTree = "<group>"; };
     3242                148B141C225DD1EA00D6E998 /* LeafExecutable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LeafExecutable.cpp; sourceTree = "<group>"; };
    32303243                148CD1D7108CF902008163C6 /* JSContextRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSContextRefPrivate.h; sourceTree = "<group>"; };
    32313244                149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerCallFrame.cpp; sourceTree = "<group>"; };
     
    67116724                                0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
    67126725                                0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
     6726                                148B1419225DD1E900D6E998 /* CachedBytecode.cpp */,
     6727                                144CA34F221F037900817789 /* CachedBytecode.h */,
    67136728                                14DAFA4521E3B871004B68F7 /* CachedTypes.cpp */,
    67146729                                143BE26521C857770020CD17 /* CachedTypes.h */,
     6730                                148B141B225DD1EA00D6E998 /* CachePayload.cpp */,
     6731                                148B1416225DD1D700D6E998 /* CachePayload.h */,
     6732                                148B141A225DD1E900D6E998 /* CacheUpdate.cpp */,
     6733                                148B1418225DD1D700D6E998 /* CacheUpdate.h */,
    67156734                                0FEC3C5F1F379F5300F59B6C /* CagedBarrierPtr.h */,
    67166735                                BCA62DFE0E2826230004F30D /* CallData.cpp */,
     
    70817100                                DCF3D5671CD29468003D5C65 /* LazyProperty.h */,
    70827101                                DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */,
     7102                                148B141C225DD1EA00D6E998 /* LeafExecutable.cpp */,
     7103                                148B1417225DD1D700D6E998 /* LeafExecutable.h */,
    70837104                                A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */,
    70847105                                A7E2EA690FB460CF00601F06 /* LiteralParser.h */,
     
    87298750                                0F885E111849A3BE00F1E3FA /* BytecodeUseDef.h in Headers */,
    87308751                                0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */,
     8752                                144CA3502224180100817789 /* CachedBytecode.h in Headers */,
    87318753                                65B8392E1BACAD360044E824 /* CachedRecovery.h in Headers */,
     8754                                14F09C2A2231923100CF88EB /* CachedTypes.h in Headers */,
     8755                                1409ECC1225E178C00BEDD54 /* CachePayload.h in Headers */,
     8756                                1409ECC0225E178100BEDD54 /* CacheUpdate.h in Headers */,
    87328757                                0FEC3C601F379F5300F59B6C /* CagedBarrierPtr.h in Headers */,
    87338758                                BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */,
     
    95149539                                DCF3D56D1CD29476003D5C65 /* LazyPropertyInlines.h in Headers */,
    95159540                                99DA00B01BD5994E00F4575C /* lazywriter.py in Headers */,
     9541                                1409ECBF225E177400BEDD54 /* LeafExecutable.h in Headers */,
    95169542                                BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
    95179543                                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r243925 r244143  
    718718runtime/BooleanPrototype.cpp
    719719runtime/CallData.cpp
     720runtime/CachePayload.cpp
     721runtime/CacheUpdate.cpp
     722runtime/CachedBytecode.cpp
    720723runtime/CachedTypes.cpp
    721724runtime/CatchScope.cpp
     
    873876runtime/JSWrapperObject.cpp
    874877runtime/LazyClassStructure.cpp
     878runtime/LeafExecutable.cpp
    875879runtime/LiteralParser.cpp
    876880runtime/Lookup.cpp
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp

    r243875 r244143  
    7878    if (error.isValid())
    7979        return nullptr;
     80    vm.codeCache()->updateCache(executable, source, kind, result);
    8081    return result;
    8182}
  • trunk/Source/JavaScriptCore/jsc.cpp

    r243869 r244143  
    968968    ~ShellSourceProvider()
    969969    {
     970        commitCachedBytecode();
     971    }
     972
     973    RefPtr<CachedBytecode> cachedBytecode() const override
     974    {
     975        if (!m_cachedBytecode->size())
     976            loadBytecode();
     977        return m_cachedBytecode.copyRef();
     978    }
     979
     980    void updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock) const override
     981    {
     982        if (!cacheEnabled())
     983            return;
     984        Ref<CachedBytecode> cachedBytecode = encodeFunctionCodeBlock(*executable->vm(), codeBlock);
     985        m_cachedBytecode->addFunctionUpdate(executable, kind, WTFMove(cachedBytecode));
     986    }
     987
     988    void cacheBytecode(const BytecodeCacheGenerator& generator) const override
     989    {
     990        if (!cacheEnabled())
     991            return;
     992        m_cachedBytecode->addGlobalUpdate(generator());
     993    }
     994
     995    void commitCachedBytecode() const override
     996    {
    970997#if OS(DARWIN)
    971         if (m_cachedBytecode.size())
    972             munmap(const_cast<void*>(m_cachedBytecode.data()), m_cachedBytecode.size());
    973 #endif
    974     }
    975 
    976     const CachedBytecode* cachedBytecode() const override
    977     {
    978         return &m_cachedBytecode;
    979     }
    980 
    981     void cacheBytecode(const BytecodeCacheGenerator& generator) const override
    982     {
    983 #if OS(DARWIN)
     998        if (!cacheEnabled() || !m_cachedBytecode->hasUpdates())
     999            return;
     1000
     1001        auto clearBytecode = makeScopeExit([&] {
     1002            m_cachedBytecode = CachedBytecode::create();
     1003        });
     1004
    9841005        String filename = cachePath();
    985         if (filename.isNull())
    986             return;
    9871006        int fd = open(filename.utf8().data(), O_CREAT | O_WRONLY | O_TRUNC | O_EXLOCK | O_NONBLOCK, 0666);
    9881007        if (fd == -1)
    9891008            return;
    990         CachedBytecode cachedBytecode = generator();
    991         write(fd, cachedBytecode.data(), cachedBytecode.size());
    992         close(fd);
    993 #else
    994         UNUSED_PARAM(generator);
     1009
     1010        auto closeFD = makeScopeExit([&] {
     1011            close(fd);
     1012        });
     1013
     1014        struct stat sb;
     1015        int res = fstat(fd, &sb);
     1016        size_t size = static_cast<size_t>(sb.st_size);
     1017        if (res || size != m_cachedBytecode->size()) {
     1018            // The bytecode cache has already been updated
     1019            return;
     1020        }
     1021
     1022        if (ftruncate(fd, m_cachedBytecode->sizeForUpdate()))
     1023            return;
     1024
     1025        m_cachedBytecode->commitUpdates([&] (off_t offset, const void* data, size_t size) {
     1026            int result = lseek(fd, offset, SEEK_SET);
     1027            ASSERT_UNUSED(result, result != -1);
     1028            size_t bytesWritten = static_cast<size_t>(write(fd, data, size));
     1029            ASSERT_UNUSED(bytesWritten, bytesWritten == size);
     1030        });
    9951031#endif
    9961032    }
     
    9991035    String cachePath() const
    10001036    {
     1037        if (!cacheEnabled())
     1038            return static_cast<const char*>(nullptr);
    10011039        const char* cachePath = Options::diskCachePath();
    1002         if (!cachePath)
    1003             return static_cast<const char*>(nullptr);
    10041040        String filename = sourceOrigin().string();
    10051041        filename.replace('/', '_');
     
    10071043    }
    10081044
    1009     void loadBytecode()
     1045    void loadBytecode() const
    10101046    {
    10111047#if OS(DARWIN)
     1048        if (!cacheEnabled())
     1049            return;
     1050
    10121051        String filename = cachePath();
    10131052        if (filename.isNull())
     
    10311070        if (buffer == MAP_FAILED)
    10321071            return;
    1033         m_cachedBytecode = CachedBytecode { buffer, size };
     1072        m_cachedBytecode = CachedBytecode::create(buffer, size);
    10341073#endif
    10351074    }
     
    10371076    ShellSourceProvider(const String& source, const SourceOrigin& sourceOrigin, URL&& url, const TextPosition& startPosition, SourceProviderSourceType sourceType)
    10381077        : StringSourceProvider(source, sourceOrigin, WTFMove(url), startPosition, sourceType)
     1078        , m_cachedBytecode(CachedBytecode::create())
    10391079    {
    10401080        loadBytecode();
    10411081    }
    10421082
    1043     CachedBytecode m_cachedBytecode;
     1083    static bool cacheEnabled()
     1084    {
     1085        static bool enabled = !!Options::diskCachePath();
     1086        return enabled;
     1087    }
     1088
     1089    mutable Ref<CachedBytecode> m_cachedBytecode;
    10441090};
    10451091
  • trunk/Source/JavaScriptCore/parser/SourceProvider.h

    r241758 r244143  
    2929#pragma once
    3030
     31#include "CachedBytecode.h"
     32#include "CodeSpecializationKind.h"
    3133#include "SourceOrigin.h"
    3234#include <wtf/RefCounted.h>
     
    3739namespace JSC {
    3840
     41class SourceCode;
     42class UnlinkedFunctionExecutable;
     43class UnlinkedFunctionCodeBlock;
     44
    3945    enum class SourceProviderSourceType : uint8_t {
    4046        Program,
     
    4349    };
    4450
    45     class CachedBytecode {
    46         WTF_MAKE_NONCOPYABLE(CachedBytecode);
    47 
    48     public:
    49         CachedBytecode()
    50             : CachedBytecode(nullptr, 0)
    51         {
    52         }
    53 
    54         CachedBytecode(const void* data, size_t size)
    55             : m_owned(false)
    56             , m_size(size)
    57             , m_data(data)
    58         {
    59         }
    60 
    61         CachedBytecode(MallocPtr<uint8_t>&& data, size_t size)
    62             : m_owned(true)
    63             , m_size(size)
    64             , m_data(data.leakPtr())
    65         {
    66         }
    67 
    68         CachedBytecode(CachedBytecode&& other)
    69         {
    70             m_owned = other.m_owned;
    71             m_size = other.m_size;
    72             m_data = other.m_data;
    73             other.m_owned = false;
    74         }
    75 
    76         CachedBytecode& operator=(CachedBytecode&& other)
    77         {
    78             freeDataIfOwned();
    79             m_owned = other.m_owned;
    80             m_size = other.m_size;
    81             m_data = other.m_data;
    82             other.m_owned = false;
    83             return *this;
    84         }
    85 
    86         const void* data() const { return m_data; }
    87         size_t size() const { return m_size; }
    88         bool owned() const { return m_owned; }
    89 
    90         ~CachedBytecode()
    91         {
    92             freeDataIfOwned();
    93         }
    94 
    95     private:
    96         void freeDataIfOwned()
    97         {
    98             if (m_data && m_owned)
    99                 fastFree(const_cast<void*>(m_data));
    100         }
    101 
    102         bool m_owned;
    103         size_t m_size;
    104         const void* m_data;
    105     };
    106 
    107     using BytecodeCacheGenerator = Function<CachedBytecode()>;
     51    using BytecodeCacheGenerator = Function<Ref<CachedBytecode>()>;
    10852
    10953    class SourceProvider : public RefCounted<SourceProvider> {
     
    11761        virtual unsigned hash() const = 0;
    11862        virtual StringView source() const = 0;
    119         virtual const CachedBytecode* cachedBytecode() const { return nullptr; }
     63        virtual RefPtr<CachedBytecode> cachedBytecode() const { return nullptr; }
    12064        virtual void cacheBytecode(const BytecodeCacheGenerator&) const { }
     65        virtual void updateCache(const UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, const UnlinkedFunctionCodeBlock*) const { }
     66        virtual void commitCachedBytecode() const { }
    12167
    12268        StringView getRange(int start, int end) const
  • trunk/Source/JavaScriptCore/runtime/CachePayload.cpp

    r244142 r244143  
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "CachePayload.h"
    2728
    28 #import "JSScript.h"
    29 #import "SourceCode.h"
    30 
    31 #if JSC_OBJC_API_ENABLED
    32 
    33 NS_ASSUME_NONNULL_BEGIN
     29#if !OS(WINDOWS)
     30#include <sys/mman.h>
     31#endif
    3432
    3533namespace JSC {
    36 class CachedBytecode;
    37 class Identifier;
    38 class JSSourceCode;
    39 };
    4034
    41 namespace WTF {
    42 class String;
    43 };
     35#if !OS(WINDOWS)
     36CachePayload CachePayload::makeMappedPayload(void* data, size_t size)
     37{
     38    return CachePayload(true, data, size);
     39}
     40#endif
    4441
    45 @interface JSScript(Internal)
     42CachePayload CachePayload::makeMallocPayload(MallocPtr<uint8_t>&& data, size_t size)
     43{
     44    return CachePayload(false, data.leakPtr(), size);
     45}
    4646
    47 - (instancetype)init;
    48 - (unsigned)hash;
    49 - (const WTF::String&)source;
    50 - (nullable const JSC::CachedBytecode*)cachedBytecode;
    51 - (JSC::JSSourceCode*)jsSourceCode;
    52 - (JSC::SourceCode)sourceCode;
    53 - (BOOL)writeCache:(String&)error;
    54 // FIXME: Remove this once we require sourceURL upon creation: https://bugs.webkit.org/show_bug.cgi?id=194909
    55 - (void)setSourceURL:(NSURL *)url;
     47CachePayload CachePayload::makeEmptyPayload()
     48{
     49    return CachePayload(true, nullptr, 0);
     50}
    5651
    57 @end
     52CachePayload::CachePayload(CachePayload&& other)
     53{
     54    m_mapped = other.m_mapped;
     55    m_size = other.m_size;
     56    m_data = other.m_data;
     57    other.m_mapped = false;
     58    other.m_data = nullptr;
     59    other.m_size = 0;
     60}
    5861
    59 NS_ASSUME_NONNULL_END
     62CachePayload::~CachePayload()
     63{
     64    freeData();
     65}
    6066
    61 #endif // JSC_OBJC_API_ENABLED
     67CachePayload& CachePayload::operator=(CachePayload&& other)
     68{
     69    ASSERT(&other != this);
     70    freeData();
     71    return *new (this) CachePayload(WTFMove(other));
     72}
     73
     74void CachePayload::freeData()
     75{
     76    if (!m_data)
     77        return;
     78    if (m_mapped) {
     79#if !OS(WINDOWS)
     80        munmap(m_data, m_size);
     81#else
     82        RELEASE_ASSERT_NOT_REACHED();
     83#endif
     84    } else
     85        fastFree(m_data);
     86}
     87
     88} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CachePayload.h

    r244142 r244143  
    2626#pragma once
    2727
    28 #import "JSScript.h"
    29 #import "SourceCode.h"
    30 
    31 #if JSC_OBJC_API_ENABLED
    32 
    33 NS_ASSUME_NONNULL_BEGIN
     28#include <wtf/MallocPtr.h>
    3429
    3530namespace JSC {
    36 class CachedBytecode;
    37 class Identifier;
    38 class JSSourceCode;
     31
     32class CachePayload {
     33public:
     34#if !OS(WINDOWS)
     35    JS_EXPORT_PRIVATE static CachePayload makeMappedPayload(void*, size_t);
     36#endif
     37    JS_EXPORT_PRIVATE static CachePayload makeMallocPayload(MallocPtr<uint8_t>&&, size_t);
     38    JS_EXPORT_PRIVATE static CachePayload makeEmptyPayload();
     39
     40    JS_EXPORT_PRIVATE CachePayload(CachePayload&&);
     41    JS_EXPORT_PRIVATE ~CachePayload();
     42    JS_EXPORT_PRIVATE CachePayload& operator=(CachePayload&& other);
     43
     44    const uint8_t* data() const { return m_data; }
     45    size_t size() const { return m_size; }
     46
     47private:
     48    CachePayload(bool mapped, void* data, size_t size)
     49        : m_mapped(mapped)
     50        , m_size(size)
     51        , m_data(static_cast<uint8_t*>(data))
     52    {
     53    }
     54
     55    void freeData();
     56
     57    bool m_mapped;
     58    size_t m_size;
     59    uint8_t* m_data;
    3960};
    4061
    41 namespace WTF {
    42 class String;
    43 };
    44 
    45 @interface JSScript(Internal)
    46 
    47 - (instancetype)init;
    48 - (unsigned)hash;
    49 - (const WTF::String&)source;
    50 - (nullable const JSC::CachedBytecode*)cachedBytecode;
    51 - (JSC::JSSourceCode*)jsSourceCode;
    52 - (JSC::SourceCode)sourceCode;
    53 - (BOOL)writeCache:(String&)error;
    54 // FIXME: Remove this once we require sourceURL upon creation: https://bugs.webkit.org/show_bug.cgi?id=194909
    55 - (void)setSourceURL:(NSURL *)url;
    56 
    57 @end
    58 
    59 NS_ASSUME_NONNULL_END
    60 
    61 #endif // JSC_OBJC_API_ENABLED
     62} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CacheUpdate.cpp

    r244142 r244143  
    2424 */
    2525
    26 #pragma once
    27 
    28 #import "JSScript.h"
    29 #import "SourceCode.h"
    30 
    31 #if JSC_OBJC_API_ENABLED
    32 
    33 NS_ASSUME_NONNULL_BEGIN
     26#include "config.h"
     27#include "CacheUpdate.h"
    3428
    3529namespace JSC {
    36 class CachedBytecode;
    37 class Identifier;
    38 class JSSourceCode;
    39 };
    4030
    41 namespace WTF {
    42 class String;
    43 };
     31CacheUpdate::CacheUpdate(GlobalUpdate&& update)
     32    : m_update(WTFMove(update))
     33{
     34}
    4435
    45 @interface JSScript(Internal)
     36CacheUpdate::CacheUpdate(FunctionUpdate&& update)
     37    : m_update(WTFMove(update))
     38{
     39}
    4640
    47 - (instancetype)init;
    48 - (unsigned)hash;
    49 - (const WTF::String&)source;
    50 - (nullable const JSC::CachedBytecode*)cachedBytecode;
    51 - (JSC::JSSourceCode*)jsSourceCode;
    52 - (JSC::SourceCode)sourceCode;
    53 - (BOOL)writeCache:(String&)error;
    54 // FIXME: Remove this once we require sourceURL upon creation: https://bugs.webkit.org/show_bug.cgi?id=194909
    55 - (void)setSourceURL:(NSURL *)url;
     41CacheUpdate::CacheUpdate(CacheUpdate&& other)
     42{
     43    if (WTF::holds_alternative<GlobalUpdate>(other.m_update))
     44        new (this) CacheUpdate(WTFMove(WTF::get<GlobalUpdate>(other.m_update)));
     45    else
     46        new (this) CacheUpdate(WTFMove(WTF::get<FunctionUpdate>(other.m_update)));
     47}
    5648
    57 @end
     49CacheUpdate& CacheUpdate::operator=(CacheUpdate&& other)
     50{
     51    this->~CacheUpdate();
     52    return *new (this) CacheUpdate(WTFMove(other));
     53}
    5854
    59 NS_ASSUME_NONNULL_END
     55bool CacheUpdate::isGlobal() const
     56{
     57    return WTF::holds_alternative<GlobalUpdate>(m_update);
     58}
    6059
    61 #endif // JSC_OBJC_API_ENABLED
     60const CacheUpdate::GlobalUpdate& CacheUpdate::asGlobal() const
     61{
     62    ASSERT(isGlobal());
     63    return WTF::get<GlobalUpdate>(m_update);
     64}
     65
     66const CacheUpdate::FunctionUpdate& CacheUpdate::asFunction() const
     67{
     68    ASSERT(!isGlobal());
     69    return WTF::get<FunctionUpdate>(m_update);
     70}
     71
     72} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CacheUpdate.h

    r244142 r244143  
    2626#pragma once
    2727
    28 #import "JSScript.h"
    29 #import "SourceCode.h"
    30 
    31 #if JSC_OBJC_API_ENABLED
    32 
    33 NS_ASSUME_NONNULL_BEGIN
     28#include "CachePayload.h"
     29#include "CachedTypes.h"
     30#include "CodeSpecializationKind.h"
     31#include <wtf/Variant.h>
    3432
    3533namespace JSC {
    36 class CachedBytecode;
    37 class Identifier;
    38 class JSSourceCode;
     34
     35class CacheUpdate {
     36public:
     37    struct GlobalUpdate {
     38        CachePayload m_payload;
     39    };
     40
     41    struct FunctionUpdate {
     42        ptrdiff_t m_base;
     43        CodeSpecializationKind m_kind;
     44        CachedFunctionExecutableMetadata m_metadata;
     45        CachePayload m_payload;
     46    };
     47
     48
     49    CacheUpdate(GlobalUpdate&&);
     50    CacheUpdate(FunctionUpdate&&);
     51
     52    CacheUpdate(CacheUpdate&&);
     53    CacheUpdate& operator=(CacheUpdate&&);
     54
     55    bool isGlobal() const;
     56    const GlobalUpdate& asGlobal() const;
     57    const FunctionUpdate& asFunction() const;
     58
     59private:
     60    Variant<GlobalUpdate, FunctionUpdate> m_update;
    3961};
    4062
    41 namespace WTF {
    42 class String;
    43 };
    44 
    45 @interface JSScript(Internal)
    46 
    47 - (instancetype)init;
    48 - (unsigned)hash;
    49 - (const WTF::String&)source;
    50 - (nullable const JSC::CachedBytecode*)cachedBytecode;
    51 - (JSC::JSSourceCode*)jsSourceCode;
    52 - (JSC::SourceCode)sourceCode;
    53 - (BOOL)writeCache:(String&)error;
    54 // FIXME: Remove this once we require sourceURL upon creation: https://bugs.webkit.org/show_bug.cgi?id=194909
    55 - (void)setSourceURL:(NSURL *)url;
    56 
    57 @end
    58 
    59 NS_ASSUME_NONNULL_END
    60 
    61 #endif // JSC_OBJC_API_ENABLED
     63} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp

    r244088 r244143  
    140140    }
    141141
    142     std::pair<MallocPtr<uint8_t>, size_t> release()
     142    void addLeafExecutable(const UnlinkedFunctionExecutable* executable, ptrdiff_t offset)
     143    {
     144        m_leafExecutables.add(executable, offset);
     145    }
     146
     147    Ref<CachedBytecode> release()
    143148    {
    144149        size_t size = m_baseOffset + m_currentPage->size();
     
    150155        }
    151156        RELEASE_ASSERT(offset == size);
    152         return { WTFMove(buffer), size };
     157        return CachedBytecode::create(WTFMove(buffer), size, WTFMove(m_leafExecutables));
    153158    }
    154159
     
    213218    Vector<Page> m_pages;
    214219    HashMap<const void*, ptrdiff_t> m_ptrToOffsetMap;
    215 };
    216 
    217 Decoder::Decoder(VM& vm, const void* baseAddress, size_t size)
     220    LeafExecutableMap m_leafExecutables;
     221};
     222
     223Decoder::Decoder(VM& vm, Ref<CachedBytecode> cachedBytecode)
    218224    : m_vm(vm)
    219     , m_baseAddress(reinterpret_cast<const uint8_t*>(baseAddress))
    220 #ifndef NDEBUG
    221     , m_size(size)
    222 #endif
    223 {
    224     UNUSED_PARAM(size);
     225    , m_cachedBytecode(WTFMove(cachedBytecode))
     226{
    225227}
    226228
     
    231233}
    232234
    233 Ref<Decoder> Decoder::create(VM& vm, const void* baseAddress, size_t size)
    234 {
    235     return adoptRef(*new Decoder(vm, baseAddress, size));
     235Ref<Decoder> Decoder::create(VM& vm, Ref<CachedBytecode> cachedBytecode)
     236{
     237    return adoptRef(*new Decoder(vm, WTFMove(cachedBytecode)));
     238}
     239
     240size_t Decoder::size() const
     241{
     242    return m_cachedBytecode->size();
    236243}
    237244
     
    239246{
    240247    const uint8_t* addr = static_cast<const uint8_t*>(ptr);
    241     ASSERT(addr >= m_baseAddress && addr < m_baseAddress + m_size);
    242     return addr - m_baseAddress;
     248    ASSERT(addr >= m_cachedBytecode->data() && addr < m_cachedBytecode->data() + m_cachedBytecode->size());
     249    return addr - m_cachedBytecode->data();
    243250}
    244251
     
    259266{
    260267#ifndef NDEBUG
    261     ASSERT(offset > 0 && static_cast<size_t>(offset) < m_size);
     268    ASSERT(offset > 0 && static_cast<size_t>(offset) < m_cachedBytecode->size());
    262269#endif
    263     return m_baseAddress + offset;
     270    return m_cachedBytecode->data() + offset;
    264271}
    265272
     
    275282    auto addResult = m_environmentToHandleMap.add(environment, handle);
    276283    ASSERT_UNUSED(addResult, addResult.isNewEntry);
     284}
     285
     286void Decoder::addLeafExecutable(const UnlinkedFunctionExecutable* executable, ptrdiff_t offset)
     287{
     288    m_cachedBytecode->leafExecutables().add(executable, offset);
    277289}
    278290
     
    340352
    341353template<typename Source>
    342 class VariableLengthObject : public CachedObject<Source> {
     354class VariableLengthObject : public CachedObject<Source>, VariableLengthObjectBase {
    343355    template<typename, typename>
    344     friend struct CachedPtr;
    345 
    346 public:
     356    friend class CachedPtr;
     357    friend struct CachedPtrOffsets;
     358
     359public:
     360    VariableLengthObject()
     361        : VariableLengthObjectBase(s_invalidOffset)
     362    {
     363    }
     364
    347365    bool isEmpty() const
    348366    {
     
    353371    const uint8_t* buffer() const
    354372    {
    355         ASSERT(m_offset != s_invalidOffset);
     373        ASSERT(!isEmpty());
    356374        return bitwise_cast<const uint8_t*>(this) + m_offset;
    357375    }
     
    380398private:
    381399    constexpr static ptrdiff_t s_invalidOffset = std::numeric_limits<ptrdiff_t>::max();
    382 
    383     ptrdiff_t m_offset { s_invalidOffset };
    384 
    385400};
    386401
     
    388403class CachedPtr : public VariableLengthObject<Source*> {
    389404    template<typename, typename>
    390     friend struct CachedRefPtr;
     405    friend class CachedRefPtr;
     406
     407    friend struct CachedPtrOffsets;
    391408
    392409public:
     
    443460    }
    444461};
     462
     463ptrdiff_t CachedPtrOffsets::offsetOffset()
     464{
     465    return OBJECT_OFFSETOF(CachedPtr<void>, m_offset);
     466}
    445467
    446468template<typename T, typename Source = SourceType<T>>
     
    483505template<typename T, typename Source = SourceType<T>>
    484506class CachedWriteBarrier : public CachedObject<WriteBarrier<Source>> {
     507    friend struct CachedWriteBarrierOffsets;
     508
    485509public:
    486510    bool isEmpty() const { return m_ptr.isEmpty(); }
     
    501525    CachedPtr<T, Source> m_ptr;
    502526};
     527
     528ptrdiff_t CachedWriteBarrierOffsets::ptrOffset()
     529{
     530    return OBJECT_OFFSETOF(CachedWriteBarrier<void>, m_ptr);
     531}
    503532
    504533template<typename T, size_t InlineCapacity = 0, typename OverflowHandler = CrashOnOverflow>
     
    15371566
    15381567class CachedFunctionExecutable : public CachedObject<UnlinkedFunctionExecutable> {
     1568    friend struct CachedFunctionExecutableOffsets;
     1569
    15391570public:
    15401571    void encode(Encoder&, const UnlinkedFunctionExecutable&);
     
    15531584    unsigned parameterCount() const { return m_parameterCount; }
    15541585
    1555     CodeFeatures features() const { return m_features; }
     1586    CodeFeatures features() const { return m_mutableMetadata.m_features; }
    15561587    SourceParseMode sourceParseMode() const { return m_sourceParseMode; }
    15571588
    15581589    unsigned isInStrictContext() const { return m_isInStrictContext; }
    1559     unsigned hasCapturedVariables() const { return m_hasCapturedVariables; }
     1590    unsigned hasCapturedVariables() const { return m_mutableMetadata.m_hasCapturedVariables; }
    15601591    unsigned isBuiltinFunction() const { return m_isBuiltinFunction; }
    15611592    unsigned isBuiltinDefaultClassConstructor() const { return m_isBuiltinDefaultClassConstructor; }
     
    15771608
    15781609private:
     1610    CachedFunctionExecutableMetadata m_mutableMetadata;
     1611
    15791612    unsigned m_firstLineOffset;
    15801613    unsigned m_lineCount;
     
    15881621    unsigned m_typeProfilingEndOffset;
    15891622    unsigned m_parameterCount;
    1590     CodeFeatures m_features;
    15911623    SourceParseMode m_sourceParseMode;
    15921624    unsigned m_isInStrictContext : 1;
    1593     unsigned m_hasCapturedVariables : 1;
    15941625    unsigned m_isBuiltinFunction : 1;
    15951626    unsigned m_isBuiltinDefaultClassConstructor : 1;
     
    16101641    CachedWriteBarrier<CachedFunctionCodeBlock, UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
    16111642};
     1643
     1644ptrdiff_t CachedFunctionExecutableOffsets::codeBlockForCallOffset()
     1645{
     1646    return OBJECT_OFFSETOF(CachedFunctionExecutable, m_unlinkedCodeBlockForCall);
     1647}
     1648
     1649ptrdiff_t CachedFunctionExecutableOffsets::codeBlockForConstructOffset()
     1650{
     1651    return OBJECT_OFFSETOF(CachedFunctionExecutable, m_unlinkedCodeBlockForConstruct);
     1652}
     1653
     1654ptrdiff_t CachedFunctionExecutableOffsets::metadataOffset()
     1655{
     1656    return OBJECT_OFFSETOF(CachedFunctionExecutable, m_mutableMetadata);
     1657}
    16121658
    16131659template<typename CodeBlockType>
     
    19261972ALWAYS_INLINE void CachedFunctionExecutable::encode(Encoder& encoder, const UnlinkedFunctionExecutable& executable)
    19271973{
     1974    m_mutableMetadata.m_features = executable.m_features;
     1975    m_mutableMetadata.m_hasCapturedVariables = executable.m_hasCapturedVariables;
     1976
    19281977    m_firstLineOffset = executable.m_firstLineOffset;
    19291978    m_lineCount = executable.m_lineCount;
     
    19381987    m_parameterCount = executable.m_parameterCount;
    19391988
    1940     m_features = executable.m_features;
    19411989    m_sourceParseMode = executable.m_sourceParseMode;
    19421990
    19431991    m_isInStrictContext = executable.m_isInStrictContext;
    1944     m_hasCapturedVariables = executable.m_hasCapturedVariables;
    19451992    m_isBuiltinFunction = executable.m_isBuiltinFunction;
    19461993    m_isBuiltinDefaultClassConstructor = executable.m_isBuiltinDefaultClassConstructor;
     
    19602007    m_unlinkedCodeBlockForCall.encode(encoder, executable.m_unlinkedCodeBlockForCall);
    19612008    m_unlinkedCodeBlockForConstruct.encode(encoder, executable.m_unlinkedCodeBlockForConstruct);
     2009
     2010    if (!executable.m_unlinkedCodeBlockForCall || !executable.m_unlinkedCodeBlockForConstruct)
     2011        encoder.addLeafExecutable(&executable, encoder.offsetOf(this));
    19622012}
    19632013
     
    19662016    UnlinkedFunctionExecutable* executable = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(decoder.vm().heap)) UnlinkedFunctionExecutable(decoder, *this);
    19672017    executable->finishCreation(decoder.vm());
    1968 
    19692018    return executable;
    19702019}
     
    20062055{
    20072056
     2057    uint32_t leafExecutables = 2;
     2058    auto checkBounds = [&](int32_t& codeBlockOffset, auto& cachedPtr) {
     2059        if (!cachedPtr.isEmpty()) {
     2060            ptrdiff_t offset = decoder.offsetOf(&cachedPtr);
     2061            if (static_cast<size_t>(offset) < decoder.size()) {
     2062                codeBlockOffset = offset;
     2063                m_isCached = true;
     2064                leafExecutables--;
     2065            }
     2066        }
     2067    };
     2068
    20082069    if (!cachedExecutable.unlinkedCodeBlockForCall().isEmpty() || !cachedExecutable.unlinkedCodeBlockForConstruct().isEmpty()) {
    2009         m_isCached = true;
    2010         m_decoder = &decoder;
    2011         if (!cachedExecutable.unlinkedCodeBlockForCall().isEmpty())
    2012             m_cachedCodeBlockForCallOffset = decoder.offsetOf(&cachedExecutable.unlinkedCodeBlockForCall());
    2013         else
    2014             m_cachedCodeBlockForCallOffset = 0;
    2015         if (!cachedExecutable.unlinkedCodeBlockForConstruct().isEmpty())
    2016             m_cachedCodeBlockForConstructOffset = decoder.offsetOf(&cachedExecutable.unlinkedCodeBlockForConstruct());
    2017         else
    2018             m_cachedCodeBlockForConstructOffset = 0;
    2019     }
     2070        checkBounds(m_cachedCodeBlockForCallOffset, cachedExecutable.unlinkedCodeBlockForCall());
     2071        checkBounds(m_cachedCodeBlockForConstructOffset, cachedExecutable.unlinkedCodeBlockForConstruct());
     2072        if (m_isCached)
     2073            m_decoder = &decoder;
     2074    }
     2075
     2076    if (leafExecutables)
     2077        decoder.addLeafExecutable(this, decoder.offsetOf(&cachedExecutable));
    20202078}
    20212079
     
    22102268}
    22112269
    2212 std::pair<MallocPtr<uint8_t>, size_t> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
     2270Ref<CachedBytecode> encodeCodeBlock(VM& vm, const SourceCodeKey& key, const UnlinkedCodeBlock* codeBlock)
    22132271{
    22142272    const ClassInfo* classInfo = codeBlock->classInfo(vm);
     
    22252283}
    22262284
    2227 UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size)
    2228 {
    2229     const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(buffer);
    2230     Ref<Decoder> decoder = Decoder::create(vm, buffer, size);
     2285Ref<CachedBytecode> encodeFunctionCodeBlock(VM& vm, const UnlinkedFunctionCodeBlock* codeBlock)
     2286{
     2287    Encoder encoder(vm);
     2288    encoder.malloc<CachedFunctionCodeBlock>()->encode(encoder, *codeBlock);
     2289    return encoder.release();
     2290}
     2291
     2292UnlinkedCodeBlock* decodeCodeBlockImpl(VM& vm, const SourceCodeKey& key, Ref<CachedBytecode> cachedBytecode)
     2293{
     2294    const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(cachedBytecode->data());
     2295    Ref<Decoder> decoder = Decoder::create(vm, WTFMove(cachedBytecode));
    22312296    std::pair<SourceCodeKey, UnlinkedCodeBlock*> entry;
    22322297    {
     
    22412306}
    22422307
    2243 bool isCachedBytecodeStillValid(VM& vm, const CachedBytecode& cachedBytecode, const SourceCodeKey& key, SourceCodeType type)
    2244 {
    2245     const void* buffer = cachedBytecode.data();
    2246     size_t size = cachedBytecode.size();
     2308bool isCachedBytecodeStillValid(VM& vm, Ref<CachedBytecode> cachedBytecode, const SourceCodeKey& key, SourceCodeType type)
     2309{
     2310    const void* buffer = cachedBytecode->data();
     2311    size_t size = cachedBytecode->size();
    22472312    if (!size)
    22482313        return false;
    22492314    const auto* cachedEntry = bitwise_cast<const GenericCacheEntry*>(buffer);
    2250     Ref<Decoder> decoder = Decoder::create(vm, buffer, size);
     2315    Ref<Decoder> decoder = Decoder::create(vm, WTFMove(cachedBytecode));
    22512316    return cachedEntry->isStillValid(decoder.get(), key, tagFromSourceCodeType(type));
    22522317}
  • trunk/Source/JavaScriptCore/runtime/CachedTypes.h

    r242605 r244143  
    2727
    2828#include "JSCast.h"
     29#include "ParserModes.h"
    2930#include "VariableEnvironment.h"
    3031#include <wtf/HashMap.h>
     
    3839class UnlinkedFunctionCodeBlock;
    3940
     41enum class SourceCodeType;
     42
     43// This struct has to be updated when incrementally writing to the bytecode
     44// cache, since this will only be filled in when we parse the function
     45struct CachedFunctionExecutableMetadata {
     46    CodeFeatures m_features;
     47    bool m_hasCapturedVariables;
     48};
     49
     50struct CachedFunctionExecutableOffsets {
     51    static ptrdiff_t codeBlockForCallOffset();
     52    static ptrdiff_t codeBlockForConstructOffset();
     53    static ptrdiff_t metadataOffset();
     54};
     55
     56struct CachedWriteBarrierOffsets {
     57    static ptrdiff_t ptrOffset();
     58};
     59
     60struct CachedPtrOffsets {
     61    static ptrdiff_t offsetOffset();
     62};
     63
     64class VariableLengthObjectBase {
     65    friend class CachedBytecode;
     66
     67protected:
     68    VariableLengthObjectBase(ptrdiff_t offset)
     69        : m_offset(offset)
     70    {
     71    }
     72
     73    ptrdiff_t m_offset;
     74};
     75
    4076class Decoder : public RefCounted<Decoder> {
    4177    WTF_MAKE_NONCOPYABLE(Decoder);
    4278
    4379public:
    44     static Ref<Decoder> create(VM&, const void*, size_t);
     80    static Ref<Decoder> create(VM&, Ref<CachedBytecode>);
    4581
    4682    ~Decoder();
    4783
    4884    VM& vm() { return m_vm; }
     85    size_t size() const;
    4986
    5087    ptrdiff_t offsetOf(const void*);
     
    5491    CompactVariableMap::Handle handleForEnvironment(CompactVariableEnvironment*) const;
    5592    void setHandleForEnvironment(CompactVariableEnvironment*, const CompactVariableMap::Handle&);
     93    void addLeafExecutable(const UnlinkedFunctionExecutable*, ptrdiff_t);
    5694
    5795    template<typename Functor>
     
    5997
    6098private:
    61     Decoder(VM&, const void*, size_t);
     99    Decoder(VM&, Ref<CachedBytecode>);
    62100
    63101    VM& m_vm;
    64     const uint8_t* m_baseAddress;
    65 #ifndef NDEBUG
    66     size_t m_size;
    67 #endif
     102    Ref<CachedBytecode> m_cachedBytecode;
    68103    HashMap<ptrdiff_t, void*> m_offsetToPtrMap;
    69104    Vector<std::function<void()>> m_finalizers;
     
    71106};
    72107
    73 enum class SourceCodeType;
     108JS_EXPORT_PRIVATE Ref<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*);
    74109
    75 std::pair<MallocPtr<uint8_t>, size_t> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*);
    76 
    77 UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, const void*, size_t);
    78 
    79 void decodeFunctionCodeBlock(Decoder&, int32_t cachedFunctionCodeBlockOffset, WriteBarrier<UnlinkedFunctionCodeBlock>&, const JSCell*);
     110UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, Ref<CachedBytecode>);
    80111
    81112template<typename UnlinkedCodeBlockType>
    82 UnlinkedCodeBlockType* decodeCodeBlock(VM& vm, const SourceCodeKey& key, const void* buffer, size_t size)
     113UnlinkedCodeBlockType* decodeCodeBlock(VM& vm, const SourceCodeKey& key, Ref<CachedBytecode> cachedBytecode)
    83114{
    84     return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, buffer, size));
     115    return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, WTFMove(cachedBytecode)));
    85116}
    86117
    87 bool isCachedBytecodeStillValid(VM&, const CachedBytecode&, const SourceCodeKey&, SourceCodeType);
     118JS_EXPORT_PRIVATE Ref<CachedBytecode> encodeFunctionCodeBlock(VM&, const UnlinkedFunctionCodeBlock*);
     119
     120JS_EXPORT_PRIVATE void decodeFunctionCodeBlock(Decoder&, int32_t cachedFunctionCodeBlockOffset, WriteBarrier<UnlinkedFunctionCodeBlock>&, const JSCell*);
     121
     122bool isCachedBytecodeStillValid(VM&, Ref<CachedBytecode>, const SourceCodeKey&, SourceCodeType);
    88123
    89124} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CodeCache.cpp

    r243875 r244143  
    8484        m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age()));
    8585
     86    key.source().provider().cacheBytecode([&] {
     87        return encodeCodeBlock(vm, key, unlinkedCodeBlock);
     88    });
     89
    8690    return unlinkedCodeBlock;
    8791}
     
    163167}
    164168
     169void CodeCache::updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode& parentSource, CodeSpecializationKind kind, const UnlinkedFunctionCodeBlock* codeBlock)
     170{
     171    parentSource.provider()->updateCache(executable, parentSource, kind, codeBlock);
     172}
     173
    165174void CodeCache::write(VM& vm)
    166175{
    167     for (auto& it : m_sourceCode) {
    168         if (it.value.written)
    169             continue;
    170         it.value.written = true;
     176    for (auto& it : m_sourceCode)
    171177        writeCodeBlock(vm, it.key, it.value);
    172     }
    173178}
    174179
     
    199204        return;
    200205
    201     key.source().provider().cacheBytecode([&] {
    202         std::pair<MallocPtr<uint8_t>, size_t> result = encodeCodeBlock(vm, key, codeBlock);
    203         return CachedBytecode { WTFMove(result.first), result.second };
    204     });
     206    key.source().provider().commitCachedBytecode();
    205207}
    206208
     
    231233}
    232234
    233 CachedBytecode serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode)
    234 {
    235     std::pair<MallocPtr<uint8_t>, size_t> result = encodeCodeBlock(vm,
     235Ref<CachedBytecode> serializeBytecode(VM& vm, UnlinkedCodeBlock* codeBlock, const SourceCode& source, SourceCodeType codeType, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, DebuggerMode debuggerMode)
     236{
     237    return encodeCodeBlock(vm,
    236238        sourceCodeKeyForSerializedBytecode(vm, source, codeType, strictMode, scriptMode, debuggerMode), codeBlock);
    237     return CachedBytecode { WTFMove(result.first), result.second };
    238 }
    239 
    240 }
     239}
     240
     241}
  • trunk/Source/JavaScriptCore/runtime/CodeCache.h

    r242239 r244143  
    6363} // namespace CodeCacheInternal
    6464
    65 #define VERBOSE_LOG(...) do { \
    66     if (CodeCacheInternal::verbose) \
    67         dataLogLn("(JSC::CodeCache) ", __VA_ARGS__); \
    68 } while (false)
    69 
    7065struct SourceCodeValue {
    7166    SourceCodeValue()
     
    7368    }
    7469
    75     SourceCodeValue(VM& vm, JSCell* cell, int64_t age, bool written = false)
     70    SourceCodeValue(VM& vm, JSCell* cell, int64_t age)
    7671        : cell(vm, cell)
    7772        , age(age)
    78         , written(written)
    7973    {
    8074    }
     
    8276    Strong<JSCell> cell;
    8377    int64_t age;
    84     bool written;
    8578};
    8679
     
    109102        prune();
    110103
    111         VERBOSE_LOG("Trying to find cached CodeBlock for ", key.source().provider().url().string());
    112104        iterator findResult = m_map.find(key);
    113105        if (findResult == m_map.end())
     
    132124        m_age += key.length();
    133125
    134         VERBOSE_LOG("Found cached CodeBlock in memory");
    135126        return jsCast<UnlinkedCodeBlockType*>(findResult->value.cell.get());
    136127    }
     
    167158    UnlinkedCodeBlockType* fetchFromDiskImpl(VM& vm, const SourceCodeKey& key)
    168159    {
    169         const CachedBytecode* cachedBytecode = key.source().provider().cachedBytecode();
    170         if (cachedBytecode && cachedBytecode->size()) {
    171             VERBOSE_LOG("Found cached CodeBlock in the SourceProvider");
    172             UnlinkedCodeBlockType* unlinkedCodeBlock = decodeCodeBlock<UnlinkedCodeBlockType>(vm, key, cachedBytecode->data(), cachedBytecode->size());
    173             if (unlinkedCodeBlock)
    174                 return unlinkedCodeBlock;
    175         }
    176         return nullptr;
     160        RefPtr<CachedBytecode> cachedBytecode = key.source().provider().cachedBytecode();
     161        if (!cachedBytecode || !cachedBytecode->size())
     162            return nullptr;
     163        return decodeCodeBlock<UnlinkedCodeBlockType>(vm, key, *cachedBytecode);
    177164    }
    178165
     
    241228    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, Optional<int> functionConstructorParametersEndPosition, ParserError&);
    242229
     230    void updateCache(const UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, const UnlinkedFunctionCodeBlock*);
     231
    243232    void clear() { m_sourceCode.clear(); }
    244233    JS_EXPORT_PRIVATE void write(VM&);
     
    330319
    331320void writeCodeBlock(VM&, const SourceCodeKey&, const SourceCodeValue&);
    332 CachedBytecode serializeBytecode(VM&, UnlinkedCodeBlock*, const SourceCode&, SourceCodeType, JSParserStrictMode, JSParserScriptMode, DebuggerMode);
     321Ref<CachedBytecode> serializeBytecode(VM&, UnlinkedCodeBlock*, const SourceCode&, SourceCodeType, JSParserStrictMode, JSParserScriptMode, DebuggerMode);
    333322SourceCodeKey sourceCodeKeyForSerializedProgram(VM&, const SourceCode&);
    334323SourceCodeKey sourceCodeKeyForSerializedModule(VM&, const SourceCode&);
  • trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r242239 r244143  
    9292}
    9393
    94 CachedBytecode generateProgramBytecode(VM& vm, const SourceCode& source, ParserError& error)
     94Ref<CachedBytecode> generateProgramBytecode(VM& vm, const SourceCode& source, ParserError& error)
    9595{
    9696    JSLockHolder lock(vm);
     
    105105    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedProgramCodeBlock>(vm, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
    106106    if (!unlinkedCodeBlock)
    107         return { };
     107        return CachedBytecode::create();
    108108    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ProgramType, strictMode, scriptMode, debuggerMode);
    109109}
    110110
    111 CachedBytecode generateModuleBytecode(VM& vm, const SourceCode& source, ParserError& error)
     111Ref<CachedBytecode> generateModuleBytecode(VM& vm, const SourceCode& source, ParserError& error)
    112112{
    113113    JSLockHolder lock(vm);
     
    122122    UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, source, strictMode, scriptMode, debuggerMode, error, evalContextType, &variablesUnderTDZ);
    123123    if (!unlinkedCodeBlock)
    124         return { };
     124        return CachedBytecode::create();
    125125    return serializeBytecode(vm, unlinkedCodeBlock, source, SourceCodeType::ModuleType, strictMode, scriptMode, debuggerMode);
    126126}
  • trunk/Source/JavaScriptCore/runtime/Completion.h

    r242239 r244143  
    4343JS_EXPORT_PRIVATE bool checkModuleSyntax(ExecState*, const SourceCode&, ParserError&);
    4444
    45 JS_EXPORT_PRIVATE CachedBytecode generateProgramBytecode(VM&, const SourceCode&, ParserError&);
    46 JS_EXPORT_PRIVATE CachedBytecode generateModuleBytecode(VM&, const SourceCode&, ParserError&);
     45JS_EXPORT_PRIVATE Ref<CachedBytecode> generateProgramBytecode(VM&, const SourceCode&, ParserError&);
     46JS_EXPORT_PRIVATE Ref<CachedBytecode> generateModuleBytecode(VM&, const SourceCode&, ParserError&);
    4747
    4848JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, const SourceCode&, JSValue thisValue, NakedPtr<Exception>& returnedException);
  • trunk/Source/JavaScriptCore/runtime/LeafExecutable.cpp

    r244142 r244143  
    2424 */
    2525
    26 #import "config.h"
    27 #import "JSScriptSourceProvider.h"
     26#include "config.h"
     27#include "LeafExecutable.h"
    2828
    29 #if JSC_OBJC_API_ENABLED
     29namespace JSC {
    3030
    31 #import "JSScriptInternal.h"
    32 
    33 unsigned JSScriptSourceProvider::hash() const
     31LeafExecutable LeafExecutable::operator+(size_t offset) const
    3432{
    35     return [m_script.get() hash];
     33    return LeafExecutable { static_cast<ptrdiff_t>(m_base + offset) };
    3634}
    3735
    38 StringView JSScriptSourceProvider::source() const
    39 {
    40     return [m_script.get() source];
    41 }
    42 
    43 const JSC::CachedBytecode* JSScriptSourceProvider::cachedBytecode() const
    44 {
    45     return [m_script.get() cachedBytecode];
    46 }
    47 
    48 #endif // JSC_OBJC_API_ENABLED
     36} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/LeafExecutable.h

    r244142 r244143  
    2424 */
    2525
    26 #import "config.h"
    27 #import "JSScriptSourceProvider.h"
     26#pragma once
    2827
    29 #if JSC_OBJC_API_ENABLED
     28#include <wtf/HashMap.h>
    3029
    31 #import "JSScriptInternal.h"
     30namespace JSC {
    3231
    33 unsigned JSScriptSourceProvider::hash() const
    34 {
    35     return [m_script.get() hash];
    36 }
     32class LeafExecutable;
     33class UnlinkedFunctionExecutable;
    3734
    38 StringView JSScriptSourceProvider::source() const
    39 {
    40     return [m_script.get() source];
    41 }
     35using LeafExecutableMap = HashMap<const UnlinkedFunctionExecutable*, LeafExecutable>;
    4236
    43 const JSC::CachedBytecode* JSScriptSourceProvider::cachedBytecode() const
    44 {
    45     return [m_script.get() cachedBytecode];
    46 }
     37class LeafExecutable {
     38public:
     39    LeafExecutable() = default;
    4740
    48 #endif // JSC_OBJC_API_ENABLED
     41    LeafExecutable(ptrdiff_t offset)
     42        : m_base(offset)
     43    {
     44    }
     45
     46    ptrdiff_t base() const { return m_base; }
     47    LeafExecutable operator+(size_t) const;
     48
     49private:
     50    ptrdiff_t m_base;
     51};
     52
     53} // namespace JSC
  • trunk/Tools/ChangeLog

    r244139 r244143  
     12019-04-10  Tadeu Zagallo  <tzagallo@apple.com>
     2
     3        Add support for incremental bytecode cache updates
     4        https://bugs.webkit.org/show_bug.cgi?id=195000
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Exit when the initial run to generate bytecode fails.
     9
     10        * Scripts/jsc-stress-test-helpers/bytecode-cache-test-helper.sh:
     11
    1122019-04-10  Alex Christensen  <achristensen@webkit.org>
    213
  • trunk/Tools/Scripts/jsc-stress-test-helpers/bytecode-cache-test-helper.sh

    r240255 r244143  
    3030    if [ $exitCode != 0 ]; then
    3131        echo "Command '$*' failed"
    32         return $exitCode
     32        exit $exitCode
    3333    fi
    3434}
Note: See TracChangeset for help on using the changeset viewer.