]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Executable.h
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / runtime / Executable.h
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 "CallData.h"
30 #include "CodeBlockHash.h"
31 #include "CodeSpecializationKind.h"
32 #include "HandlerInfo.h"
33 #include "JSFunction.h"
34 #include "Interpreter.h"
35 #include "JITCode.h"
36 #include "JSGlobalObject.h"
37 #include "LLIntCLoop.h"
38 #include "SamplingTool.h"
39 #include "SourceCode.h"
40 #include "UnlinkedCodeBlock.h"
41 #include <wtf/PassOwnPtr.h>
42
43 namespace JSC {
44
45 class CodeBlock;
46 class Debugger;
47 class EvalCodeBlock;
48 class FunctionCodeBlock;
49 class LLIntOffsetsExtractor;
50 class ProgramCodeBlock;
51 class JSScope;
52
53 enum CompilationKind { FirstCompilation, OptimizingCompilation };
54
55 inline bool isCall(CodeSpecializationKind kind)
56 {
57 if (kind == CodeForCall)
58 return true;
59 ASSERT(kind == CodeForConstruct);
60 return false;
61 }
62
63 class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
64 friend class WTF::DoublyLinkedListNode<ExecutableBase>;
65 friend class JIT;
66
67 protected:
68 static const int NUM_PARAMETERS_IS_HOST = 0;
69 static const int NUM_PARAMETERS_NOT_COMPILED = -1;
70
71 ExecutableBase(VM& vm, Structure* structure, int numParameters)
72 : JSCell(vm, structure)
73 , m_numParametersForCall(numParameters)
74 , m_numParametersForConstruct(numParameters)
75 {
76 }
77
78 void finishCreation(VM& vm)
79 {
80 Base::finishCreation(vm);
81 }
82
83 public:
84 typedef JSCell Base;
85
86 #if ENABLE(JIT)
87 static const bool needsDestruction = true;
88 static const bool hasImmortalStructure = true;
89 static void destroy(JSCell*);
90 #endif
91
92 CodeBlockHash hashFor(CodeSpecializationKind) const;
93
94 bool isFunctionExecutable()
95 {
96 return structure()->typeInfo().type() == FunctionExecutableType;
97 }
98
99 bool isHostFunction() const
100 {
101 ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
102 return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
103 }
104
105 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
106
107 void clearCode();
108
109 static JS_EXPORTDATA const ClassInfo s_info;
110
111 protected:
112 static const unsigned StructureFlags = 0;
113 int m_numParametersForCall;
114 int m_numParametersForConstruct;
115
116 public:
117 static void clearCodeVirtual(ExecutableBase*);
118
119 #if ENABLE(JIT)
120 JITCode& generatedJITCodeForCall()
121 {
122 ASSERT(m_jitCodeForCall);
123 return m_jitCodeForCall;
124 }
125
126 JITCode& generatedJITCodeForConstruct()
127 {
128 ASSERT(m_jitCodeForConstruct);
129 return m_jitCodeForConstruct;
130 }
131
132 JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
133 {
134 if (kind == CodeForCall)
135 return generatedJITCodeForCall();
136 ASSERT(kind == CodeForConstruct);
137 return generatedJITCodeForConstruct();
138 }
139
140 MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
141 {
142 ASSERT(m_jitCodeForCall);
143 ASSERT(m_jitCodeForCallWithArityCheck);
144 return m_jitCodeForCallWithArityCheck;
145 }
146
147 MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
148 {
149 ASSERT(m_jitCodeForConstruct);
150 ASSERT(m_jitCodeForConstructWithArityCheck);
151 return m_jitCodeForConstructWithArityCheck;
152 }
153
154 MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
155 {
156 if (kind == CodeForCall)
157 return generatedJITCodeForCallWithArityCheck();
158 ASSERT(kind == CodeForConstruct);
159 return generatedJITCodeForConstructWithArityCheck();
160 }
161
162 bool hasJITCodeForCall() const
163 {
164 return m_numParametersForCall >= 0;
165 }
166
167 bool hasJITCodeForConstruct() const
168 {
169 return m_numParametersForConstruct >= 0;
170 }
171
172 bool hasJITCodeFor(CodeSpecializationKind kind) const
173 {
174 if (kind == CodeForCall)
175 return hasJITCodeForCall();
176 ASSERT(kind == CodeForConstruct);
177 return hasJITCodeForConstruct();
178 }
179
180 static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind)
181 {
182 if (kind == CodeForCall)
183 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCall);
184 ASSERT(kind == CodeForConstruct);
185 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstruct);
186 }
187
188 static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
189 {
190 if (kind == CodeForCall)
191 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
192 ASSERT(kind == CodeForConstruct);
193 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
194 }
195
196 static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
197 {
198 if (kind == CodeForCall)
199 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
200 ASSERT(kind == CodeForConstruct);
201 return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
202 }
203 #endif // ENABLE(JIT)
204
205 // Intrinsics are only for calls, currently.
206 Intrinsic intrinsic() const;
207
208 Intrinsic intrinsicFor(CodeSpecializationKind kind) const
209 {
210 if (isCall(kind))
211 return intrinsic();
212 return NoIntrinsic;
213 }
214
215 #if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
216 MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
217 {
218 #if ENABLE(JIT)
219 return generatedJITCodeFor(kind).addressForCall();
220 #else
221 return LLInt::CLoop::hostCodeEntryFor(kind);
222 #endif
223 }
224
225 MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
226 {
227 #if ENABLE(JIT)
228 return generatedJITCodeFor(kind).addressForCall();
229 #else
230 return LLInt::CLoop::jsCodeEntryFor(kind);
231 #endif
232 }
233
234 MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
235 {
236 #if ENABLE(JIT)
237 return generatedJITCodeWithArityCheckFor(kind);
238 #else
239 return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind);
240 #endif
241 }
242
243 static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
244 {
245 #if ENABLE(JIT)
246 UNUSED_PARAM(catchPCForInterpreter);
247 return handler->nativeCode.executableAddress();
248 #else
249 UNUSED_PARAM(handler);
250 return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
251 #endif
252 }
253 #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
254
255 protected:
256 ExecutableBase* m_prev;
257 ExecutableBase* m_next;
258
259 #if ENABLE(JIT)
260 JITCode m_jitCodeForCall;
261 JITCode m_jitCodeForConstruct;
262 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
263 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
264 #endif
265 };
266
267 class NativeExecutable : public ExecutableBase {
268 friend class JIT;
269 friend class LLIntOffsetsExtractor;
270 public:
271 typedef ExecutableBase Base;
272
273 #if ENABLE(JIT)
274 static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
275 {
276 NativeExecutable* executable;
277 if (!callThunk) {
278 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
279 executable->finishCreation(vm, JITCode(), JITCode(), intrinsic);
280 } else {
281 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
282 executable->finishCreation(vm, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
283 }
284 return executable;
285 }
286 #endif
287
288 #if ENABLE(LLINT_C_LOOP)
289 static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
290 {
291 ASSERT(!vm.canUseJIT());
292 NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
293 executable->finishCreation(vm);
294 return executable;
295 }
296 #endif
297
298 #if ENABLE(JIT)
299 static void destroy(JSCell*);
300 #endif
301
302 CodeBlockHash hashFor(CodeSpecializationKind) const;
303
304 NativeFunction function() { return m_function; }
305 NativeFunction constructor() { return m_constructor; }
306
307 NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
308 {
309 if (kind == CodeForCall)
310 return function();
311 ASSERT(kind == CodeForConstruct);
312 return constructor();
313 }
314
315 static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
316 {
317 if (kind == CodeForCall)
318 return OBJECT_OFFSETOF(NativeExecutable, m_function);
319 ASSERT(kind == CodeForConstruct);
320 return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
321 }
322
323 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
324
325 static const ClassInfo s_info;
326
327 Intrinsic intrinsic() const;
328
329 protected:
330 #if ENABLE(JIT)
331 void finishCreation(VM& vm, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
332 {
333 Base::finishCreation(vm);
334 m_jitCodeForCall = callThunk;
335 m_jitCodeForConstruct = constructThunk;
336 m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
337 m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
338 m_intrinsic = intrinsic;
339 }
340 #endif
341
342 private:
343 NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
344 : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
345 , m_function(function)
346 , m_constructor(constructor)
347 {
348 }
349
350 NativeFunction m_function;
351 NativeFunction m_constructor;
352
353 Intrinsic m_intrinsic;
354 };
355
356 class ScriptExecutable : public ExecutableBase {
357 public:
358 typedef ExecutableBase Base;
359
360 ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
361 : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
362 , m_source(source)
363 , m_features(isInStrictContext ? StrictModeFeature : 0)
364 {
365 }
366
367 ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
368 : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
369 , m_source(source)
370 , m_features(isInStrictContext ? StrictModeFeature : 0)
371 {
372 }
373
374 #if ENABLE(JIT)
375 static void destroy(JSCell*);
376 #endif
377
378 CodeBlockHash hashFor(CodeSpecializationKind) const;
379
380 const SourceCode& source() const { return m_source; }
381 intptr_t sourceID() const { return m_source.providerID(); }
382 const String& sourceURL() const { return m_source.provider()->url(); }
383 int lineNo() const { return m_firstLine; }
384 int lastLine() const { return m_lastLine; }
385 unsigned startColumn() const { return m_startColumn; }
386
387 bool usesEval() const { return m_features & EvalFeature; }
388 bool usesArguments() const { return m_features & ArgumentsFeature; }
389 bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
390 bool isStrictMode() const { return m_features & StrictModeFeature; }
391
392 void unlinkCalls();
393
394 CodeFeatures features() const { return m_features; }
395
396 static const ClassInfo s_info;
397
398 void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
399 {
400 m_features = features;
401 m_hasCapturedVariables = hasCapturedVariables;
402 m_firstLine = firstLine;
403 m_lastLine = lastLine;
404 m_startColumn = startColumn;
405 }
406
407 protected:
408 void finishCreation(VM& vm)
409 {
410 Base::finishCreation(vm);
411 vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
412
413 #if ENABLE(CODEBLOCK_SAMPLING)
414 if (SamplingTool* sampler = vm.interpreter->sampler())
415 sampler->notifyOfScope(vm, this);
416 #endif
417 }
418
419 SourceCode m_source;
420 CodeFeatures m_features;
421 bool m_hasCapturedVariables;
422 int m_firstLine;
423 int m_lastLine;
424 unsigned m_startColumn;
425 };
426
427 class EvalExecutable : public ScriptExecutable {
428 friend class LLIntOffsetsExtractor;
429 public:
430 typedef ScriptExecutable Base;
431
432 static void destroy(JSCell*);
433
434 JSObject* compile(ExecState* exec, JSScope* scope)
435 {
436 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
437 JSObject* error = 0;
438 if (!m_evalCodeBlock)
439 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
440 ASSERT(!error == !!m_evalCodeBlock);
441 return error;
442 }
443
444 JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
445
446 #if ENABLE(JIT)
447 void jettisonOptimizedCode(VM&);
448 bool jitCompile(ExecState*);
449 #endif
450
451 EvalCodeBlock& generatedBytecode()
452 {
453 ASSERT(m_evalCodeBlock);
454 return *m_evalCodeBlock;
455 }
456
457 static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
458 {
459 EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
460 executable->finishCreation(exec->vm());
461 return executable;
462 }
463
464 #if ENABLE(JIT)
465 JITCode& generatedJITCode()
466 {
467 return generatedJITCodeForCall();
468 }
469 #endif
470 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
471 {
472 return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
473 }
474
475 static const ClassInfo s_info;
476
477 void unlinkCalls();
478
479 void clearCode();
480
481 ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
482
483 private:
484 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
485 EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
486
487 JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
488 static void visitChildren(JSCell*, SlotVisitor&);
489
490 OwnPtr<EvalCodeBlock> m_evalCodeBlock;
491 WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
492 RefPtr<CodeCache> m_codeCache;
493 };
494
495 class ProgramExecutable : public ScriptExecutable {
496 friend class LLIntOffsetsExtractor;
497 public:
498 typedef ScriptExecutable Base;
499
500 static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
501 {
502 ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
503 executable->finishCreation(exec->vm());
504 return executable;
505 }
506
507
508 JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
509
510 static void destroy(JSCell*);
511
512 JSObject* compile(ExecState* exec, JSScope* scope)
513 {
514 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
515 JSObject* error = 0;
516 if (!m_programCodeBlock)
517 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
518 ASSERT(!error == !!m_programCodeBlock);
519 return error;
520 }
521
522 JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
523
524 #if ENABLE(JIT)
525 void jettisonOptimizedCode(VM&);
526 bool jitCompile(ExecState*);
527 #endif
528
529 ProgramCodeBlock& generatedBytecode()
530 {
531 ASSERT(m_programCodeBlock);
532 return *m_programCodeBlock;
533 }
534
535 JSObject* checkSyntax(ExecState*);
536
537 #if ENABLE(JIT)
538 JITCode& generatedJITCode()
539 {
540 return generatedJITCodeForCall();
541 }
542 #endif
543
544 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
545 {
546 return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
547 }
548
549 static const ClassInfo s_info;
550
551 void unlinkCalls();
552
553 void clearCode();
554
555 ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
556
557 private:
558 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
559
560 ProgramExecutable(ExecState*, const SourceCode&);
561
562 enum ConstantMode { IsConstant, IsVariable };
563 enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
564 int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
565
566 JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
567 static void visitChildren(JSCell*, SlotVisitor&);
568
569 WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
570 OwnPtr<ProgramCodeBlock> m_programCodeBlock;
571 };
572
573 class FunctionExecutable : public ScriptExecutable {
574 friend class JIT;
575 friend class LLIntOffsetsExtractor;
576 public:
577 typedef ScriptExecutable Base;
578
579 static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
580 {
581 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
582 executable->finishCreation(vm);
583 return executable;
584 }
585 static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
586
587 static void destroy(JSCell*);
588
589 UnlinkedFunctionExecutable* unlinkedExecutable()
590 {
591 return m_unlinkedExecutable.get();
592 }
593
594 // Returns either call or construct bytecode. This can be appropriate
595 // for answering questions that that don't vary between call and construct --
596 // for example, argumentsRegister().
597 FunctionCodeBlock& generatedBytecode()
598 {
599 if (m_codeBlockForCall)
600 return *m_codeBlockForCall;
601 ASSERT(m_codeBlockForConstruct);
602 return *m_codeBlockForConstruct;
603 }
604
605 PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
606
607 JSObject* compileForCall(ExecState* exec, JSScope* scope)
608 {
609 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
610 JSObject* error = 0;
611 if (!m_codeBlockForCall)
612 error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
613 ASSERT(!error == !!m_codeBlockForCall);
614 return error;
615 }
616
617 JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex);
618
619 #if ENABLE(JIT)
620 void jettisonOptimizedCodeForCall(VM&);
621 bool jitCompileForCall(ExecState*);
622 #endif
623
624 bool isGeneratedForCall() const
625 {
626 return m_codeBlockForCall;
627 }
628
629 FunctionCodeBlock& generatedBytecodeForCall()
630 {
631 ASSERT(m_codeBlockForCall);
632 return *m_codeBlockForCall;
633 }
634
635 JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
636 {
637 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
638 JSObject* error = 0;
639 if (!m_codeBlockForConstruct)
640 error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
641 ASSERT(!error == !!m_codeBlockForConstruct);
642 return error;
643 }
644
645 JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex);
646
647 #if ENABLE(JIT)
648 void jettisonOptimizedCodeForConstruct(VM&);
649 bool jitCompileForConstruct(ExecState*);
650 #endif
651
652 bool isGeneratedForConstruct() const
653 {
654 return m_codeBlockForConstruct;
655 }
656
657 FunctionCodeBlock& generatedBytecodeForConstruct()
658 {
659 ASSERT(m_codeBlockForConstruct);
660 return *m_codeBlockForConstruct;
661 }
662
663 JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
664 {
665 ASSERT(exec->callee());
666 ASSERT(exec->callee()->inherits(&JSFunction::s_info));
667 ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
668
669 if (kind == CodeForCall)
670 return compileForCall(exec, scope);
671 ASSERT(kind == CodeForConstruct);
672 return compileForConstruct(exec, scope);
673 }
674
675 JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, unsigned bytecodeIndex, CodeSpecializationKind kind)
676 {
677 ASSERT(exec->callee());
678 ASSERT(exec->callee()->inherits(&JSFunction::s_info));
679 ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
680
681 if (kind == CodeForCall)
682 return compileOptimizedForCall(exec, scope, bytecodeIndex);
683 ASSERT(kind == CodeForConstruct);
684 return compileOptimizedForConstruct(exec, scope, bytecodeIndex);
685 }
686
687
688 #if ENABLE(JIT)
689 void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
690 {
691 if (kind == CodeForCall)
692 jettisonOptimizedCodeForCall(vm);
693 else {
694 ASSERT(kind == CodeForConstruct);
695 jettisonOptimizedCodeForConstruct(vm);
696 }
697 }
698
699 bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
700 {
701 if (kind == CodeForCall)
702 return jitCompileForCall(exec);
703 ASSERT(kind == CodeForConstruct);
704 return jitCompileForConstruct(exec);
705 }
706 #endif
707
708 bool isGeneratedFor(CodeSpecializationKind kind)
709 {
710 if (kind == CodeForCall)
711 return isGeneratedForCall();
712 ASSERT(kind == CodeForConstruct);
713 return isGeneratedForConstruct();
714 }
715
716 FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
717 {
718 if (kind == CodeForCall)
719 return generatedBytecodeForCall();
720 ASSERT(kind == CodeForConstruct);
721 return generatedBytecodeForConstruct();
722 }
723
724 FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
725
726 FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
727 {
728 return baselineCodeBlockFor(kind);
729 }
730
731 const Identifier& name() { return m_unlinkedExecutable->name(); }
732 const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
733 JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
734 size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
735 String paramString() const;
736 SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
737
738 void clearCodeIfNotCompiling();
739 void clearUnlinkedCodeForRecompilationIfNotCompiling();
740 static void visitChildren(JSCell*, SlotVisitor&);
741 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
742 {
743 return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
744 }
745
746 static const ClassInfo s_info;
747
748 void unlinkCalls();
749
750 void clearCode();
751
752 private:
753 FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
754
755 JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
756 JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
757
758 OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
759 {
760 if (kind == CodeForCall)
761 return m_codeBlockForCall;
762 ASSERT(kind == CodeForConstruct);
763 return m_codeBlockForConstruct;
764 }
765
766 bool isCompiling()
767 {
768 #if ENABLE(JIT)
769 if (!m_jitCodeForCall && m_codeBlockForCall)
770 return true;
771 if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
772 return true;
773 #endif
774 return false;
775 }
776
777 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
778 WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
779 OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
780 OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
781 };
782
783 inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
784 : Base(vm, scope->globalObject()->functionStructure())
785 , m_executable(vm, this, executable)
786 , m_scope(vm, this, scope)
787 , m_allocationProfileWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
788 {
789 }
790
791 inline FunctionExecutable* JSFunction::jsExecutable() const
792 {
793 ASSERT(!isHostFunctionNonInline());
794 return static_cast<FunctionExecutable*>(m_executable.get());
795 }
796
797 inline bool JSFunction::isHostFunction() const
798 {
799 ASSERT(m_executable);
800 return m_executable->isHostFunction();
801 }
802
803 inline NativeFunction JSFunction::nativeFunction()
804 {
805 ASSERT(isHostFunction());
806 return static_cast<NativeExecutable*>(m_executable.get())->function();
807 }
808
809 inline NativeFunction JSFunction::nativeConstructor()
810 {
811 ASSERT(isHostFunction());
812 return static_cast<NativeExecutable*>(m_executable.get())->constructor();
813 }
814
815 inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
816 {
817 JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
818 if (!function || !function->isHostFunction())
819 return false;
820 return function->nativeFunction() == nativeFunction;
821 }
822
823 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
824 {
825 switch (executable->structure()->typeInfo().type()) {
826 case EvalExecutableType:
827 return jsCast<EvalExecutable*>(executable)->clearCode();
828 case ProgramExecutableType:
829 return jsCast<ProgramExecutable*>(executable)->clearCode();
830 case FunctionExecutableType:
831 return jsCast<FunctionExecutable*>(executable)->clearCode();
832 default:
833 return jsCast<NativeExecutable*>(executable)->clearCode();
834 }
835 }
836
837 inline void ScriptExecutable::unlinkCalls()
838 {
839 switch (structure()->typeInfo().type()) {
840 case EvalExecutableType:
841 return jsCast<EvalExecutable*>(this)->unlinkCalls();
842 case ProgramExecutableType:
843 return jsCast<ProgramExecutable*>(this)->unlinkCalls();
844 case FunctionExecutableType:
845 return jsCast<FunctionExecutable*>(this)->unlinkCalls();
846 default:
847 RELEASE_ASSERT_NOT_REACHED();
848 }
849 }
850
851 }
852
853 #endif