2 * Copyright (C) 2009, 2010, 2013-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "ArityCheckMode.h"
31 #include "CodeBlockHash.h"
32 #include "CodeSpecializationKind.h"
33 #include "CompilationResult.h"
34 #include "ExecutableInfo.h"
35 #include "HandlerInfo.h"
36 #include "InferredValue.h"
38 #include "JSGlobalObject.h"
39 #include "SourceCode.h"
41 #include "UnlinkedCodeBlock.h"
42 #include "UnlinkedFunctionExecutable.h"
49 class FunctionCodeBlock;
52 class LLIntOffsetsExtractor;
53 class ProgramCodeBlock;
54 class ModuleProgramCodeBlock;
56 class WebAssemblyCodeBlock;
57 class ModuleProgramCodeBlock;
61 enum CompilationKind { FirstCompilation, OptimizingCompilation };
63 inline bool isCall(CodeSpecializationKind kind)
65 if (kind == CodeForCall)
67 ASSERT(kind == CodeForConstruct);
71 class ExecutableBase : public JSCell {
75 static const int NUM_PARAMETERS_IS_HOST = 0;
76 static const int NUM_PARAMETERS_NOT_COMPILED = -1;
78 ExecutableBase(VM& vm, Structure* structure, int numParameters, Intrinsic intrinsic)
79 : JSCell(vm, structure)
80 , m_numParametersForCall(numParameters)
81 , m_numParametersForConstruct(numParameters)
82 , m_intrinsic(intrinsic)
86 void finishCreation(VM& vm)
88 Base::finishCreation(vm);
93 static const unsigned StructureFlags = Base::StructureFlags;
95 static const bool needsDestruction = true;
96 static void destroy(JSCell*);
98 CodeBlockHash hashFor(CodeSpecializationKind) const;
100 bool isEvalExecutable() const
102 return type() == EvalExecutableType;
104 bool isFunctionExecutable() const
106 return type() == FunctionExecutableType;
108 bool isProgramExecutable() const
110 return type() == ProgramExecutableType;
112 bool isModuleProgramExecutable()
114 return type() == ModuleProgramExecutableType;
118 bool isHostFunction() const
120 ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
121 return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
124 #if ENABLE(WEBASSEMBLY)
125 bool isWebAssemblyExecutable() const
127 return type() == WebAssemblyExecutableType;
131 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
138 int m_numParametersForCall;
139 int m_numParametersForConstruct;
142 PassRefPtr<JITCode> generatedJITCodeForCall()
144 ASSERT(m_jitCodeForCall);
145 return m_jitCodeForCall;
148 PassRefPtr<JITCode> generatedJITCodeForConstruct()
150 ASSERT(m_jitCodeForConstruct);
151 return m_jitCodeForConstruct;
154 PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
156 if (kind == CodeForCall)
157 return generatedJITCodeForCall();
158 ASSERT(kind == CodeForConstruct);
159 return generatedJITCodeForConstruct();
162 MacroAssemblerCodePtr entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity)
164 // Check if we have a cached result. We only have it for arity check because we use the
165 // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in
167 if (arity == MustCheckArity) {
170 if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
173 case CodeForConstruct:
174 if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
179 MacroAssemblerCodePtr result =
180 generatedJITCodeFor(kind)->addressForCall(arity);
181 if (arity == MustCheckArity) {
182 // Cache the result; this is necessary for the JIT's virtual call optimizations.
185 m_jitCodeForCallWithArityCheck = result;
187 case CodeForConstruct:
188 m_jitCodeForConstructWithArityCheck = result;
195 static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
196 CodeSpecializationKind kind)
200 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
201 case CodeForConstruct:
202 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
204 RELEASE_ASSERT_NOT_REACHED();
208 static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
210 if (kind == CodeForCall)
211 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
212 ASSERT(kind == CodeForConstruct);
213 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
216 bool hasJITCodeForCall() const
218 return m_numParametersForCall >= 0;
221 bool hasJITCodeForConstruct() const
223 return m_numParametersForConstruct >= 0;
226 bool hasJITCodeFor(CodeSpecializationKind kind) const
228 if (kind == CodeForCall)
229 return hasJITCodeForCall();
230 ASSERT(kind == CodeForConstruct);
231 return hasJITCodeForConstruct();
234 // Intrinsics are only for calls, currently.
235 Intrinsic intrinsic() const { return m_intrinsic; }
237 Intrinsic intrinsicFor(CodeSpecializationKind kind) const
244 void dump(PrintStream&) const;
247 Intrinsic m_intrinsic;
248 RefPtr<JITCode> m_jitCodeForCall;
249 RefPtr<JITCode> m_jitCodeForConstruct;
250 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
251 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
254 class NativeExecutable final : public ExecutableBase {
256 friend class LLIntOffsetsExtractor;
258 typedef ExecutableBase Base;
259 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
261 static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name);
263 static void destroy(JSCell*);
265 CodeBlockHash hashFor(CodeSpecializationKind) const;
267 NativeFunction function() { return m_function; }
268 NativeFunction constructor() { return m_constructor; }
270 NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
272 if (kind == CodeForCall)
274 ASSERT(kind == CodeForConstruct);
275 return constructor();
278 static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
280 if (kind == CodeForCall)
281 return OBJECT_OFFSETOF(NativeExecutable, m_function);
282 ASSERT(kind == CodeForConstruct);
283 return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
286 static Structure* createStructure(VM&, JSGlobalObject*, JSValue proto);
290 const String& name() const { return m_name; }
293 void finishCreation(VM&, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, const String& name);
296 friend class ExecutableBase;
298 NativeExecutable(VM&, NativeFunction function, NativeFunction constructor, Intrinsic);
300 NativeFunction m_function;
301 NativeFunction m_constructor;
306 class ScriptExecutable : public ExecutableBase {
308 typedef ExecutableBase Base;
309 static const unsigned StructureFlags = Base::StructureFlags;
311 static void destroy(JSCell*);
313 CodeBlockHash hashFor(CodeSpecializationKind) const;
315 const SourceCode& source() const { return m_source; }
316 intptr_t sourceID() const { return m_source.providerID(); }
317 const String& sourceURL() const { return m_source.provider()->url(); }
318 int firstLine() const { return m_firstLine; }
319 void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; }
320 bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; }
321 int overrideLineNumber() const { return m_overrideLineNumber; }
322 int lastLine() const { return m_lastLine; }
323 unsigned startColumn() const { return m_startColumn; }
324 unsigned endColumn() const { return m_endColumn; }
325 unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
326 unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
328 bool usesEval() const { return m_features & EvalFeature; }
329 bool usesArguments() const { return m_features & ArgumentsFeature; }
330 bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
331 bool isStrictMode() const { return m_features & StrictModeFeature; }
332 DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
333 EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); }
335 ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
337 void setNeverInline(bool value) { m_neverInline = value; }
338 void setNeverOptimize(bool value) { m_neverOptimize = value; }
339 void setNeverFTLOptimize(bool value) { m_neverFTLOptimize = value; }
340 void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
341 bool neverInline() const { return m_neverInline; }
342 bool neverOptimize() const { return m_neverOptimize; }
343 bool neverFTLOptimize() const { return m_neverFTLOptimize; }
344 bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
345 bool isInliningCandidate() const { return !neverInline(); }
346 bool isOkToOptimize() const { return !neverOptimize(); }
348 bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
350 CodeFeatures features() const { return m_features; }
354 void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
356 m_features = features;
357 m_hasCapturedVariables = hasCapturedVariables;
358 m_firstLine = firstLine;
359 m_lastLine = lastLine;
360 ASSERT(startColumn != UINT_MAX);
361 m_startColumn = startColumn;
362 ASSERT(endColumn != UINT_MAX);
363 m_endColumn = endColumn;
366 void installCode(CodeBlock*);
367 void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
368 CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
369 CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
371 // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
372 // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
373 // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
374 // their CodeBlock*& reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing
375 // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked
376 // by conservative GC if a GC happens after we create the CodeBlock.
377 template <typename ExecutableType>
378 JSObject* prepareForExecution(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock);
380 template <typename Functor> void forEachCodeBlock(Functor&&);
383 friend class ExecutableBase;
384 JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
387 ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
389 void finishCreation(VM& vm)
391 Base::finishCreation(vm);
392 vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
394 #if ENABLE(CODEBLOCK_SAMPLING)
395 if (SamplingTool* sampler = vm.interpreter->sampler())
396 sampler->notifyOfScope(vm, this);
400 CodeFeatures m_features;
401 bool m_didTryToEnterInLoop;
402 bool m_hasCapturedVariables : 1;
403 bool m_neverInline : 1;
404 bool m_neverOptimize : 1;
405 bool m_neverFTLOptimize : 1;
406 bool m_isArrowFunctionContext : 1;
407 unsigned m_derivedContextType : 2; // DerivedContextType
408 unsigned m_evalContextType : 2; // EvalContextType
410 int m_overrideLineNumber;
413 unsigned m_startColumn;
414 unsigned m_endColumn;
415 unsigned m_typeProfilingStartOffset;
416 unsigned m_typeProfilingEndOffset;
420 class EvalExecutable final : public ScriptExecutable {
421 friend class LLIntOffsetsExtractor;
423 typedef ScriptExecutable Base;
424 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
426 static void destroy(JSCell*);
428 EvalCodeBlock* codeBlock()
430 return m_evalCodeBlock.get();
433 static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);
435 PassRefPtr<JITCode> generatedJITCode()
437 return generatedJITCodeForCall();
440 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
442 return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
447 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); }
449 unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
450 unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
453 friend class ExecutableBase;
454 friend class ScriptExecutable;
456 EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
458 static void visitChildren(JSCell*, SlotVisitor&);
460 WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
461 WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
464 class ProgramExecutable final : public ScriptExecutable {
465 friend class LLIntOffsetsExtractor;
467 typedef ScriptExecutable Base;
468 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
470 static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
472 ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
473 executable->finishCreation(exec->vm());
478 JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
480 static void destroy(JSCell*);
482 ProgramCodeBlock* codeBlock()
484 return m_programCodeBlock.get();
487 JSObject* checkSyntax(ExecState*);
489 PassRefPtr<JITCode> generatedJITCode()
491 return generatedJITCodeForCall();
494 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
496 return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
501 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }
504 friend class ExecutableBase;
505 friend class ScriptExecutable;
507 ProgramExecutable(ExecState*, const SourceCode&);
509 static void visitChildren(JSCell*, SlotVisitor&);
511 WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
512 WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
515 class ModuleProgramExecutable final : public ScriptExecutable {
516 friend class LLIntOffsetsExtractor;
518 typedef ScriptExecutable Base;
519 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
521 static ModuleProgramExecutable* create(ExecState*, const SourceCode&);
523 static void destroy(JSCell*);
525 ModuleProgramCodeBlock* codeBlock()
527 return m_moduleProgramCodeBlock.get();
530 PassRefPtr<JITCode> generatedJITCode()
532 return generatedJITCodeForCall();
535 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
537 return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info());
542 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }
544 UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
546 SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
549 friend class ExecutableBase;
550 friend class ScriptExecutable;
552 ModuleProgramExecutable(ExecState*, const SourceCode&);
554 static void visitChildren(JSCell*, SlotVisitor&);
556 WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
557 WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
558 WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
561 class FunctionExecutable final : public ScriptExecutable {
563 friend class LLIntOffsetsExtractor;
565 typedef ScriptExecutable Base;
566 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
568 static FunctionExecutable* create(
569 VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable,
570 unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic intrinsic)
572 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, intrinsic);
573 executable->finishCreation(vm);
576 static FunctionExecutable* fromGlobalCode(
577 const Identifier& name, ExecState&, const SourceCode&,
578 JSObject*& exception, int overrideLineNumber);
580 static void destroy(JSCell*);
582 UnlinkedFunctionExecutable* unlinkedExecutable() const
584 return m_unlinkedExecutable.get();
587 // Returns either call or construct bytecode. This can be appropriate
588 // for answering questions that that don't vary between call and construct --
589 // for example, argumentsRegister().
590 FunctionCodeBlock* eitherCodeBlock()
592 if (m_codeBlockForCall)
593 return m_codeBlockForCall.get();
594 return m_codeBlockForConstruct.get();
597 bool isGeneratedForCall() const
599 return !!m_codeBlockForCall;
602 FunctionCodeBlock* codeBlockForCall()
604 return m_codeBlockForCall.get();
607 bool isGeneratedForConstruct() const
609 return m_codeBlockForConstruct.get();
612 FunctionCodeBlock* codeBlockForConstruct()
614 return m_codeBlockForConstruct.get();
617 bool isGeneratedFor(CodeSpecializationKind kind)
619 if (kind == CodeForCall)
620 return isGeneratedForCall();
621 ASSERT(kind == CodeForConstruct);
622 return isGeneratedForConstruct();
625 FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
627 if (kind == CodeForCall)
628 return codeBlockForCall();
629 ASSERT(kind == CodeForConstruct);
630 return codeBlockForConstruct();
633 FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
635 FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
637 return baselineCodeBlockFor(kind);
640 RefPtr<TypeSet> returnStatementTypeSet()
642 if (!m_returnStatementTypeSet)
643 m_returnStatementTypeSet = TypeSet::create();
645 return m_returnStatementTypeSet;
648 FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
649 bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
650 ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
651 bool isClass() const { return !classSource().isNull(); }
652 bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
653 bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
654 bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
655 DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
656 bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
657 const Identifier& name() { return m_unlinkedExecutable->name(); }
658 const Identifier& ecmaName() { return m_unlinkedExecutable->ecmaName(); }
659 const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
660 size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
661 SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
662 const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); }
664 static void visitChildren(JSCell*, SlotVisitor&);
665 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
667 return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
670 unsigned parametersStartOffset() const { return m_parametersStartOffset; }
672 void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
674 m_parametersStartOffset = parametersStartOffset;
675 m_typeProfilingStartOffset = typeProfilingStartOffset;
676 m_typeProfilingEndOffset = typeProfilingEndOffset;
681 InferredValue* singletonFunction() { return m_singletonFunction.get(); }
684 friend class ExecutableBase;
686 VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine,
687 unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic);
689 void finishCreation(VM&);
691 friend class ScriptExecutable;
693 unsigned m_parametersStartOffset;
694 WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
695 WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
696 WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
697 RefPtr<TypeSet> m_returnStatementTypeSet;
698 WriteBarrier<InferredValue> m_singletonFunction;
701 #if ENABLE(WEBASSEMBLY)
702 class WebAssemblyExecutable final : public ExecutableBase {
704 typedef ExecutableBase Base;
705 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
707 static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)
709 WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);
710 executable->finishCreation(vm);
714 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
716 return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
719 static void destroy(JSCell*);
723 void prepareForExecution(ExecState*);
725 WebAssemblyCodeBlock* codeBlockForCall()
727 return m_codeBlockForCall.get();
731 friend class ExecutableBase;
732 WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
734 static void visitChildren(JSCell*, SlotVisitor&);
737 WriteBarrier<JSWASMModule> m_module;
738 unsigned m_functionIndex;
740 WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
744 template <typename ExecutableType>
745 JSObject* ScriptExecutable::prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)
747 if (hasJITCodeFor(kind)) {
748 if (std::is_same<ExecutableType, EvalExecutable>::value)
749 resultCodeBlock = jsCast<CodeBlock*>(jsCast<EvalExecutable*>(this)->codeBlock());
750 else if (std::is_same<ExecutableType, ProgramExecutable>::value)
751 resultCodeBlock = jsCast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->codeBlock());
752 else if (std::is_same<ExecutableType, ModuleProgramExecutable>::value)
753 resultCodeBlock = jsCast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->codeBlock());
754 else if (std::is_same<ExecutableType, FunctionExecutable>::value)
755 resultCodeBlock = jsCast<CodeBlock*>(jsCast<FunctionExecutable*>(this)->codeBlockFor(kind));
757 RELEASE_ASSERT_NOT_REACHED();
760 return prepareForExecutionImpl(exec, function, scope, kind, resultCodeBlock);
765 #endif // Executable_h