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