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
45namespace JSC {
46
47class CodeBlock;
48class Debugger;
49class EvalCodeBlock;
50class FunctionCodeBlock;
51class JSScope;
52class JSWASMModule;
53class LLIntOffsetsExtractor;
54class ProgramCodeBlock;
55class ModuleProgramCodeBlock;
56class JSScope;
57class WebAssemblyCodeBlock;
58class ModuleProgramCodeBlock;
59class JSModuleRecord;
60class JSScope;
61
62enum CompilationKind { FirstCompilation, OptimizingCompilation };
63
64inline bool isCall(CodeSpecializationKind kind)
65{
66 if (kind == CodeForCall)
67 return true;
68 ASSERT(kind == CodeForConstruct);
69 return false;
70}
71
72class ExecutableBase : public JSCell {
73 friend class JIT;
74
75protected:
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
91public:
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
137protected:
138 int m_numParametersForCall;
139 int m_numParametersForConstruct;
140
141public:
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
246protected:
247 RefPtr<JITCode> m_jitCodeForCall;
248 RefPtr<JITCode> m_jitCodeForConstruct;
249 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
250 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
251};
252
253class NativeExecutable final : public ExecutableBase {
254 friend class JIT;
255 friend class LLIntOffsetsExtractor;
256public:
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, const String& name)
261 {
262 NativeExecutable* executable;
263 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
264 executable->finishCreation(vm, callThunk, constructThunk, intrinsic, name);
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 const String& name() const { return m_name; }
298
299protected:
300 void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic, const String& name)
301 {
302 Base::finishCreation(vm);
303 m_jitCodeForCall = callThunk;
304 m_jitCodeForConstruct = constructThunk;
305 m_intrinsic = intrinsic;
306 m_name = name;
307 }
308
309private:
310 friend class ExecutableBase;
311
312 NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
313 : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
314 , m_function(function)
315 , m_constructor(constructor)
316 {
317 }
318
319 NativeFunction m_function;
320 NativeFunction m_constructor;
321
322 Intrinsic m_intrinsic;
323
324 String m_name;
325};
326
327class ScriptExecutable : public ExecutableBase {
328public:
329 typedef ExecutableBase Base;
330 static const unsigned StructureFlags = Base::StructureFlags;
331
332 static void destroy(JSCell*);
333
334 CodeBlockHash hashFor(CodeSpecializationKind) const;
335
336 const SourceCode& source() const { return m_source; }
337 intptr_t sourceID() const { return m_source.providerID(); }
338 const String& sourceURL() const { return m_source.provider()->url(); }
339 int firstLine() const { return m_firstLine; }
340 void setOverrideLineNumber(int overrideLineNumber) { m_overrideLineNumber = overrideLineNumber; }
341 bool hasOverrideLineNumber() const { return m_overrideLineNumber != -1; }
342 int overrideLineNumber() const { return m_overrideLineNumber; }
343 int lastLine() const { return m_lastLine; }
344 unsigned startColumn() const { return m_startColumn; }
345 unsigned endColumn() const { return m_endColumn; }
346 unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
347 unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
348
349 bool usesEval() const { return m_features & EvalFeature; }
350 bool usesArguments() const { return m_features & ArgumentsFeature; }
351 bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
352 bool isStrictMode() const { return m_features & StrictModeFeature; }
353 DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
354
355 ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
356
357 void setNeverInline(bool value) { m_neverInline = value; }
358 void setNeverOptimize(bool value) { m_neverOptimize = value; }
359 void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
360 bool neverInline() const { return m_neverInline; }
361 bool neverOptimize() const { return m_neverOptimize; }
362 bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
363 bool isInliningCandidate() const { return !neverInline(); }
364 bool isOkToOptimize() const { return !neverOptimize(); }
365
366 bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
367
368 CodeFeatures features() const { return m_features; }
369
370 DECLARE_EXPORT_INFO;
371
372 void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
373 {
374 m_features = features;
375 m_hasCapturedVariables = hasCapturedVariables;
376 m_firstLine = firstLine;
377 m_lastLine = lastLine;
378 ASSERT(startColumn != UINT_MAX);
379 m_startColumn = startColumn;
380 ASSERT(endColumn != UINT_MAX);
381 m_endColumn = endColumn;
382 }
383
384 void installCode(CodeBlock*);
385 void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
386 CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
387 CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
388
389 JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
390 {
391 if (hasJITCodeFor(kind))
392 return 0;
393 return prepareForExecutionImpl(exec, function, scope, kind);
394 }
395
396 template <typename Functor> void forEachCodeBlock(Functor&&);
397
398private:
399 friend class ExecutableBase;
400 JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
401
402protected:
403 ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext);
404
405 void finishCreation(VM& vm)
406 {
407 Base::finishCreation(vm);
408 vm.heap.addExecutable(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
409
410#if ENABLE(CODEBLOCK_SAMPLING)
411 if (SamplingTool* sampler = vm.interpreter->sampler())
412 sampler->notifyOfScope(vm, this);
413#endif
414 }
415
416 CodeFeatures m_features;
417 bool m_didTryToEnterInLoop;
418 bool m_hasCapturedVariables : 1;
419 bool m_neverInline : 1;
420 bool m_neverOptimize : 1;
421 bool m_isArrowFunctionContext : 1;
422 unsigned m_derivedContextType : 2; // DerivedContextType
423
424 int m_overrideLineNumber;
425 int m_firstLine;
426 int m_lastLine;
427 unsigned m_startColumn;
428 unsigned m_endColumn;
429 unsigned m_typeProfilingStartOffset;
430 unsigned m_typeProfilingEndOffset;
431 SourceCode m_source;
432};
433
434class EvalExecutable final : public ScriptExecutable {
435 friend class LLIntOffsetsExtractor;
436public:
437 typedef ScriptExecutable Base;
438 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
439
440 static void destroy(JSCell*);
441
442 EvalCodeBlock* codeBlock()
443 {
444 return m_evalCodeBlock.get();
445 }
446
447 static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, DerivedContextType, bool isArrowFunctionContext, const VariableEnvironment*);
448
449 PassRefPtr<JITCode> generatedJITCode()
450 {
451 return generatedJITCodeForCall();
452 }
453
454 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
455 {
456 return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
457 }
458
459 DECLARE_INFO;
460
461 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext() , false); }
462
463 unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
464 unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
465
466private:
467 friend class ExecutableBase;
468 friend class ScriptExecutable;
469
470 EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext);
471
472 static void visitChildren(JSCell*, SlotVisitor&);
473
474 WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
475 WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
476};
477
478class ProgramExecutable final : public ScriptExecutable {
479 friend class LLIntOffsetsExtractor;
480public:
481 typedef ScriptExecutable Base;
482 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
483
484 static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
485 {
486 ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
487 executable->finishCreation(exec->vm());
488 return executable;
489 }
490
491
492 JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
493
494 static void destroy(JSCell*);
495
496 ProgramCodeBlock* codeBlock()
497 {
498 return m_programCodeBlock.get();
499 }
500
501 JSObject* checkSyntax(ExecState*);
502
503 PassRefPtr<JITCode> generatedJITCode()
504 {
505 return generatedJITCodeForCall();
506 }
507
508 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
509 {
510 return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
511 }
512
513 DECLARE_INFO;
514
515 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false); }
516
517private:
518 friend class ExecutableBase;
519 friend class ScriptExecutable;
520
521 ProgramExecutable(ExecState*, const SourceCode&);
522
523 static void visitChildren(JSCell*, SlotVisitor&);
524
525 WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
526 WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
527};
528
529class ModuleProgramExecutable final : public ScriptExecutable {
530 friend class LLIntOffsetsExtractor;
531public:
532 typedef ScriptExecutable Base;
533 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
534
535 static ModuleProgramExecutable* create(ExecState*, const SourceCode&);
536
537 static void destroy(JSCell*);
538
539 ModuleProgramCodeBlock* codeBlock()
540 {
541 return m_moduleProgramCodeBlock.get();
542 }
543
544 PassRefPtr<JITCode> generatedJITCode()
545 {
546 return generatedJITCodeForCall();
547 }
548
549 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
550 {
551 return Structure::create(vm, globalObject, proto, TypeInfo(ModuleProgramExecutableType, StructureFlags), info());
552 }
553
554 DECLARE_INFO;
555
556 ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false); }
557
558 UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
559
560 SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
561
562private:
563 friend class ExecutableBase;
564 friend class ScriptExecutable;
565
566 ModuleProgramExecutable(ExecState*, const SourceCode&);
567
568 static void visitChildren(JSCell*, SlotVisitor&);
569
570 WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
571 WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
572 WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
573};
574
575class FunctionExecutable final : public ScriptExecutable {
576 friend class JIT;
577 friend class LLIntOffsetsExtractor;
578public:
579 typedef ScriptExecutable Base;
580 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
581
582 static FunctionExecutable* create(
583 VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable,
584 unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn)
585 {
586 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn);
587 executable->finishCreation(vm);
588 return executable;
589 }
590 static FunctionExecutable* fromGlobalCode(
591 const Identifier& name, ExecState&, const SourceCode&,
592 JSObject*& exception, int overrideLineNumber);
593
594 static void destroy(JSCell*);
595
596 UnlinkedFunctionExecutable* unlinkedExecutable() const
597 {
598 return m_unlinkedExecutable.get();
599 }
600
601 // Returns either call or construct bytecode. This can be appropriate
602 // for answering questions that that don't vary between call and construct --
603 // for example, argumentsRegister().
604 FunctionCodeBlock* eitherCodeBlock()
605 {
606 if (m_codeBlockForCall)
607 return m_codeBlockForCall.get();
608 return m_codeBlockForConstruct.get();
609 }
610
611 bool isGeneratedForCall() const
612 {
613 return !!m_codeBlockForCall;
614 }
615
616 FunctionCodeBlock* codeBlockForCall()
617 {
618 return m_codeBlockForCall.get();
619 }
620
621 bool isGeneratedForConstruct() const
622 {
623 return m_codeBlockForConstruct.get();
624 }
625
626 FunctionCodeBlock* codeBlockForConstruct()
627 {
628 return m_codeBlockForConstruct.get();
629 }
630
631 bool isGeneratedFor(CodeSpecializationKind kind)
632 {
633 if (kind == CodeForCall)
634 return isGeneratedForCall();
635 ASSERT(kind == CodeForConstruct);
636 return isGeneratedForConstruct();
637 }
638
639 FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
640 {
641 if (kind == CodeForCall)
642 return codeBlockForCall();
643 ASSERT(kind == CodeForConstruct);
644 return codeBlockForConstruct();
645 }
646
647 FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
648
649 FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
650 {
651 return baselineCodeBlockFor(kind);
652 }
653
654 RefPtr<TypeSet> returnStatementTypeSet()
655 {
656 if (!m_returnStatementTypeSet)
657 m_returnStatementTypeSet = TypeSet::create();
658
659 return m_returnStatementTypeSet;
660 }
661
662 FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
663 bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
664 ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
665 bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
666 DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
667 bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
668 const Identifier& name() { return m_unlinkedExecutable->name(); }
669 const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
670 JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
671 size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
672 SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
673
674 static void visitChildren(JSCell*, SlotVisitor&);
675 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
676 {
677 return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
678 }
679
680 unsigned parametersStartOffset() const { return m_parametersStartOffset; }
681
682 void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
683 {
684 m_parametersStartOffset = parametersStartOffset;
685 m_typeProfilingStartOffset = typeProfilingStartOffset;
686 m_typeProfilingEndOffset = typeProfilingEndOffset;
687 }
688
689 DECLARE_INFO;
690
691 InferredValue* singletonFunction() { return m_singletonFunction.get(); }
692
693private:
694 friend class ExecutableBase;
695 FunctionExecutable(
696 VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine,
697 unsigned lastLine, unsigned startColumn, unsigned endColumn);
698
699 void finishCreation(VM&);
700
701 friend class ScriptExecutable;
702
703 unsigned m_parametersStartOffset;
704 WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
705 WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
706 WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
707 RefPtr<TypeSet> m_returnStatementTypeSet;
708 WriteBarrier<InferredValue> m_singletonFunction;
709};
710
711#if ENABLE(WEBASSEMBLY)
712class WebAssemblyExecutable final : public ExecutableBase {
713public:
714 typedef ExecutableBase Base;
715 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
716
717 static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)
718 {
719 WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);
720 executable->finishCreation(vm);
721 return executable;
722 }
723
724 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
725 {
726 return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());
727 }
728
729 static void destroy(JSCell*);
730
731 DECLARE_INFO;
732
733 void prepareForExecution(ExecState*);
734
735 WebAssemblyCodeBlock* codeBlockForCall()
736 {
737 return m_codeBlockForCall.get();
738 }
739
740private:
741 friend class ExecutableBase;
742 WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
743
744 static void visitChildren(JSCell*, SlotVisitor&);
745
746 SourceCode m_source;
747 WriteBarrier<JSWASMModule> m_module;
748 unsigned m_functionIndex;
749
750 WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
751};
752#endif
753
754} // namespace JSC
755
756#endif // Executable_h
757