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