2727#import " JSScriptInternal.h"
2828
2929#import " APICast.h"
30+ #import " Identifier.h"
3031#import " JSContextInternal.h"
32+ #import " JSScriptSourceProvider.h"
33+ #import " JSSourceCode.h"
3134#import " JSValuePrivate.h"
35+ #import " JSVirtualMachineInternal.h"
36+ #import " ParserError.h"
3237#import " Symbol.h"
38+ #include < sys/stat.h>
3339
3440#if JSC_OBJC_API_ENABLED
3541
3642@implementation JSScript {
43+ __weak JSVirtualMachine* m_virtualMachine;
3744 String m_source;
45+ NSURL * m_cachePath;
46+ JSC ::CachedBytecode m_cachedBytecode;
47+ JSC ::Strong<JSC ::JSSourceCode> m_jsSourceCode;
48+ UniquedStringImpl* m_moduleKey;
3849}
3950
4051+ (instancetype )scriptWithSource : (NSString *)source inVirtualMachine : (JSVirtualMachine *)vm
4152{
42- UNUSED_PARAM (vm);
43- JSScript *result = [[JSScript alloc ] init ];
53+ JSScript *result = [[[JSScript alloc ] init ] autorelease ];
4454 result->m_source = source;
55+ result->m_virtualMachine = vm;
4556 return result;
4657}
4758
@@ -81,9 +92,6 @@ + (instancetype)scriptFromASCIIFile:(NSURL *)filePath inVirtualMachine:(JSVirtua
8192{
8293 // FIXME: This should check codeSigning.
8394 UNUSED_PARAM (codeSigningPath);
84- // FIXME: This should actually cache bytecode.
85- UNUSED_PARAM (cachePath);
86- UNUSED_PARAM (vm);
8795 URL filePathURL ([filePath absoluteURL ]);
8896 if (!filePathURL.isLocalFile ())
8997 return nil ;
@@ -95,8 +103,11 @@ + (instancetype)scriptFromASCIIFile:(NSURL *)filePath inVirtualMachine:(JSVirtua
95103 if (!charactersAreAllASCII (buffer.data (), buffer.size ()))
96104 return nil ;
97105
98- JSScript *result = [[JSScript alloc ] init ];
106+ JSScript *result = [[[JSScript alloc ] init ] autorelease ];
107+ result->m_virtualMachine = vm;
99108 result->m_source = String::fromUTF8WithLatin1Fallback (buffer.data (), buffer.size ());
109+ result->m_cachePath = cachePath;
110+ [result readCache ];
100111 return result;
101112}
102113
@@ -105,7 +116,95 @@ + (instancetype)scriptFromUTF8File:(NSURL *)filePath inVirtualMachine:(JSVirtual
105116 return [JSScript scriptFromASCIIFile: filePath inVirtualMachine: vm withCodeSigning: codeSigningPath andBytecodeCache: cachePath];
106117}
107118
108- const String& getJSScriptSourceCode (JSScript *module ) { return module ->m_source ; }
119+ - (void )dealloc
120+ {
121+ if (m_cachedBytecode.size () && !m_cachedBytecode.owned ())
122+ munmap (const_cast <void *>(m_cachedBytecode.data ()), m_cachedBytecode.size ());
123+ [super dealloc ];
124+ }
125+
126+ - (void )readCache
127+ {
128+ if (!m_cachePath)
129+ return ;
130+
131+ int fd = open (m_cachePath.path .UTF8String , O_RDONLY );
132+ if (fd == -1 )
133+ return ;
134+
135+ int rc = flock (fd, LOCK_SH | LOCK_NB );
136+ if (rc) {
137+ close (fd);
138+ return ;
139+ }
140+
141+ struct stat sb;
142+ int res = fstat (fd, &sb);
143+ size_t size = static_cast <size_t >(sb.st_size );
144+ if (res || !size) {
145+ close (fd);
146+ return ;
147+ }
148+
149+ void * buffer = mmap (nullptr , size, PROT_READ , MAP_PRIVATE , fd, 0 );
150+ close (fd);
151+
152+ m_cachedBytecode = JSC ::CachedBytecode { buffer, size };
153+ }
154+
155+ - (void )writeCache
156+ {
157+ if (m_cachedBytecode.size () || !m_cachePath)
158+ return ;
159+
160+ JSC ::ParserError error;
161+ m_cachedBytecode = JSC::generateModuleBytecode (m_virtualMachine.vm , m_jsSourceCode->sourceCode (), error);
162+ if (error.isValid ())
163+ return ;
164+ int fd = open (m_cachePath.path .UTF8String , O_CREAT | O_WRONLY , 0666 );
165+ if (fd == -1 )
166+ return ;
167+ int rc = flock (fd, LOCK_EX | LOCK_NB );
168+ if (!rc)
169+ write (fd, m_cachedBytecode.data (), m_cachedBytecode.size ());
170+ close (fd);
171+ }
172+
173+ @end
174+
175+ @implementation JSScript (Internal)
176+
177+ - (unsigned )hash
178+ {
179+ return m_source.hash ();
180+ }
181+
182+ - (const String&)source
183+ {
184+ return m_source;
185+ }
186+
187+ - (const JSC ::CachedBytecode*)cachedBytecode
188+ {
189+ return &m_cachedBytecode;
190+ }
191+
192+ - (JSC ::JSSourceCode*)jsSourceCode : (const JSC ::Identifier&)moduleKey
193+ {
194+ if (m_jsSourceCode) {
195+ ASSERT (moduleKey.impl () == m_moduleKey);
196+ return m_jsSourceCode.get ();
197+ }
198+
199+ JSC ::VM & vm = m_virtualMachine.vm ;
200+ TextPosition startPosition { };
201+ Ref<JSScriptSourceProvider> sourceProvider = JSScriptSourceProvider::create (self, JSC::SourceOrigin (moduleKey.string ()), URL ({ }, moduleKey.string ()), TextPosition (), JSC ::SourceProviderSourceType::Module);
202+ JSC ::SourceCode sourceCode (WTFMove (sourceProvider), startPosition.m_line .oneBasedInt (), startPosition.m_column .oneBasedInt ());
203+ JSC ::JSSourceCode* jsSourceCode = JSC::JSSourceCode::create (vm, WTFMove (sourceCode));
204+ m_jsSourceCode.set (vm, jsSourceCode);
205+ [self writeCache ];
206+ return jsSourceCode;
207+ }
109208
110209@end
111210
0 commit comments