[ES6] "super" and "this" should be lexically bound inside an arrow function and shoul...
[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     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;
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     RefPtr<JITCode> m_jitCodeForCall;
248     RefPtr<JITCode> m_jitCodeForConstruct;
249     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
250     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
251 };
252
253 class NativeExecutable final : public ExecutableBase {
254     friend class JIT;
255     friend class LLIntOffsetsExtractor;
256 public:
257     typedef ExecutableBase Base;
258     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
259
260     static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic)
261     {
262         NativeExecutable* executable;
263         executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
264         executable->finishCreation(vm, callThunk, constructThunk, intrinsic);
265         return executable;
266     }
267
268     static void destroy(JSCell*);
269
270     CodeBlockHash hashFor(CodeSpecializationKind) const;
271
272     NativeFunction function() { return m_function; }
273     NativeFunction constructor() { return m_constructor; }
274         
275     NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
276     {
277         if (kind == CodeForCall)
278             return function();
279         ASSERT(kind == CodeForConstruct);
280         return constructor();
281     }
282         
283     static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
284     {
285         if (kind == CodeForCall)
286             return OBJECT_OFFSETOF(NativeExecutable, m_function);
287         ASSERT(kind == CodeForConstruct);
288         return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
289     }
290
291     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
292         
293     DECLARE_INFO;
294
295     Intrinsic intrinsic() const;
296
297 protected:
298     void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
299     {
300         Base::finishCreation(vm);
301         m_jitCodeForCall = callThunk;
302         m_jitCodeForConstruct = constructThunk;
303         m_intrinsic = intrinsic;
304     }
305
306 private:
307     friend class ExecutableBase;
308
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 isArrowFunctionContext() const { return m_isArrowFunctionContext; }
348     bool isStrictMode() const { return m_features & StrictModeFeature; }
349     bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
350     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
351         
352     void setNeverInline(bool value) { m_neverInline = value; }
353     void setNeverOptimize(bool value) { m_neverOptimize = value; }
354     void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
355     bool neverInline() const { return m_neverInline; }
356     bool neverOptimize() const { return m_neverOptimize; }
357     bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
358     bool isInliningCandidate() const { return !neverInline(); }
359     bool isOkToOptimize() const { return !neverOptimize(); }
360     
361     bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
362
363     CodeFeatures features() const { return m_features; }
364         
365     DECLARE_EXPORT_INFO;
366
367     void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
368     {
369         m_features = features;
370         m_hasCapturedVariables = hasCapturedVariables;
371         m_firstLine = firstLine;
372         m_lastLine = lastLine;
373         ASSERT(startColumn != UINT_MAX);
374         m_startColumn = startColumn;
375         ASSERT(endColumn != UINT_MAX);
376         m_endColumn = endColumn;
377     }
378
379     void installCode(CodeBlock*);
380     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
381     CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
382     CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
383     
384     JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
385     {
386         if (hasJITCodeFor(kind))
387             return 0;
388         return prepareForExecutionImpl(exec, function, scope, kind);
389     }
390
391     template <typename Functor> void forEachCodeBlock(Functor&&);
392
393 private:
394     friend class ExecutableBase;
395     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
396
397 protected:
398     ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, bool isInDerivedConstructorContext, bool isInArrowFunctionContext);
399
400     void finishCreation(VM& vm)
401     {
402         Base::finishCreation(vm);
403         vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
404
405 #if ENABLE(CODEBLOCK_SAMPLING)
406         if (SamplingTool* sampler = vm.interpreter->sampler())
407             sampler->notifyOfScope(vm, this);
408 #endif
409     }
410
411     SourceCode m_source;
412     CodeFeatures m_features;
413     bool m_hasCapturedVariables;
414     bool m_neverInline;
415     bool m_neverOptimize { false };
416     bool m_didTryToEnterInLoop;
417     bool m_isDerivedConstructorContext;
418     bool m_isArrowFunctionContext;
419     int m_overrideLineNumber;
420     int m_firstLine;
421     int m_lastLine;
422     unsigned m_startColumn;
423     unsigned m_endColumn;
424     unsigned m_typeProfilingStartOffset;
425     unsigned m_typeProfilingEndOffset;
426 };
427
428 class EvalExecutable final : public ScriptExecutable {
429     friend class LLIntOffsetsExtractor;
430 public:
431     typedef ScriptExecutable Base;
432     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
433
434     static void destroy(JSCell*);
435
436     EvalCodeBlock* codeBlock()
437     {
438         return m_evalCodeBlock.get();
439     }
440
441     static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, bool isDerivedConstructorContext, bool isArrowFunctionContext, const VariableEnvironment*);
442
443     PassRefPtr<JITCode> generatedJITCode()
444     {
445         return generatedJITCodeForCall();
446     }
447
448     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
449     {
450         return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
451     }
452         
453     DECLARE_INFO;
454
455
456     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), isArrowFunctionContext()); }
457
458     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
459     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
460
461 private:
462     friend class ExecutableBase;
463     friend class ScriptExecutable;
464     EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, bool isDerivedConstructorContext, bool isArrowFunctionContext);
465
466     static void visitChildren(JSCell*, SlotVisitor&);
467
468     WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
469     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
470 };
471
472 class ProgramExecutable final : public ScriptExecutable {
473     friend class LLIntOffsetsExtractor;
474 public:
475     typedef ScriptExecutable Base;
476     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
477
478     static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
479     {
480         ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
481         executable->finishCreation(exec->vm());
482         return executable;
483     }
484
485
486     JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
487
488     static void destroy(JSCell*);
489
490     ProgramCodeBlock* codeBlock()
491     {
492         return m_programCodeBlock.get();
493     }
494
495     JSObject* checkSyntax(ExecState*);
496
497     PassRefPtr<JITCode> generatedJITCode()
498     {
499         return generatedJITCodeForCall();
500     }
501         
502     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
503     {
504         return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
505     }
506         
507     DECLARE_INFO;
508
509     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), false); }
510
511 private:
512     friend class ExecutableBase;
513     friend class ScriptExecutable;
514
515     ProgramExecutable(ExecState*, const SourceCode&);
516
517     static void visitChildren(JSCell*, SlotVisitor&);
518
519     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
520     WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
521 };
522
523 class ModuleProgramExecutable final : public ScriptExecutable {
524     friend class LLIntOffsetsExtractor;
525 public:
526     typedef ScriptExecutable Base;
527     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
528
529     static ModuleProgramExecutable* create(ExecState*, const SourceCode&);
530
531     static void destroy(JSCell*);
532
533     ModuleProgramCodeBlock* codeBlock()
534     {
535         return m_moduleProgramCodeBlock.get();
536     }
537
538     PassRefPtr<JITCode> generatedJITCode()
539     {
540         return generatedJITCodeForCall();
541     }
542
543     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
544     {
545         return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info());
546     }
547
548     DECLARE_INFO;
549
550     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, isDerivedConstructorContext(), false); }
551
552     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
553
554     SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
555
556 private:
557     friend class ExecutableBase;
558     friend class ScriptExecutable;
559
560     ModuleProgramExecutable(ExecState*, const SourceCode&);
561
562     static void visitChildren(JSCell*, SlotVisitor&);
563
564     WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
565     WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
566     WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
567 };
568
569 class FunctionExecutable final : public ScriptExecutable {
570     friend class JIT;
571     friend class LLIntOffsetsExtractor;
572 public:
573     typedef ScriptExecutable Base;
574     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
575
576     static FunctionExecutable* create(
577         VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
578         unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn)
579     {
580         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn);
581         executable->finishCreation(vm);
582         return executable;
583     }
584     static FunctionExecutable* fromGlobalCode(
585         const Identifier& name, ExecState&, const SourceCode&, 
586         JSObject*& exception, int overrideLineNumber);
587
588     static void destroy(JSCell*);
589         
590     UnlinkedFunctionExecutable* unlinkedExecutable() const
591     {
592         return m_unlinkedExecutable.get();
593     }
594
595     // Returns either call or construct bytecode. This can be appropriate
596     // for answering questions that that don't vary between call and construct --
597     // for example, argumentsRegister().
598     FunctionCodeBlock* eitherCodeBlock()
599     {
600         if (m_codeBlockForCall)
601             return m_codeBlockForCall.get();
602         return m_codeBlockForConstruct.get();
603     }
604         
605     bool isGeneratedForCall() const
606     {
607         return !!m_codeBlockForCall;
608     }
609
610     FunctionCodeBlock* codeBlockForCall()
611     {
612         return m_codeBlockForCall.get();
613     }
614
615     bool isGeneratedForConstruct() const
616     {
617         return m_codeBlockForConstruct.get();
618     }
619
620     FunctionCodeBlock* codeBlockForConstruct()
621     {
622         return m_codeBlockForConstruct.get();
623     }
624         
625     bool isGeneratedFor(CodeSpecializationKind kind)
626     {
627         if (kind == CodeForCall)
628             return isGeneratedForCall();
629         ASSERT(kind == CodeForConstruct);
630         return isGeneratedForConstruct();
631     }
632         
633     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
634     {
635         if (kind == CodeForCall)
636             return codeBlockForCall();
637         ASSERT(kind == CodeForConstruct);
638         return codeBlockForConstruct();
639     }
640
641     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
642         
643     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
644     {
645         return baselineCodeBlockFor(kind);
646     }
647
648     RefPtr<TypeSet> returnStatementTypeSet() 
649     {
650         if (!m_returnStatementTypeSet)
651             m_returnStatementTypeSet = TypeSet::create();
652
653         return m_returnStatementTypeSet;
654     }
655         
656     FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
657     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
658     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
659     // TODO:Think about avoid using isArrowFunction veriabl
660     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
661     bool isDerivedConstructorContext() const { return m_unlinkedExecutable->isDerivedConstructorContext(); }
662     bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
663     const Identifier& name() { return m_unlinkedExecutable->name(); }
664     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
665     JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
666     size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
667     SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
668
669     static void visitChildren(JSCell*, SlotVisitor&);
670     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
671     {
672         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
673     }
674
675     unsigned parametersStartOffset() const { return m_parametersStartOffset; }
676
677     void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
678     {
679         m_parametersStartOffset = parametersStartOffset;
680         m_typeProfilingStartOffset = typeProfilingStartOffset;
681         m_typeProfilingEndOffset = typeProfilingEndOffset;
682     }
683
684     DECLARE_INFO;
685
686     InferredValue* singletonFunction() { return m_singletonFunction.get(); }
687
688 private:
689     friend class ExecutableBase;
690     FunctionExecutable(
691         VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, 
692         unsigned lastLine, unsigned startColumn, unsigned endColumn);
693     
694     void finishCreation(VM&);
695
696     friend class ScriptExecutable;
697     
698     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
699     WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
700     WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
701     RefPtr<TypeSet> m_returnStatementTypeSet;
702     unsigned m_parametersStartOffset;
703     WriteBarrier<InferredValue> m_singletonFunction;
704 };
705
706 #if ENABLE(WEBASSEMBLY)
707 class WebAssemblyExecutable final : public ExecutableBase {
708 public:
709     typedef ExecutableBase Base;
710     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
711
712     static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)
713     {
714         WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);
715         executable->finishCreation(vm);
716         return executable;
717     }
718
719     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
720     {
721         return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
722     }
723
724     static void destroy(JSCell*);
725
726     DECLARE_INFO;
727
728     void prepareForExecution(ExecState*);
729
730     WebAssemblyCodeBlock* codeBlockForCall()
731     {
732         return m_codeBlockForCall.get();
733     }
734
735 private:
736     friend class ExecutableBase;
737     WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
738
739     static void visitChildren(JSCell*, SlotVisitor&);
740
741     SourceCode m_source;
742     WriteBarrier<JSWASMModule> m_module;
743     unsigned m_functionIndex;
744
745     WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
746 };
747 #endif
748
749 } // namespace JSC
750
751 #endif // Executable_h