Create WebAssembly functions
[WebKit-https.git] / Source / JavaScriptCore / runtime / Executable.h
1 /*
2  * Copyright (C) 2009, 2010, 2013-2015 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 "DFGPlan.h"
35 #include "ExecutableInfo.h"
36 #include "HandlerInfo.h"
37 #include "InferredValue.h"
38 #include "JITCode.h"
39 #include "JSGlobalObject.h"
40 #include "RegisterPreservationMode.h"
41 #include "SamplingTool.h"
42 #include "SourceCode.h"
43 #include "TypeSet.h"
44 #include "UnlinkedCodeBlock.h"
45 #include "UnlinkedFunctionExecutable.h"
46
47 namespace JSC {
48
49 class CodeBlock;
50 class Debugger;
51 class EvalCodeBlock;
52 class FunctionCodeBlock;
53 class JSScope;
54 class JSWASMModule;
55 class LLIntOffsetsExtractor;
56 class ProgramCodeBlock;
57 class WebAssemblyCodeBlock;
58     
59 enum CompilationKind { FirstCompilation, OptimizingCompilation };
60
61 inline bool isCall(CodeSpecializationKind kind)
62 {
63     if (kind == CodeForCall)
64         return true;
65     ASSERT(kind == CodeForConstruct);
66     return false;
67 }
68
69 class ExecutableBase : public JSCell {
70     friend class JIT;
71
72 protected:
73     static const int NUM_PARAMETERS_IS_HOST = 0;
74     static const int NUM_PARAMETERS_NOT_COMPILED = -1;
75
76     ExecutableBase(VM& vm, Structure* structure, int numParameters)
77         : JSCell(vm, structure)
78         , m_numParametersForCall(numParameters)
79         , m_numParametersForConstruct(numParameters)
80     {
81     }
82
83     void finishCreation(VM& vm)
84     {
85         Base::finishCreation(vm);
86     }
87
88 public:
89     typedef JSCell Base;
90     static const unsigned StructureFlags = Base::StructureFlags;
91
92     static const bool needsDestruction = true;
93     static void destroy(JSCell*);
94         
95     CodeBlockHash hashFor(CodeSpecializationKind) const;
96
97     bool isEvalExecutable() const
98     {
99         return type() == EvalExecutableType;
100     }
101     bool isFunctionExecutable() const
102     {
103         return type() == FunctionExecutableType;
104     }
105     bool isProgramExecutable() const
106     {
107         return type() == ProgramExecutableType;
108     }
109
110     bool isHostFunction() const
111     {
112         ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
113         return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
114     }
115
116 #if ENABLE(WEBASSEMBLY)
117     bool isWebAssemblyExecutable() const
118     {
119         return type() == WebAssemblyExecutableType;
120     }
121 #endif
122
123     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
124         
125     void clearCode();
126
127     DECLARE_EXPORT_INFO;
128
129 protected:
130     int m_numParametersForCall;
131     int m_numParametersForConstruct;
132
133 public:
134     static void clearCodeVirtual(ExecutableBase*);
135
136     PassRefPtr<JITCode> generatedJITCodeForCall()
137     {
138         ASSERT(m_jitCodeForCall);
139         return m_jitCodeForCall;
140     }
141
142     PassRefPtr<JITCode> generatedJITCodeForConstruct()
143     {
144         ASSERT(m_jitCodeForConstruct);
145         return m_jitCodeForConstruct;
146     }
147         
148     PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
149     {
150         if (kind == CodeForCall)
151             return generatedJITCodeForCall();
152         ASSERT(kind == CodeForConstruct);
153         return generatedJITCodeForConstruct();
154     }
155     
156     MacroAssemblerCodePtr entrypointFor(
157         VM& vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers)
158     {
159         // Check if we have a cached result. We only have it for arity check because we use the
160         // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in
161         // machine code.
162         if (arity == MustCheckArity) {
163             switch (kind) {
164             case CodeForCall:
165                 switch (registers) {
166                 case RegisterPreservationNotRequired:
167                     if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
168                         return result;
169                     break;
170                 case MustPreserveRegisters:
171                     if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs)
172                         return result;
173                     break;
174                 }
175                 break;
176             case CodeForConstruct:
177                 switch (registers) {
178                 case RegisterPreservationNotRequired:
179                     if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
180                         return result;
181                     break;
182                 case MustPreserveRegisters:
183                     if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs)
184                         return result;
185                     break;
186                 }
187                 break;
188             }
189         }
190         MacroAssemblerCodePtr result =
191             generatedJITCodeFor(kind)->addressForCall(vm, this, arity, registers);
192         if (arity == MustCheckArity) {
193             // Cache the result; this is necessary for the JIT's virtual call optimizations.
194             switch (kind) {
195             case CodeForCall:
196                 switch (registers) {
197                 case RegisterPreservationNotRequired:
198                     m_jitCodeForCallWithArityCheck = result;
199                     break;
200                 case MustPreserveRegisters:
201                     m_jitCodeForCallWithArityCheckAndPreserveRegs = result;
202                     break;
203                 }
204                 break;
205             case CodeForConstruct:
206                 switch (registers) {
207                 case RegisterPreservationNotRequired:
208                     m_jitCodeForConstructWithArityCheck = result;
209                     break;
210                 case MustPreserveRegisters:
211                     m_jitCodeForConstructWithArityCheckAndPreserveRegs = result;
212                     break;
213                 }
214                 break;
215             }
216         }
217         return result;
218     }
219
220     static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
221         CodeSpecializationKind kind, RegisterPreservationMode registers)
222     {
223         switch (kind) {
224         case CodeForCall:
225             switch (registers) {
226             case RegisterPreservationNotRequired:
227                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
228             case MustPreserveRegisters:
229                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs);
230             }
231         case CodeForConstruct:
232             switch (registers) {
233             case RegisterPreservationNotRequired:
234                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
235             case MustPreserveRegisters:
236                 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs);
237             }
238         }
239         RELEASE_ASSERT_NOT_REACHED();
240         return 0;
241     }
242     
243     static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
244     {
245         if (kind == CodeForCall)
246             return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
247         ASSERT(kind == CodeForConstruct);
248         return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
249     }
250
251     bool hasJITCodeForCall() const
252     {
253         return m_numParametersForCall >= 0;
254     }
255         
256     bool hasJITCodeForConstruct() const
257     {
258         return m_numParametersForConstruct >= 0;
259     }
260         
261     bool hasJITCodeFor(CodeSpecializationKind kind) const
262     {
263         if (kind == CodeForCall)
264             return hasJITCodeForCall();
265         ASSERT(kind == CodeForConstruct);
266         return hasJITCodeForConstruct();
267     }
268
269     // Intrinsics are only for calls, currently.
270     Intrinsic intrinsic() const;
271         
272     Intrinsic intrinsicFor(CodeSpecializationKind kind) const
273     {
274         if (isCall(kind))
275             return intrinsic();
276         return NoIntrinsic;
277     }
278     
279     void dump(PrintStream&) const;
280         
281 protected:
282     RefPtr<JITCode> m_jitCodeForCall;
283     RefPtr<JITCode> m_jitCodeForConstruct;
284     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
285     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
286     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs;
287     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs;
288 };
289
290 class NativeExecutable final : public ExecutableBase {
291     friend class JIT;
292     friend class LLIntOffsetsExtractor;
293 public:
294     typedef ExecutableBase Base;
295     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
296
297     static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic)
298     {
299         NativeExecutable* executable;
300         executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
301         executable->finishCreation(vm, callThunk, constructThunk, intrinsic);
302         return executable;
303     }
304
305     static void destroy(JSCell*);
306
307     CodeBlockHash hashFor(CodeSpecializationKind) const;
308
309     NativeFunction function() { return m_function; }
310     NativeFunction constructor() { return m_constructor; }
311         
312     NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
313     {
314         if (kind == CodeForCall)
315             return function();
316         ASSERT(kind == CodeForConstruct);
317         return constructor();
318     }
319         
320     static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
321     {
322         if (kind == CodeForCall)
323             return OBJECT_OFFSETOF(NativeExecutable, m_function);
324         ASSERT(kind == CodeForConstruct);
325         return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
326     }
327
328     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
329         
330     DECLARE_INFO;
331
332     Intrinsic intrinsic() const;
333
334 protected:
335     void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
336     {
337         Base::finishCreation(vm);
338         m_jitCodeForCall = callThunk;
339         m_jitCodeForConstruct = constructThunk;
340         m_intrinsic = intrinsic;
341     }
342
343 private:
344     NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
345         : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
346         , m_function(function)
347         , m_constructor(constructor)
348     {
349     }
350
351     NativeFunction m_function;
352     NativeFunction m_constructor;
353         
354     Intrinsic m_intrinsic;
355 };
356
357 class ScriptExecutable : public ExecutableBase {
358 public:
359     typedef ExecutableBase Base;
360     static const unsigned StructureFlags = Base::StructureFlags;
361
362     static void destroy(JSCell*);
363         
364     CodeBlockHash hashFor(CodeSpecializationKind) const;
365
366     const SourceCode& source() const { return m_source; }
367     intptr_t sourceID() const { return m_source.providerID(); }
368     const String& sourceURL() const { return m_source.provider()->url(); }
369     int firstLine() const { return m_firstLine; }
370     void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; }
371     bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; }
372     int overrideLineNumber() const { return m_overrideLineNumber; }
373     int lastLine() const { return m_lastLine; }
374     unsigned startColumn() const { return m_startColumn; }
375     unsigned endColumn() const { return m_endColumn; }
376     unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
377     unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
378
379     bool usesEval() const { return m_features & EvalFeature; }
380     bool usesArguments() const { return m_features & ArgumentsFeature; }
381     bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
382     bool isStrictMode() const { return m_features & StrictModeFeature; }
383     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
384         
385     void setNeverInline(bool value) { m_neverInline = value; }
386     void setNeverOptimize(bool value) { m_neverOptimize = value; }
387     void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
388     bool neverInline() const { return m_neverInline; }
389     bool neverOptimize() const { return m_neverOptimize; }
390     bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
391     bool isInliningCandidate() const { return !neverInline(); }
392     bool isOkToOptimize() const { return !neverOptimize(); }
393     
394     bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
395
396     CodeFeatures features() const { return m_features; }
397         
398     DECLARE_EXPORT_INFO;
399
400     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
401     {
402         m_features = features;
403         m_hasCapturedVariables = hasCapturedVariables;
404         m_firstLine = firstLine;
405         m_lastLine = lastLine;
406         ASSERT(startColumn != UINT_MAX);
407         m_startColumn = startColumn;
408         ASSERT(endColumn != UINT_MAX);
409         m_endColumn = endColumn;
410     }
411
412     void installCode(CodeBlock*);
413     RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
414     PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
415     
416     JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
417     {
418         if (hasJITCodeFor(kind))
419             return 0;
420         return prepareForExecutionImpl(exec, function, scope, kind);
421     }
422
423     template <typename Functor> void forEachCodeBlock(Functor&&);
424
425 private:
426     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
427
428 protected:
429     ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext);
430
431     void finishCreation(VM& vm)
432     {
433         Base::finishCreation(vm);
434         vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
435
436 #if ENABLE(CODEBLOCK_SAMPLING)
437         if (SamplingTool* sampler = vm.interpreter->sampler())
438             sampler->notifyOfScope(vm, this);
439 #endif
440     }
441
442     SourceCode m_source;
443     CodeFeatures m_features;
444     bool m_hasCapturedVariables;
445     bool m_neverInline;
446     bool m_neverOptimize { false };
447     bool m_didTryToEnterInLoop;
448     int m_overrideLineNumber;
449     int m_firstLine;
450     int m_lastLine;
451     unsigned m_startColumn;
452     unsigned m_endColumn;
453     unsigned m_typeProfilingStartOffset;
454     unsigned m_typeProfilingEndOffset;
455 };
456
457 class EvalExecutable final : public ScriptExecutable {
458     friend class LLIntOffsetsExtractor;
459 public:
460     typedef ScriptExecutable Base;
461     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
462
463     static void destroy(JSCell*);
464
465     EvalCodeBlock* codeBlock()
466     {
467         return m_evalCodeBlock.get();
468     }
469
470     static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, const VariableEnvironment*);
471
472     PassRefPtr<JITCode> generatedJITCode()
473     {
474         return generatedJITCodeForCall();
475     }
476
477     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
478     {
479         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
480     }
481         
482     DECLARE_INFO;
483
484     void clearCode();
485
486     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
487
488     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
489     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
490
491 private:
492     friend class ScriptExecutable;
493     EvalExecutable(ExecState*, const SourceCode&, bool);
494
495     static void visitChildren(JSCell*, SlotVisitor&);
496
497     RefPtr<EvalCodeBlock> m_evalCodeBlock;
498     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
499 };
500
501 class ProgramExecutable final : public ScriptExecutable {
502     friend class LLIntOffsetsExtractor;
503 public:
504     typedef ScriptExecutable Base;
505     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
506
507     static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
508     {
509         ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
510         executable->finishCreation(exec->vm());
511         return executable;
512     }
513
514
515     JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
516
517     static void destroy(JSCell*);
518
519     ProgramCodeBlock* codeBlock()
520     {
521         return m_programCodeBlock.get();
522     }
523
524     JSObject* checkSyntax(ExecState*);
525
526     PassRefPtr<JITCode> generatedJITCode()
527     {
528         return generatedJITCodeForCall();
529     }
530         
531     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
532     {
533         return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
534     }
535         
536     DECLARE_INFO;
537
538     void clearCode();
539
540     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
541
542 private:
543     friend class ScriptExecutable;
544
545     ProgramExecutable(ExecState*, const SourceCode&);
546
547     static void visitChildren(JSCell*, SlotVisitor&);
548
549     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
550     RefPtr<ProgramCodeBlock> m_programCodeBlock;
551 };
552
553 class FunctionExecutable final : public ScriptExecutable {
554     friend class JIT;
555     friend class LLIntOffsetsExtractor;
556 public:
557     typedef ScriptExecutable Base;
558     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
559
560     static FunctionExecutable* create(
561         VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
562         unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn)
563     {
564         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn);
565         executable->finishCreation(vm);
566         return executable;
567     }
568     static FunctionExecutable* fromGlobalCode(
569         const Identifier& name, ExecState&, const SourceCode&, 
570         JSObject*& exception, int overrideLineNumber);
571
572     static void destroy(JSCell*);
573         
574     UnlinkedFunctionExecutable* unlinkedExecutable() const
575     {
576         return m_unlinkedExecutable.get();
577     }
578
579     // Returns either call or construct bytecode. This can be appropriate
580     // for answering questions that that don't vary between call and construct --
581     // for example, argumentsRegister().
582     FunctionCodeBlock* eitherCodeBlock()
583     {
584         if (m_codeBlockForCall)
585             return m_codeBlockForCall.get();
586         return m_codeBlockForConstruct.get();
587     }
588         
589     bool isGeneratedForCall() const
590     {
591         return m_codeBlockForCall;
592     }
593
594     FunctionCodeBlock* codeBlockForCall()
595     {
596         return m_codeBlockForCall.get();
597     }
598
599     bool isGeneratedForConstruct() const
600     {
601         return m_codeBlockForConstruct;
602     }
603
604     FunctionCodeBlock* codeBlockForConstruct()
605     {
606         return m_codeBlockForConstruct.get();
607     }
608         
609     bool isGeneratedFor(CodeSpecializationKind kind)
610     {
611         if (kind == CodeForCall)
612             return isGeneratedForCall();
613         ASSERT(kind == CodeForConstruct);
614         return isGeneratedForConstruct();
615     }
616         
617     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
618     {
619         if (kind == CodeForCall)
620             return codeBlockForCall();
621         ASSERT(kind == CodeForConstruct);
622         return codeBlockForConstruct();
623     }
624
625     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
626         
627     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
628     {
629         return baselineCodeBlockFor(kind);
630     }
631
632     RefPtr<TypeSet> returnStatementTypeSet() 
633     {
634         if (!m_returnStatementTypeSet)
635             m_returnStatementTypeSet = TypeSet::create();
636
637         return m_returnStatementTypeSet;
638     }
639         
640     FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
641     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
642     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
643     bool isArrowFunction() const { return m_unlinkedExecutable->isArrowFunction(); }
644     bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
645     const Identifier& name() { return m_unlinkedExecutable->name(); }
646     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
647     JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
648     size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
649
650     static void visitChildren(JSCell*, SlotVisitor&);
651     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
652     {
653         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
654     }
655
656     unsigned parametersStartOffset() const { return m_parametersStartOffset; }
657
658     void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
659     {
660         m_parametersStartOffset = parametersStartOffset;
661         m_typeProfilingStartOffset = typeProfilingStartOffset;
662         m_typeProfilingEndOffset = typeProfilingEndOffset;
663     }
664
665     DECLARE_INFO;
666
667     void clearCode();
668     
669     InferredValue* singletonFunction() { return m_singletonFunction.get(); }
670
671 private:
672     FunctionExecutable(
673         VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, 
674         unsigned lastLine, unsigned startColumn, unsigned endColumn);
675     
676     void finishCreation(VM&);
677
678     friend class ScriptExecutable;
679     
680     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
681     RefPtr<FunctionCodeBlock> m_codeBlockForCall;
682     RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
683     RefPtr<TypeSet> m_returnStatementTypeSet;
684     unsigned m_parametersStartOffset;
685     WriteBarrier<InferredValue> m_singletonFunction;
686 };
687
688 #if ENABLE(WEBASSEMBLY)
689 class WebAssemblyExecutable final : public ExecutableBase {
690 public:
691     typedef ExecutableBase Base;
692     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
693
694     static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)
695     {
696         WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);
697         executable->finishCreation(vm);
698         return executable;
699     }
700
701     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
702     {
703         return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
704     }
705
706     static void destroy(JSCell*);
707
708     DECLARE_INFO;
709
710     void clearCode();
711
712     void prepareForExecution(ExecState*);
713
714     WebAssemblyCodeBlock* codeBlockForCall()
715     {
716         return m_codeBlockForCall.get();
717     }
718
719 private:
720     WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
721
722     static void visitChildren(JSCell*, SlotVisitor&);
723
724     SourceCode m_source;
725     WriteBarrier<JSWASMModule> m_module;
726     unsigned m_functionIndex;
727
728     RefPtr<WebAssemblyCodeBlock> m_codeBlockForCall;
729 };
730 #endif
731
732 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
733 {
734     switch (executable->type()) {
735     case EvalExecutableType:
736         return jsCast<EvalExecutable*>(executable)->clearCode();
737     case ProgramExecutableType:
738         return jsCast<ProgramExecutable*>(executable)->clearCode();
739     case FunctionExecutableType:
740         return jsCast<FunctionExecutable*>(executable)->clearCode();
741 #if ENABLE(WEBASSEMBLY)
742     case WebAssemblyExecutableType:
743         return jsCast<WebAssemblyExecutable*>(executable)->clearCode();
744 #endif
745     default:
746         return jsCast<NativeExecutable*>(executable)->clearCode();
747     }
748 }
749
750 }
751
752 #endif