115b178ce2bcf3ff5938207a0faf3c57d517b8b1
[WebKit-https.git] / Source / JavaScriptCore / runtime / ScriptExecutable.cpp
1 /*
2  * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #include "BatchedTransitionOptimizer.h"
29 #include "CodeBlock.h"
30 #include "Debugger.h"
31 #include "EvalCodeBlock.h"
32 #include "FunctionCodeBlock.h"
33 #include "IsoCellSetInlines.h"
34 #include "JIT.h"
35 #include "JSCInlines.h"
36 #include "LLIntEntrypoint.h"
37 #include "ModuleProgramCodeBlock.h"
38 #include "Parser.h"
39 #include "ProgramCodeBlock.h"
40 #include "TypeProfiler.h"
41 #include "VMInlines.h"
42 #include <wtf/CommaPrinter.h>
43
44 namespace JSC {
45
46 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ScriptExecutable) };
47
48 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, EvalContextType evalContextType, Intrinsic intrinsic)
49     : ExecutableBase(vm, structure)
50     , m_source(source)
51     , m_intrinsic(intrinsic)
52     , m_features(isInStrictContext ? StrictModeFeature : 0)
53     , m_hasCapturedVariables(false)
54     , m_neverInline(false)
55     , m_neverOptimize(false)
56     , m_neverFTLOptimize(false)
57     , m_isArrowFunctionContext(isInArrowFunctionContext)
58     , m_canUseOSRExitFuzzing(true)
59     , m_derivedContextType(static_cast<unsigned>(derivedContextType))
60     , m_evalContextType(static_cast<unsigned>(evalContextType))
61 {
62 }
63
64 void ScriptExecutable::destroy(JSCell* cell)
65 {
66     static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
67 }
68
69 void ScriptExecutable::clearCode(IsoCellSet& clearableCodeSet)
70 {
71 #if ENABLE(JIT)
72     m_jitCodeForCall = nullptr;
73     m_jitCodeForConstruct = nullptr;
74     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
75     m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
76 #endif
77     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
78     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
79
80     switch (type()) {
81     case FunctionExecutableType: {
82         FunctionExecutable* executable = static_cast<FunctionExecutable*>(this);
83         executable->m_codeBlockForCall.clear();
84         executable->m_codeBlockForConstruct.clear();
85         break;
86     }
87     case EvalExecutableType: {
88         EvalExecutable* executable = static_cast<EvalExecutable*>(this);
89         executable->m_evalCodeBlock.clear();
90         executable->m_unlinkedEvalCodeBlock.clear();
91         break;
92     }
93     case ProgramExecutableType: {
94         ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
95         executable->m_programCodeBlock.clear();
96         executable->m_unlinkedProgramCodeBlock.clear();
97         break;
98     }
99     case ModuleProgramExecutableType: {
100         ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
101         executable->m_moduleProgramCodeBlock.clear();
102         executable->m_unlinkedModuleProgramCodeBlock.clear();
103         executable->m_moduleEnvironmentSymbolTable.clear();
104         break;
105     }
106     default:
107         RELEASE_ASSERT_NOT_REACHED();
108         break;
109     }
110
111     ASSERT(&VM::SpaceAndSet::setFor(*subspace()) == &clearableCodeSet);
112     clearableCodeSet.remove(this);
113 }
114
115 void ScriptExecutable::installCode(CodeBlock* codeBlock)
116 {
117     installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
118 }
119
120 void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)
121 {
122     if (genericCodeBlock)
123         CODEBLOCK_LOG_EVENT(genericCodeBlock, "installCode", ());
124     
125     CodeBlock* oldCodeBlock = nullptr;
126     
127     switch (codeType) {
128     case GlobalCode: {
129         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
130         ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
131         
132         ASSERT(kind == CodeForCall);
133         
134         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_programCodeBlock.get());
135         executable->m_programCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
136         break;
137     }
138
139     case ModuleCode: {
140         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
141         ModuleProgramCodeBlock* codeBlock = static_cast<ModuleProgramCodeBlock*>(genericCodeBlock);
142
143         ASSERT(kind == CodeForCall);
144
145         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_moduleProgramCodeBlock.get());
146         executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
147         break;
148     }
149
150     case EvalCode: {
151         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
152         EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
153         
154         ASSERT(kind == CodeForCall);
155         
156         oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_evalCodeBlock.get());
157         executable->m_evalCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
158         break;
159     }
160         
161     case FunctionCode: {
162         FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
163         FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
164         
165         switch (kind) {
166         case CodeForCall:
167             oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForCall.get());
168             executable->m_codeBlockForCall.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
169             break;
170         case CodeForConstruct:
171             oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForConstruct.get());
172             executable->m_codeBlockForConstruct.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
173             break;
174         }
175         break;
176     }
177     }
178
179     switch (kind) {
180     case CodeForCall:
181         m_jitCodeForCall = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
182         m_jitCodeForCallWithArityCheck = nullptr;
183         m_numParametersForCall = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
184         break;
185     case CodeForConstruct:
186         m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
187         m_jitCodeForConstructWithArityCheck = nullptr;
188         m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;
189         break;
190     }
191
192     auto& clearableCodeSet = VM::SpaceAndSet::setFor(*subspace());
193     if (hasClearableCode(vm))
194         clearableCodeSet.add(this);
195     else
196         clearableCodeSet.remove(this);
197
198     if (genericCodeBlock) {
199         RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
200         RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
201         
202         if (UNLIKELY(Options::verboseOSR()))
203             dataLog("Installing ", *genericCodeBlock, "\n");
204         
205         if (UNLIKELY(vm.m_perBytecodeProfiler))
206             vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
207         
208         Debugger* debugger = genericCodeBlock->globalObject()->debugger();
209         if (UNLIKELY(debugger))
210             debugger->registerCodeBlock(genericCodeBlock);
211     }
212
213     if (oldCodeBlock)
214         oldCodeBlock->unlinkIncomingCalls();
215
216     vm.heap.writeBarrier(this);
217 }
218
219 bool ScriptExecutable::hasClearableCode(VM& vm) const
220 {
221 #if ENABLE(JIT)
222     if (m_jitCodeForCall
223         || m_jitCodeForConstruct
224         || m_jitCodeForCallWithArityCheck
225         || m_jitCodeForConstructWithArityCheck)
226         return true;
227 #endif
228
229     if (structure(vm)->classInfo() == FunctionExecutable::info()) {
230         auto* executable = static_cast<const FunctionExecutable*>(this);
231         if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
232             return true;
233
234     } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
235         auto* executable = static_cast<const EvalExecutable*>(this);
236         if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
237             return true;
238
239     } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
240         auto* executable = static_cast<const ProgramExecutable*>(this);
241         if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
242             return true;
243
244     } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
245         auto* executable = static_cast<const ModuleProgramExecutable*>(this);
246         if (executable->m_moduleProgramCodeBlock
247             || executable->m_unlinkedModuleProgramCodeBlock
248             || executable->m_moduleEnvironmentSymbolTable)
249             return true;
250     }
251     return false;
252 }
253
254 CodeBlock* ScriptExecutable::newCodeBlockFor(
255     CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
256 {
257     VM* vm = scope->vm();
258     auto throwScope = DECLARE_THROW_SCOPE(*vm);
259
260     ASSERT(vm->heap.isDeferred());
261     ASSERT(endColumn() != UINT_MAX);
262
263     JSGlobalObject* globalObject = scope->globalObject(*vm);
264     ExecState* exec = globalObject->globalExec();
265
266     if (classInfo(*vm) == EvalExecutable::info()) {
267         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
268         RELEASE_ASSERT(kind == CodeForCall);
269         RELEASE_ASSERT(!executable->m_evalCodeBlock);
270         RELEASE_ASSERT(!function);
271         auto codeBlock = EvalCodeBlock::create(vm,
272             executable, executable->m_unlinkedEvalCodeBlock.get(), scope);
273         EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
274         if (!codeBlock) {
275             exception = throwException(
276                 exec, throwScope,
277                 createOutOfMemoryError(exec));
278             return nullptr;
279         }
280         return codeBlock;
281     }
282     
283     if (classInfo(*vm) == ProgramExecutable::info()) {
284         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
285         RELEASE_ASSERT(kind == CodeForCall);
286         RELEASE_ASSERT(!executable->m_programCodeBlock);
287         RELEASE_ASSERT(!function);
288         auto codeBlock = ProgramCodeBlock::create(vm,
289             executable, executable->m_unlinkedProgramCodeBlock.get(), scope);
290         EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
291         if (!codeBlock) {
292             exception = throwException(
293                 exec, throwScope,
294                 createOutOfMemoryError(exec));
295             return nullptr;
296         }
297         return codeBlock;
298     }
299
300     if (classInfo(*vm) == ModuleProgramExecutable::info()) {
301         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
302         RELEASE_ASSERT(kind == CodeForCall);
303         RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
304         RELEASE_ASSERT(!function);
305         auto codeBlock = ModuleProgramCodeBlock::create(vm,
306             executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope);
307         EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
308         if (!codeBlock) {
309             exception = throwException(
310                 exec, throwScope,
311                 createOutOfMemoryError(exec));
312             return nullptr;
313         }
314         return codeBlock;
315     }
316
317     RELEASE_ASSERT(classInfo(*vm) == FunctionExecutable::info());
318     RELEASE_ASSERT(function);
319     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
320     RELEASE_ASSERT(!executable->codeBlockFor(kind));
321     ParserError error;
322     DebuggerMode debuggerMode = globalObject->hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
323     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = 
324         executable->m_unlinkedExecutable->unlinkedCodeBlockFor(
325             *vm, executable->m_source, kind, debuggerMode, error, 
326             executable->parseMode());
327     recordParse(
328         executable->m_unlinkedExecutable->features(), 
329         executable->m_unlinkedExecutable->hasCapturedVariables(),
330         lastLine(), endColumn()); 
331     if (!unlinkedCodeBlock) {
332         exception = throwException(
333             globalObject->globalExec(), throwScope,
334             error.toErrorObject(globalObject, executable->m_source));
335         return nullptr;
336     }
337
338     RELEASE_AND_RETURN(throwScope, FunctionCodeBlock::create(vm, executable, unlinkedCodeBlock, scope));
339 }
340
341 CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
342     CodeSpecializationKind kind)
343 {
344     VM& vm = *this->vm();
345     if (classInfo(vm) == EvalExecutable::info()) {
346         RELEASE_ASSERT(kind == CodeForCall);
347         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
348         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
349             executable->codeBlock()->baselineVersion());
350         EvalCodeBlock* result = EvalCodeBlock::create(&vm,
351             CodeBlock::CopyParsedBlock, *baseline);
352         result->setAlternative(vm, baseline);
353         return result;
354     }
355     
356     if (classInfo(vm) == ProgramExecutable::info()) {
357         RELEASE_ASSERT(kind == CodeForCall);
358         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
359         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
360             executable->codeBlock()->baselineVersion());
361         ProgramCodeBlock* result = ProgramCodeBlock::create(&vm,
362             CodeBlock::CopyParsedBlock, *baseline);
363         result->setAlternative(vm, baseline);
364         return result;
365     }
366
367     if (classInfo(vm) == ModuleProgramExecutable::info()) {
368         RELEASE_ASSERT(kind == CodeForCall);
369         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
370         ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>(
371             executable->codeBlock()->baselineVersion());
372         ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(&vm,
373             CodeBlock::CopyParsedBlock, *baseline);
374         result->setAlternative(vm, baseline);
375         return result;
376     }
377
378     RELEASE_ASSERT(classInfo(vm) == FunctionExecutable::info());
379     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
380     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
381         executable->codeBlockFor(kind)->baselineVersion());
382     FunctionCodeBlock* result = FunctionCodeBlock::create(&vm,
383         CodeBlock::CopyParsedBlock, *baseline);
384     result->setAlternative(vm, baseline);
385     return result;
386 }
387
388 static void setupLLInt(VM& vm, CodeBlock* codeBlock)
389 {
390     LLInt::setEntrypoint(vm, codeBlock);
391 }
392
393 static void setupJIT(VM& vm, CodeBlock* codeBlock)
394 {
395 #if ENABLE(JIT)
396     CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);
397     RELEASE_ASSERT(result == CompilationSuccessful);
398 #else
399     UNUSED_PARAM(vm);
400     UNUSED_PARAM(codeBlock);
401     UNREACHABLE_FOR_PLATFORM();
402 #endif
403 }
404
405 JSObject* ScriptExecutable::prepareForExecutionImpl(
406     VM& vm, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)
407 {
408     auto throwScope = DECLARE_THROW_SCOPE(vm);
409     DeferGCForAWhile deferGC(vm.heap);
410
411     if (vm.getAndClearFailNextNewCodeBlock()) {
412         auto& state = *scope->globalObject(vm)->globalExec();
413         return throwException(&state, throwScope, createError(&state, "Forced Failure"_s));
414     }
415
416     JSObject* exception = nullptr;
417     CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
418     resultCodeBlock = codeBlock;
419     EXCEPTION_ASSERT(!!throwScope.exception() == !codeBlock);
420     if (UNLIKELY(!codeBlock))
421         return exception;
422     
423     if (Options::validateBytecode())
424         codeBlock->validate();
425     
426     if (Options::useLLInt())
427         setupLLInt(vm, codeBlock);
428     else
429         setupJIT(vm, codeBlock);
430     
431     installCode(vm, codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
432     return nullptr;
433 }
434
435 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
436 {
437     return CodeBlockHash(source(), kind);
438 }
439
440 Optional<int> ScriptExecutable::overrideLineNumber(VM& vm) const
441 {
442     if (inherits<FunctionExecutable>(vm))
443         return jsCast<const FunctionExecutable*>(this)->overrideLineNumber();
444     return WTF::nullopt;
445 }
446
447 unsigned ScriptExecutable::typeProfilingStartOffset(VM& vm) const
448 {
449     if (inherits<FunctionExecutable>(vm))
450         return jsCast<const FunctionExecutable*>(this)->typeProfilingStartOffset(vm);
451     if (inherits<EvalExecutable>(vm))
452         return UINT_MAX;
453     return 0;
454 }
455
456 unsigned ScriptExecutable::typeProfilingEndOffset(VM& vm) const
457 {
458     if (inherits<FunctionExecutable>(vm))
459         return jsCast<const FunctionExecutable*>(this)->typeProfilingEndOffset(vm);
460     if (inherits<EvalExecutable>(vm))
461         return UINT_MAX;
462     return m_source.length() - 1;
463 }
464
465 } // namespace JSC