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