blob: 983e1aea2b95922663962e865336b565791c3a83 [file] [log] [blame]
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +00001/*
mark.lam@apple.com60c090d2019-03-07 10:16:58 +00002 * Copyright (C) 2009-2019 Apple Inc. All rights reserved.
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +00003 *
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
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000028#include "CodeBlock.h"
29#include "Debugger.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000030#include "EvalCodeBlock.h"
31#include "FunctionCodeBlock.h"
ysuzuki@apple.com5ff64dc2019-03-22 07:14:43 +000032#include "GlobalExecutable.h"
mark.lam@apple.com38aca1d2018-06-21 15:09:40 +000033#include "IsoCellSetInlines.h"
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000034#include "JIT.h"
ysuzuki@apple.come5836342019-05-07 22:15:59 +000035#include "JSTemplateObjectDescriptor.h"
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000036#include "LLIntEntrypoint.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000037#include "ModuleProgramCodeBlock.h"
ross.kirsling@sony.com0ebe33c2020-05-15 19:39:36 +000038#include "ParserError.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000039#include "ProgramCodeBlock.h"
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000040#include "VMInlines.h"
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000041
42namespace JSC {
43
utatane.tea@gmail.coma5544f12017-05-19 09:23:20 +000044const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ScriptExecutable) };
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000045
tzagallo@apple.com30abe892020-03-27 18:39:46 +000046ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, Intrinsic intrinsic)
ysuzuki@apple.com6189a492019-02-06 19:49:04 +000047 : ExecutableBase(vm, structure)
48 , m_source(source)
49 , m_intrinsic(intrinsic)
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000050 , m_features(isInStrictContext ? StrictModeFeature : 0)
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000051 , m_hasCapturedVariables(false)
52 , m_neverInline(false)
53 , m_neverOptimize(false)
54 , m_neverFTLOptimize(false)
55 , m_isArrowFunctionContext(isInArrowFunctionContext)
56 , m_canUseOSRExitFuzzing(true)
ysuzuki@apple.comcdbe02a2019-05-03 18:54:44 +000057 , m_codeForGeneratorBodyWasGenerated(false)
tzagallo@apple.com30abe892020-03-27 18:39:46 +000058 , m_isInsideOrdinaryFunction(isInsideOrdinaryFunction)
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000059 , m_derivedContextType(static_cast<unsigned>(derivedContextType))
60 , m_evalContextType(static_cast<unsigned>(evalContextType))
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +000061{
62}
63
64void ScriptExecutable::destroy(JSCell* cell)
65{
66 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
67}
68
mark.lam@apple.com38aca1d2018-06-21 15:09:40 +000069void ScriptExecutable::clearCode(IsoCellSet& clearableCodeSet)
70{
ysuzuki@apple.com6189a492019-02-06 19:49:04 +000071 m_jitCodeForCall = nullptr;
72 m_jitCodeForConstruct = nullptr;
73 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
74 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr<JSEntryPtrTag>();
ysuzuki@apple.com6189a492019-02-06 19:49:04 +000075
76 switch (type()) {
77 case FunctionExecutableType: {
78 FunctionExecutable* executable = static_cast<FunctionExecutable*>(this);
79 executable->m_codeBlockForCall.clear();
80 executable->m_codeBlockForConstruct.clear();
81 break;
82 }
83 case EvalExecutableType: {
84 EvalExecutable* executable = static_cast<EvalExecutable*>(this);
85 executable->m_evalCodeBlock.clear();
86 executable->m_unlinkedEvalCodeBlock.clear();
87 break;
88 }
89 case ProgramExecutableType: {
90 ProgramExecutable* executable = static_cast<ProgramExecutable*>(this);
91 executable->m_programCodeBlock.clear();
92 executable->m_unlinkedProgramCodeBlock.clear();
93 break;
94 }
95 case ModuleProgramExecutableType: {
96 ModuleProgramExecutable* executable = static_cast<ModuleProgramExecutable*>(this);
97 executable->m_moduleProgramCodeBlock.clear();
98 executable->m_unlinkedModuleProgramCodeBlock.clear();
99 executable->m_moduleEnvironmentSymbolTable.clear();
100 break;
101 }
102 default:
103 RELEASE_ASSERT_NOT_REACHED();
104 break;
105 }
106
ysuzuki@apple.com64b74db2019-02-05 06:32:08 +0000107 ASSERT(&VM::SpaceAndSet::setFor(*subspace()) == &clearableCodeSet);
mark.lam@apple.com38aca1d2018-06-21 15:09:40 +0000108 clearableCodeSet.remove(this);
109}
110
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000111void ScriptExecutable::installCode(CodeBlock* codeBlock)
112{
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000113 installCode(codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000114}
115
116void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)
117{
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000118 if (genericCodeBlock)
119 CODEBLOCK_LOG_EVENT(genericCodeBlock, "installCode", ());
120
121 CodeBlock* oldCodeBlock = nullptr;
122
123 switch (codeType) {
124 case GlobalCode: {
125 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
126 ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);
127
128 ASSERT(kind == CodeForCall);
129
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000130 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_programCodeBlock.get());
131 executable->m_programCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000132 break;
133 }
134
135 case ModuleCode: {
136 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
137 ModuleProgramCodeBlock* codeBlock = static_cast<ModuleProgramCodeBlock*>(genericCodeBlock);
138
139 ASSERT(kind == CodeForCall);
140
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000141 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_moduleProgramCodeBlock.get());
142 executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000143 break;
144 }
145
146 case EvalCode: {
147 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
148 EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);
149
150 ASSERT(kind == CodeForCall);
151
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000152 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_evalCodeBlock.get());
153 executable->m_evalCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000154 break;
155 }
156
157 case FunctionCode: {
158 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
159 FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);
160
161 switch (kind) {
162 case CodeForCall:
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000163 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForCall.get());
164 executable->m_codeBlockForCall.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000165 break;
166 case CodeForConstruct:
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000167 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForConstruct.get());
168 executable->m_codeBlockForConstruct.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000169 break;
170 }
171 break;
172 }
173 }
174
175 switch (kind) {
176 case CodeForCall:
177 m_jitCodeForCall = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
mark.lam@apple.comde0dba72018-04-18 03:31:09 +0000178 m_jitCodeForCallWithArityCheck = nullptr;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000179 break;
180 case CodeForConstruct:
181 m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;
mark.lam@apple.comde0dba72018-04-18 03:31:09 +0000182 m_jitCodeForConstructWithArityCheck = nullptr;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000183 break;
184 }
185
ysuzuki@apple.com64b74db2019-02-05 06:32:08 +0000186 auto& clearableCodeSet = VM::SpaceAndSet::setFor(*subspace());
ysuzuki@apple.com6189a492019-02-06 19:49:04 +0000187 if (hasClearableCode(vm))
mark.lam@apple.com38aca1d2018-06-21 15:09:40 +0000188 clearableCodeSet.add(this);
189 else
190 clearableCodeSet.remove(this);
191
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000192 if (genericCodeBlock) {
193 RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
194 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
195
rmorisset@apple.comb966ea92020-01-16 23:24:38 +0000196 dataLogLnIf(Options::verboseOSR(), "Installing ", *genericCodeBlock);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000197
mark.lam@apple.com167235e2017-08-10 23:00:06 +0000198 if (UNLIKELY(vm.m_perBytecodeProfiler))
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000199 vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);
200
mark.lam@apple.com167235e2017-08-10 23:00:06 +0000201 Debugger* debugger = genericCodeBlock->globalObject()->debugger();
202 if (UNLIKELY(debugger))
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000203 debugger->registerCodeBlock(genericCodeBlock);
204 }
205
206 if (oldCodeBlock)
207 oldCodeBlock->unlinkIncomingCalls();
208
209 vm.heap.writeBarrier(this);
210}
211
ysuzuki@apple.com6189a492019-02-06 19:49:04 +0000212bool ScriptExecutable::hasClearableCode(VM& vm) const
213{
ysuzuki@apple.com6189a492019-02-06 19:49:04 +0000214 if (m_jitCodeForCall
215 || m_jitCodeForConstruct
216 || m_jitCodeForCallWithArityCheck
217 || m_jitCodeForConstructWithArityCheck)
218 return true;
ysuzuki@apple.com6189a492019-02-06 19:49:04 +0000219
220 if (structure(vm)->classInfo() == FunctionExecutable::info()) {
221 auto* executable = static_cast<const FunctionExecutable*>(this);
222 if (executable->m_codeBlockForCall || executable->m_codeBlockForConstruct)
223 return true;
224
225 } else if (structure(vm)->classInfo() == EvalExecutable::info()) {
226 auto* executable = static_cast<const EvalExecutable*>(this);
227 if (executable->m_evalCodeBlock || executable->m_unlinkedEvalCodeBlock)
228 return true;
229
230 } else if (structure(vm)->classInfo() == ProgramExecutable::info()) {
231 auto* executable = static_cast<const ProgramExecutable*>(this);
232 if (executable->m_programCodeBlock || executable->m_unlinkedProgramCodeBlock)
233 return true;
234
235 } else if (structure(vm)->classInfo() == ModuleProgramExecutable::info()) {
236 auto* executable = static_cast<const ModuleProgramExecutable*>(this);
237 if (executable->m_moduleProgramCodeBlock
238 || executable->m_unlinkedModuleProgramCodeBlock
239 || executable->m_moduleEnvironmentSymbolTable)
240 return true;
241 }
242 return false;
243}
244
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000245CodeBlock* ScriptExecutable::newCodeBlockFor(
mark.lam@apple.com60c090d2019-03-07 10:16:58 +0000246 CodeSpecializationKind kind, JSFunction* function, JSScope* scope, Exception*& exception)
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000247{
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000248 VM& vm = scope->vm();
249 auto throwScope = DECLARE_THROW_SCOPE(vm);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000250
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000251 ASSERT(vm.heap.isDeferred());
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000252 ASSERT(endColumn() != UINT_MAX);
253
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000254 JSGlobalObject* globalObject = scope->globalObject(vm);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000255
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000256 if (classInfo(vm) == EvalExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000257 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
258 RELEASE_ASSERT(kind == CodeForCall);
259 RELEASE_ASSERT(!executable->m_evalCodeBlock);
260 RELEASE_ASSERT(!function);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000261 auto codeBlock = EvalCodeBlock::create(vm,
ysuzuki@apple.comc9db6aa2019-02-09 00:29:21 +0000262 executable, executable->m_unlinkedEvalCodeBlock.get(), scope);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000263 EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000264 if (!codeBlock) {
265 exception = throwException(
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000266 globalObject, throwScope,
267 createOutOfMemoryError(globalObject));
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000268 return nullptr;
269 }
270 return codeBlock;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000271 }
272
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000273 if (classInfo(vm) == ProgramExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000274 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
275 RELEASE_ASSERT(kind == CodeForCall);
276 RELEASE_ASSERT(!executable->m_programCodeBlock);
277 RELEASE_ASSERT(!function);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000278 auto codeBlock = ProgramCodeBlock::create(vm,
ysuzuki@apple.comc9db6aa2019-02-09 00:29:21 +0000279 executable, executable->m_unlinkedProgramCodeBlock.get(), scope);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000280 EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000281 if (!codeBlock) {
282 exception = throwException(
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000283 globalObject, throwScope,
284 createOutOfMemoryError(globalObject));
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000285 return nullptr;
286 }
287 return codeBlock;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000288 }
289
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000290 if (classInfo(vm) == ModuleProgramExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000291 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
292 RELEASE_ASSERT(kind == CodeForCall);
293 RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
294 RELEASE_ASSERT(!function);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000295 auto codeBlock = ModuleProgramCodeBlock::create(vm,
ysuzuki@apple.comc9db6aa2019-02-09 00:29:21 +0000296 executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000297 EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000298 if (!codeBlock) {
299 exception = throwException(
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000300 globalObject, throwScope,
301 createOutOfMemoryError(globalObject));
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000302 return nullptr;
303 }
304 return codeBlock;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000305 }
306
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000307 RELEASE_ASSERT(classInfo(vm) == FunctionExecutable::info());
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000308 RELEASE_ASSERT(function);
309 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
310 RELEASE_ASSERT(!executable->codeBlockFor(kind));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000311 ParserError error;
ysuzuki@apple.comcdbe02a2019-05-03 18:54:44 +0000312 OptionSet<CodeGenerationMode> codeGenerationMode = globalObject->defaultCodeGenerationMode();
313 // We continue using the same CodeGenerationMode for Generators because live generator objects can
314 // keep the state which is only valid with the CodeBlock compiled with the same CodeGenerationMode.
315 if (isGeneratorOrAsyncFunctionBodyParseMode(executable->parseMode())) {
316 if (!m_codeForGeneratorBodyWasGenerated) {
317 m_codeGenerationModeForGeneratorBody = codeGenerationMode;
318 m_codeForGeneratorBodyWasGenerated = true;
319 } else
320 codeGenerationMode = m_codeGenerationModeForGeneratorBody;
321 }
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000322 UnlinkedFunctionCodeBlock* unlinkedCodeBlock =
323 executable->m_unlinkedExecutable->unlinkedCodeBlockFor(
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000324 vm, executable->source(), kind, codeGenerationMode, error,
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000325 executable->parseMode());
326 recordParse(
327 executable->m_unlinkedExecutable->features(),
ggaren@apple.coma5548d52016-12-05 22:46:06 +0000328 executable->m_unlinkedExecutable->hasCapturedVariables(),
329 lastLine(), endColumn());
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000330 if (!unlinkedCodeBlock) {
331 exception = throwException(
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000332 globalObject, throwScope,
ysuzuki@apple.com5ff64dc2019-03-22 07:14:43 +0000333 error.toErrorObject(globalObject, executable->source()));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000334 return nullptr;
335 }
336
ysuzuki@apple.comc9db6aa2019-02-09 00:29:21 +0000337 RELEASE_AND_RETURN(throwScope, FunctionCodeBlock::create(vm, executable, unlinkedCodeBlock, scope));
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000338}
339
340CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
341 CodeSpecializationKind kind)
342{
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000343 VM& vm = this->vm();
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000344 if (classInfo(vm) == EvalExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000345 RELEASE_ASSERT(kind == CodeForCall);
346 EvalExecutable* executable = jsCast<EvalExecutable*>(this);
347 EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000348 executable->codeBlock()->baselineVersion());
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000349 EvalCodeBlock* result = EvalCodeBlock::create(vm,
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000350 CodeBlock::CopyParsedBlock, *baseline);
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000351 result->setAlternative(vm, baseline);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000352 return result;
353 }
354
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000355 if (classInfo(vm) == ProgramExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000356 RELEASE_ASSERT(kind == CodeForCall);
357 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
358 ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000359 executable->codeBlock()->baselineVersion());
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000360 ProgramCodeBlock* result = ProgramCodeBlock::create(vm,
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000361 CodeBlock::CopyParsedBlock, *baseline);
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000362 result->setAlternative(vm, baseline);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000363 return result;
364 }
365
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000366 if (classInfo(vm) == ModuleProgramExecutable::info()) {
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000367 RELEASE_ASSERT(kind == CodeForCall);
368 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
369 ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>(
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000370 executable->codeBlock()->baselineVersion());
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000371 ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(vm,
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000372 CodeBlock::CopyParsedBlock, *baseline);
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000373 result->setAlternative(vm, baseline);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000374 return result;
375 }
376
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000377 RELEASE_ASSERT(classInfo(vm) == FunctionExecutable::info());
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000378 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
379 FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
380 executable->codeBlockFor(kind)->baselineVersion());
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000381 FunctionCodeBlock* result = FunctionCodeBlock::create(vm,
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000382 CodeBlock::CopyParsedBlock, *baseline);
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000383 result->setAlternative(vm, baseline);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000384 return result;
385}
386
ticaiolima@gmail.com49f5dbf2019-03-19 13:36:05 +0000387static void setupLLInt(CodeBlock* codeBlock)
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000388{
ticaiolima@gmail.com49f5dbf2019-03-19 13:36:05 +0000389 LLInt::setEntrypoint(codeBlock);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000390}
391
392static void setupJIT(VM& vm, CodeBlock* codeBlock)
393{
394#if ENABLE(JIT)
mark.lam@apple.com5ba07792019-08-27 22:14:52 +0000395 CompilationResult result = JIT::compile(vm, codeBlock, JITCompilationMustSucceed);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000396 RELEASE_ASSERT(result == CompilationSuccessful);
397#else
398 UNUSED_PARAM(vm);
399 UNUSED_PARAM(codeBlock);
400 UNREACHABLE_FOR_PLATFORM();
401#endif
402}
403
mark.lam@apple.com60c090d2019-03-07 10:16:58 +0000404Exception* ScriptExecutable::prepareForExecutionImpl(
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000405 VM& vm, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)
406{
mark.lam@apple.com758b3782016-11-21 17:19:30 +0000407 auto throwScope = DECLARE_THROW_SCOPE(vm);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000408 DeferGCForAWhile deferGC(vm.heap);
409
mark.lam@apple.com60c090d2019-03-07 10:16:58 +0000410 if (UNLIKELY(vm.getAndClearFailNextNewCodeBlock())) {
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000411 JSGlobalObject* globalObject = scope->globalObject(vm);
412 return throwException(globalObject, throwScope, createError(globalObject, "Forced Failure"_s));
mark.lam@apple.com758b3782016-11-21 17:19:30 +0000413 }
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000414
mark.lam@apple.com60c090d2019-03-07 10:16:58 +0000415 Exception* exception = nullptr;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000416 CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
417 resultCodeBlock = codeBlock;
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000418 EXCEPTION_ASSERT(!!throwScope.exception() == !codeBlock);
mark.lam@apple.com758b3782016-11-21 17:19:30 +0000419 if (UNLIKELY(!codeBlock))
ryanhaddad@apple.combd063872018-10-12 21:42:23 +0000420 return exception;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000421
422 if (Options::validateBytecode())
423 codeBlock->validate();
424
commit-queue@webkit.orgbe3c27f2020-01-15 06:02:48 +0000425 if (Options::useLLInt())
sbarati@apple.coma2543722020-01-14 01:43:03 +0000426 setupLLInt(codeBlock);
commit-queue@webkit.orgbe3c27f2020-01-15 06:02:48 +0000427 else
428 setupJIT(vm, codeBlock);
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000429
430 installCode(vm, codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
ryanhaddad@apple.combd063872018-10-12 21:42:23 +0000431 return nullptr;
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000432}
433
ysuzuki@apple.come5836342019-05-07 22:15:59 +0000434ScriptExecutable* ScriptExecutable::topLevelExecutable()
435{
436 switch (type()) {
437 case FunctionExecutableType:
438 return jsCast<FunctionExecutable*>(this)->topLevelExecutable();
439 default:
440 return this;
441 }
442}
443
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000444JSArray* ScriptExecutable::createTemplateObject(JSGlobalObject* globalObject, JSTemplateObjectDescriptor* descriptor)
ysuzuki@apple.come5836342019-05-07 22:15:59 +0000445{
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000446 VM& vm = globalObject->vm();
ysuzuki@apple.come5836342019-05-07 22:15:59 +0000447 auto scope = DECLARE_THROW_SCOPE(vm);
448
449 TemplateObjectMap& templateObjectMap = ensureTemplateObjectMap(vm);
450 TemplateObjectMap::AddResult result;
451 {
452 auto locker = holdLock(cellLock());
453 result = templateObjectMap.add(descriptor->endOffset(), WriteBarrier<JSArray>());
454 }
455 if (JSArray* array = result.iterator->value.get())
456 return array;
ysuzuki@apple.com52e98bb2019-10-22 09:24:48 +0000457 JSArray* templateObject = descriptor->createTemplateObject(globalObject);
ysuzuki@apple.come5836342019-05-07 22:15:59 +0000458 RETURN_IF_EXCEPTION(scope, nullptr);
459 result.iterator->value.set(vm, this, templateObject);
460 return templateObject;
461}
462
463auto ScriptExecutable::ensureTemplateObjectMapImpl(std::unique_ptr<TemplateObjectMap>& dest) -> TemplateObjectMap&
464{
465 if (dest)
466 return *dest;
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +0000467 auto result = makeUnique<TemplateObjectMap>();
ysuzuki@apple.come5836342019-05-07 22:15:59 +0000468 WTF::storeStoreFence();
469 dest = WTFMove(result);
470 return *dest;
471}
472
473auto ScriptExecutable::ensureTemplateObjectMap(VM& vm) -> TemplateObjectMap&
474{
475 switch (type()) {
476 case FunctionExecutableType:
477 return static_cast<FunctionExecutable*>(this)->ensureTemplateObjectMap(vm);
478 case EvalExecutableType:
479 return static_cast<EvalExecutable*>(this)->ensureTemplateObjectMap(vm);
480 case ProgramExecutableType:
481 return static_cast<ProgramExecutable*>(this)->ensureTemplateObjectMap(vm);
482 case ModuleProgramExecutableType:
483 default:
484 ASSERT(type() == ModuleProgramExecutableType);
485 return static_cast<ModuleProgramExecutable*>(this)->ensureTemplateObjectMap(vm);
486 }
487}
488
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000489CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const
490{
491 return CodeBlockHash(source(), kind);
492}
493
ysuzuki@apple.com5fbfa402019-02-04 21:02:27 +0000494Optional<int> ScriptExecutable::overrideLineNumber(VM& vm) const
495{
496 if (inherits<FunctionExecutable>(vm))
497 return jsCast<const FunctionExecutable*>(this)->overrideLineNumber();
498 return WTF::nullopt;
499}
500
501unsigned ScriptExecutable::typeProfilingStartOffset(VM& vm) const
502{
503 if (inherits<FunctionExecutable>(vm))
504 return jsCast<const FunctionExecutable*>(this)->typeProfilingStartOffset(vm);
505 if (inherits<EvalExecutable>(vm))
506 return UINT_MAX;
507 return 0;
508}
509
510unsigned ScriptExecutable::typeProfilingEndOffset(VM& vm) const
511{
512 if (inherits<FunctionExecutable>(vm))
513 return jsCast<const FunctionExecutable*>(this)->typeProfilingEndOffset(vm);
514 if (inherits<EvalExecutable>(vm))
515 return UINT_MAX;
ysuzuki@apple.com5ff64dc2019-03-22 07:14:43 +0000516 return source().length() - 1;
517}
518
519void ScriptExecutable::recordParse(CodeFeatures features, bool hasCapturedVariables, int lastLine, unsigned endColumn)
520{
521 switch (type()) {
522 case FunctionExecutableType:
523 // Since UnlinkedFunctionExecutable holds the information to calculate lastLine and endColumn, we do not need to remember them in ScriptExecutable's fields.
524 jsCast<FunctionExecutable*>(this)->recordParse(features, hasCapturedVariables);
525 return;
526 default:
527 jsCast<GlobalExecutable*>(this)->recordParse(features, hasCapturedVariables, lastLine, endColumn);
528 return;
529 }
530}
531
532int ScriptExecutable::lastLine() const
533{
534 switch (type()) {
535 case FunctionExecutableType:
536 return jsCast<const FunctionExecutable*>(this)->lastLine();
537 default:
538 return jsCast<const GlobalExecutable*>(this)->lastLine();
539 }
540 return 0;
541}
542
543unsigned ScriptExecutable::endColumn() const
544{
545 switch (type()) {
546 case FunctionExecutableType:
547 return jsCast<const FunctionExecutable*>(this)->endColumn();
548 default:
549 return jsCast<const GlobalExecutable*>(this)->endColumn();
550 }
551 return 0;
ysuzuki@apple.com5fbfa402019-02-04 21:02:27 +0000552}
553
ggaren@apple.comc9a6ef42016-10-28 20:04:56 +0000554} // namespace JSC