b506b1c754f03d50658020768b4f69f287eee3be
[WebKit-https.git] / Source / JavaScriptCore / runtime / Executable.h
1 /*
2  * Copyright (C) 2009, 2010, 2013-2016 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 #ifndef Executable_h
27 #define Executable_h
28
29 #include "ArityCheckMode.h"
30 #include "CallData.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"
37 #include "JITCode.h"
38 #include "JSGlobalObject.h"
39 #include "SourceCode.h"
40 #include "TypeSet.h"
41 #include "UnlinkedCodeBlock.h"
42 #include "UnlinkedFunctionExecutable.h"
43
44 namespace JSC {
45
46 class CodeBlock;
47 class Debugger;
48 class EvalCodeBlock;
49 class FunctionCodeBlock;
50 class JSScope;
51 class JSWASMModule;
52 class LLIntOffsetsExtractor;
53 class ProgramCodeBlock;
54 class ModuleProgramCodeBlock;
55 class JSScope;
56 class WebAssemblyCodeBlock;
57 class ModuleProgramCodeBlock;
58 class JSModuleRecord;
59 class JSScope;
60
61 enum CompilationKind { FirstCompilation, OptimizingCompilation };
62
63 inline bool isCall(CodeSpecializationKind kind)
64 {
65     if (kind == CodeForCall)
66         return true;
67     ASSERT(kind == CodeForConstruct);
68     return false;
69 }
70
71 class ExecutableBase : public JSCell {
72     friend class JIT;
73
74 protected:
75     static const int NUM_PARAMETERS_IS_HOST = 0;
76     static const int NUM_PARAMETERS_NOT_COMPILED = -1;
77
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)
83     {
84     }
85
86     void finishCreation(VM& vm)
87     {
88         Base::finishCreation(vm);
89     }
90
91 public:
92     typedef JSCell Base;
93     static const unsigned StructureFlags = Base::StructureFlags;
94
95     static const bool needsDestruction = true;
96     static void destroy(JSCell*);
97         
98     CodeBlockHash hashFor(CodeSpecializationKind) const;
99
100     bool isEvalExecutable() const
101     {
102         return type() == EvalExecutableType;
103     }
104     bool isFunctionExecutable() const
105     {
106         return type() == FunctionExecutableType;
107     }
108     bool isProgramExecutable() const
109     {
110         return type() == ProgramExecutableType;
111     }
112     bool isModuleProgramExecutable()
113     {
114         return type() == ModuleProgramExecutableType;
115     }
116
117
118     bool isHostFunction() const
119     {
120         ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
121         return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
122     }
123
124 #if ENABLE(WEBASSEMBLY)
125     bool isWebAssemblyExecutable() const
126     {
127         return type() == WebAssemblyExecutableType;
128     }
129 #endif
130
131     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
132         
133     void clearCode();
134
135     DECLARE_EXPORT_INFO;
136
137 protected:
138     int m_numParametersForCall;
139     int m_numParametersForConstruct;
140
141 public:
142     PassRefPtr<JITCode> generatedJITCodeForCall()
143     {
144         ASSERT(m_jitCodeForCall);
145         return m_jitCodeForCall;
146     }
147
148     PassRefPtr<JITCode> generatedJITCodeForConstruct()
149     {
150         ASSERT(m_jitCodeForConstruct);
151         return m_jitCodeForConstruct;
152     }
153         
154     PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
155     {
156         if (kind == CodeForCall)
157             return generatedJITCodeForCall();
158         ASSERT(kind == CodeForConstruct);
159         return generatedJITCodeForConstruct();
160     }
161     
162     MacroAssemblerCodePtr entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity)
163     {
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
166         // machine code.
167         if (arity == MustCheckArity) {
168             switch (kind) {
169             case CodeForCall:
170                 if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
171                     return result;
172                 break;
173             case CodeForConstruct:
174                 if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
175                     return result;
176                 break;
177             }
178         }
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.
183             switch (kind) {
184             case CodeForCall:
185                 m_jitCodeForCallWithArityCheck = result;
186                 break;
187             case CodeForConstruct:
188                 m_jitCodeForConstructWithArityCheck = result;
189                 break;
190             }
191         }
192         return result;
193     }
194
195     static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
196         CodeSpecializationKind kind)
197     {
198         switch (kind) {
199         case CodeForCall:
200             return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
201         case CodeForConstruct:
202             return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
203         }
204         RELEASE_ASSERT_NOT_REACHED();
205         return 0;
206     }
207     
208     static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
209     {
210         if (kind == CodeForCall)
211             return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
212         ASSERT(kind == CodeForConstruct);
213         return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
214     }
215
216     bool hasJITCodeForCall() const
217     {
218         return m_numParametersForCall >= 0;
219     }
220         
221     bool hasJITCodeForConstruct() const
222     {
223         return m_numParametersForConstruct >= 0;
224     }
225         
226     bool hasJITCodeFor(CodeSpecializationKind kind) const
227     {
228         if (kind == CodeForCall)
229             return hasJITCodeForCall();
230         ASSERT(kind == CodeForConstruct);
231         return hasJITCodeForConstruct();
232     }
233
234     // Intrinsics are only for calls, currently.
235     Intrinsic intrinsic() const { return m_intrinsic; }
236         
237     Intrinsic intrinsicFor(CodeSpecializationKind kind) const
238     {
239         if (isCall(kind))
240             return intrinsic();
241         return NoIntrinsic;
242     }
243     
244     void dump(PrintStream&) const;
245         
246 protected:
247     Intrinsic m_intrinsic;
248     RefPtr<JITCode> m_jitCodeForCall;
249     RefPtr<JITCode> m_jitCodeForConstruct;
250     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
251     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
252 };
253
254 class NativeExecutable final : public ExecutableBase {
255     friend class JIT;
256     friend class LLIntOffsetsExtractor;
257 public:
258     typedef ExecutableBase Base;
259     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
260
261     static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name);
262
263     static void destroy(JSCell*);
264
265     CodeBlockHash hashFor(CodeSpecializationKind) const;
266
267     NativeFunction function() { return m_function; }
268     NativeFunction constructor() { return m_constructor; }
269         
270     NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
271     {
272         if (kind == CodeForCall)
273             return function();
274         ASSERT(kind == CodeForConstruct);
275         return constructor();
276     }
277         
278     static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
279     {
280         if (kind == CodeForCall)
281             return OBJECT_OFFSETOF(NativeExecutable, m_function);
282         ASSERT(kind == CodeForConstruct);
283         return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
284     }
285
286     static Structure* createStructure(VM&, JSGlobalObject*, JSValue proto);
287         
288     DECLARE_INFO;
289
290     const String& name() const { return m_name; }
291
292 protected:
293     void finishCreation(VM&, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, const String& name);
294
295 private:
296     friend class ExecutableBase;
297
298     NativeExecutable(VM&, NativeFunction function, NativeFunction constructor, Intrinsic);
299
300     NativeFunction m_function;
301     NativeFunction m_constructor;
302
303     String m_name;
304 };
305
306 class ScriptExecutable : public ExecutableBase {
307 public:
308     typedef ExecutableBase Base;
309     static const unsigned StructureFlags = Base::StructureFlags;
310
311     static void destroy(JSCell*);
312         
313     CodeBlockHash hashFor(CodeSpecializationKind) const;
314
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; }
327
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); }
334
335     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
336         
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(); }
347     
348     bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
349
350     CodeFeatures features() const { return m_features; }
351         
352     DECLARE_EXPORT_INFO;
353
354     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
355     {
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;
364     }
365
366     void installCode(CodeBlock*);
367     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
368     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
369     CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
370
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);
379
380     template <typename Functor> void forEachCodeBlock(Functor&&);
381
382 private:
383     friend class ExecutableBase;
384     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
385
386 protected:
387     ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, EvalContextType, Intrinsic);
388
389     void finishCreation(VM& vm)
390     {
391         Base::finishCreation(vm);
392         vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
393
394 #if ENABLE(CODEBLOCK_SAMPLING)
395         if (SamplingTool* sampler = vm.interpreter->sampler())
396             sampler->notifyOfScope(vm, this);
397 #endif
398     }
399
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
409
410     int m_overrideLineNumber;
411     int m_firstLine;
412     int m_lastLine;
413     unsigned m_startColumn;
414     unsigned m_endColumn;
415     unsigned m_typeProfilingStartOffset;
416     unsigned m_typeProfilingEndOffset;
417     SourceCode m_source;
418 };
419
420 class EvalExecutable final : public ScriptExecutable {
421     friend class LLIntOffsetsExtractor;
422 public:
423     typedef ScriptExecutable Base;
424     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
425
426     static void destroy(JSCell*);
427
428     EvalCodeBlock* codeBlock()
429     {
430         return m_evalCodeBlock.get();
431     }
432
433     static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType, const VariableEnvironment*);
434
435     PassRefPtr<JITCode> generatedJITCode()
436     {
437         return generatedJITCodeForCall();
438     }
439
440     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
441     {
442         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
443     }
444         
445     DECLARE_INFO;
446
447     ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); }
448
449     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
450     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
451
452 private:
453     friend class ExecutableBase;
454     friend class ScriptExecutable;
455
456     EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
457
458     static void visitChildren(JSCell*, SlotVisitor&);
459
460     WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
461     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
462 };
463
464 class ProgramExecutable final : public ScriptExecutable {
465     friend class LLIntOffsetsExtractor;
466 public:
467     typedef ScriptExecutable Base;
468     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
469
470     static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
471     {
472         ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
473         executable->finishCreation(exec->vm());
474         return executable;
475     }
476
477
478     JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
479
480     static void destroy(JSCell*);
481
482     ProgramCodeBlock* codeBlock()
483     {
484         return m_programCodeBlock.get();
485     }
486
487     JSObject* checkSyntax(ExecState*);
488
489     PassRefPtr<JITCode> generatedJITCode()
490     {
491         return generatedJITCodeForCall();
492     }
493         
494     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
495     {
496         return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
497     }
498         
499     DECLARE_INFO;
500
501     ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }
502
503 private:
504     friend class ExecutableBase;
505     friend class ScriptExecutable;
506
507     ProgramExecutable(ExecState*, const SourceCode&);
508
509     static void visitChildren(JSCell*, SlotVisitor&);
510
511     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
512     WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
513 };
514
515 class ModuleProgramExecutable final : public ScriptExecutable {
516     friend class LLIntOffsetsExtractor;
517 public:
518     typedef ScriptExecutable Base;
519     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
520
521     static ModuleProgramExecutable* create(ExecState*, const SourceCode&);
522
523     static void destroy(JSCell*);
524
525     ModuleProgramCodeBlock* codeBlock()
526     {
527         return m_moduleProgramCodeBlock.get();
528     }
529
530     PassRefPtr<JITCode> generatedJITCode()
531     {
532         return generatedJITCodeForCall();
533     }
534
535     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
536     {
537         return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info());
538     }
539
540     DECLARE_INFO;
541
542     ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); }
543
544     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
545
546     SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
547
548 private:
549     friend class ExecutableBase;
550     friend class ScriptExecutable;
551
552     ModuleProgramExecutable(ExecState*, const SourceCode&);
553
554     static void visitChildren(JSCell*, SlotVisitor&);
555
556     WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
557     WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
558     WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
559 };
560
561 class FunctionExecutable final : public ScriptExecutable {
562     friend class JIT;
563     friend class LLIntOffsetsExtractor;
564 public:
565     typedef ScriptExecutable Base;
566     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
567
568     static FunctionExecutable* create(
569         VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
570         unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic intrinsic)
571     {
572         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, intrinsic);
573         executable->finishCreation(vm);
574         return executable;
575     }
576     static FunctionExecutable* fromGlobalCode(
577         const Identifier& name, ExecState&, const SourceCode&, 
578         JSObject*& exception, int overrideLineNumber);
579
580     static void destroy(JSCell*);
581         
582     UnlinkedFunctionExecutable* unlinkedExecutable() const
583     {
584         return m_unlinkedExecutable.get();
585     }
586
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()
591     {
592         if (m_codeBlockForCall)
593             return m_codeBlockForCall.get();
594         return m_codeBlockForConstruct.get();
595     }
596         
597     bool isGeneratedForCall() const
598     {
599         return !!m_codeBlockForCall;
600     }
601
602     FunctionCodeBlock* codeBlockForCall()
603     {
604         return m_codeBlockForCall.get();
605     }
606
607     bool isGeneratedForConstruct() const
608     {
609         return m_codeBlockForConstruct.get();
610     }
611
612     FunctionCodeBlock* codeBlockForConstruct()
613     {
614         return m_codeBlockForConstruct.get();
615     }
616         
617     bool isGeneratedFor(CodeSpecializationKind kind)
618     {
619         if (kind == CodeForCall)
620             return isGeneratedForCall();
621         ASSERT(kind == CodeForConstruct);
622         return isGeneratedForConstruct();
623     }
624         
625     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
626     {
627         if (kind == CodeForCall)
628             return codeBlockForCall();
629         ASSERT(kind == CodeForConstruct);
630         return codeBlockForConstruct();
631     }
632
633     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
634         
635     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
636     {
637         return baselineCodeBlockFor(kind);
638     }
639
640     RefPtr<TypeSet> returnStatementTypeSet() 
641     {
642         if (!m_returnStatementTypeSet)
643             m_returnStatementTypeSet = TypeSet::create();
644
645         return m_returnStatementTypeSet;
646     }
647         
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(); }
663
664     static void visitChildren(JSCell*, SlotVisitor&);
665     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
666     {
667         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
668     }
669
670     unsigned parametersStartOffset() const { return m_parametersStartOffset; }
671
672     void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
673     {
674         m_parametersStartOffset = parametersStartOffset;
675         m_typeProfilingStartOffset = typeProfilingStartOffset;
676         m_typeProfilingEndOffset = typeProfilingEndOffset;
677     }
678
679     DECLARE_INFO;
680
681     InferredValue* singletonFunction() { return m_singletonFunction.get(); }
682
683 private:
684     friend class ExecutableBase;
685     FunctionExecutable(
686         VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, 
687         unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic);
688     
689     void finishCreation(VM&);
690
691     friend class ScriptExecutable;
692     
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;
699 };
700
701 #if ENABLE(WEBASSEMBLY)
702 class WebAssemblyExecutable final : public ExecutableBase {
703 public:
704     typedef ExecutableBase Base;
705     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
706
707     static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)
708     {
709         WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);
710         executable->finishCreation(vm);
711         return executable;
712     }
713
714     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
715     {
716         return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
717     }
718
719     static void destroy(JSCell*);
720
721     DECLARE_INFO;
722
723     void prepareForExecution(ExecState*);
724
725     WebAssemblyCodeBlock* codeBlockForCall()
726     {
727         return m_codeBlockForCall.get();
728     }
729
730 private:
731     friend class ExecutableBase;
732     WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
733
734     static void visitChildren(JSCell*, SlotVisitor&);
735
736     SourceCode m_source;
737     WriteBarrier<JSWASMModule> m_module;
738     unsigned m_functionIndex;
739
740     WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
741 };
742 #endif
743
744 template <typename ExecutableType>
745 JSObject* ScriptExecutable::prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)
746 {
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));
756         else
757             RELEASE_ASSERT_NOT_REACHED();
758         return nullptr;
759     }
760     return prepareForExecutionImpl(exec, function, scope, kind, resultCodeBlock);
761 }
762
763 } // namespace JSC
764
765 #endif // Executable_h