]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Executable.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / runtime / Executable.h
CommitLineData
f9bf01c6 1/*
14957cd0 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
f9bf01c6
A
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
14957cd0 29#include "CallData.h"
6fe7ccc8 30#include "CodeSpecializationKind.h"
f9bf01c6
A
31#include "JSFunction.h"
32#include "Interpreter.h"
33#include "Nodes.h"
34#include "SamplingTool.h"
14957cd0 35#include <wtf/PassOwnPtr.h>
f9bf01c6
A
36
37namespace JSC {
38
39 class CodeBlock;
40 class Debugger;
41 class EvalCodeBlock;
14957cd0 42 class FunctionCodeBlock;
6fe7ccc8 43 class LLIntOffsetsExtractor;
f9bf01c6
A
44 class ProgramCodeBlock;
45 class ScopeChainNode;
6fe7ccc8
A
46
47 enum CompilationKind { FirstCompilation, OptimizingCompilation };
f9bf01c6 48
6fe7ccc8
A
49 inline bool isCall(CodeSpecializationKind kind)
50 {
51 if (kind == CodeForCall)
52 return true;
53 ASSERT(kind == CodeForConstruct);
54 return false;
55 }
f9bf01c6 56
14957cd0 57 class ExecutableBase : public JSCell {
f9bf01c6
A
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;
6fe7ccc8 63
14957cd0
A
64 ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
65 : JSCell(globalData, structure)
66 , m_numParametersForCall(numParameters)
67 , m_numParametersForConstruct(numParameters)
f9bf01c6 68 {
6fe7ccc8
A
69 }
70
71 void finishCreation(JSGlobalData& globalData)
72 {
73 Base::finishCreation(globalData);
74 }
75
76 public:
77 typedef JSCell Base;
78
14957cd0 79#if ENABLE(JIT)
6fe7ccc8 80 static void destroy(JSCell*);
14957cd0 81#endif
f9bf01c6 82
14957cd0
A
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 }
f9bf01c6 88
6fe7ccc8 89 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
14957cd0 90
6fe7ccc8 91 static JS_EXPORTDATA const ClassInfo s_info;
f9bf01c6
A
92
93 protected:
14957cd0
A
94 static const unsigned StructureFlags = 0;
95 int m_numParametersForCall;
96 int m_numParametersForConstruct;
f9bf01c6
A
97
98#if ENABLE(JIT)
99 public:
14957cd0 100 JITCode& generatedJITCodeForCall()
f9bf01c6 101 {
14957cd0
A
102 ASSERT(m_jitCodeForCall);
103 return m_jitCodeForCall;
f9bf01c6
A
104 }
105
14957cd0 106 JITCode& generatedJITCodeForConstruct()
f9bf01c6 107 {
14957cd0
A
108 ASSERT(m_jitCodeForConstruct);
109 return m_jitCodeForConstruct;
110 }
6fe7ccc8
A
111
112 JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
113 {
114 if (kind == CodeForCall)
115 return generatedJITCodeForCall();
116 ASSERT(kind == CodeForConstruct);
117 return generatedJITCodeForConstruct();
118 }
14957cd0 119
6fe7ccc8 120 MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
14957cd0 121 {
6fe7ccc8
A
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;
f9bf01c6
A
168 }
169
170 protected:
14957cd0
A
171 JITCode m_jitCodeForCall;
172 JITCode m_jitCodeForConstruct;
173 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
174 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
f9bf01c6 175#endif
6fe7ccc8 176 void clearCode();
f9bf01c6
A
177 };
178
f9bf01c6 179 class NativeExecutable : public ExecutableBase {
14957cd0 180 friend class JIT;
6fe7ccc8 181 friend class LLIntOffsetsExtractor;
f9bf01c6 182 public:
6fe7ccc8
A
183 typedef ExecutableBase Base;
184
14957cd0 185#if ENABLE(JIT)
6fe7ccc8
A
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;
f9bf01c6 199 }
6fe7ccc8
A
200#endif
201
202#if ENABLE(CLASSIC_INTERPRETER)
14957cd0
A
203 static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
204 {
6fe7ccc8
A
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;
14957cd0
A
210 }
211#endif
f9bf01c6 212
6fe7ccc8
A
213#if ENABLE(JIT)
214 static void destroy(JSCell*);
215#endif
f9bf01c6 216
14957cd0 217 NativeFunction function() { return m_function; }
6fe7ccc8 218 NativeFunction constructor() { return m_constructor; }
14957cd0 219
6fe7ccc8 220 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
14957cd0
A
221
222 static const ClassInfo s_info;
6fe7ccc8
A
223
224 Intrinsic intrinsic() const;
225
226 protected:
14957cd0 227#if ENABLE(JIT)
6fe7ccc8 228 void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
14957cd0 229 {
6fe7ccc8
A
230 ASSERT(!globalData.interpreter->classicEnabled());
231 Base::finishCreation(globalData);
14957cd0
A
232 m_jitCodeForCall = callThunk;
233 m_jitCodeForConstruct = constructThunk;
234 m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
235 m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
6fe7ccc8
A
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;
14957cd0 246 }
6fe7ccc8
A
247#endif
248
249 static void finalize(JSCell*);
250
251 private:
14957cd0
A
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)
f9bf01c6
A
256 {
257 }
258
14957cd0 259 NativeFunction m_function;
14957cd0 260 NativeFunction m_constructor;
6fe7ccc8
A
261
262 Intrinsic m_intrinsic;
f9bf01c6
A
263 };
264
265 class ScriptExecutable : public ExecutableBase {
266 public:
6fe7ccc8
A
267 typedef ExecutableBase Base;
268
269 ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
270 : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
f9bf01c6 271 , m_source(source)
14957cd0 272 , m_features(isInStrictContext ? StrictModeFeature : 0)
f9bf01c6 273 {
f9bf01c6
A
274 }
275
14957cd0
A
276 ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
277 : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
f9bf01c6 278 , m_source(source)
14957cd0 279 , m_features(isInStrictContext ? StrictModeFeature : 0)
f9bf01c6 280 {
f9bf01c6
A
281 }
282
6fe7ccc8
A
283#if ENABLE(JIT)
284 static void destroy(JSCell*);
285#endif
286
f9bf01c6 287 const SourceCode& source() { return m_source; }
6fe7ccc8 288 intptr_t sourceID() const { return m_source.providerID(); }
f9bf01c6
A
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; }
14957cd0
A
295 bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
296 bool isStrictMode() const { return m_features & StrictModeFeature; }
f9bf01c6 297
6fe7ccc8 298 void unlinkCalls();
14957cd0
A
299
300 static const ClassInfo s_info;
6fe7ccc8 301
f9bf01c6 302 protected:
6fe7ccc8
A
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
14957cd0 312 void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
f9bf01c6
A
313 {
314 m_features = features;
14957cd0 315 m_hasCapturedVariables = hasCapturedVariables;
f9bf01c6
A
316 m_firstLine = firstLine;
317 m_lastLine = lastLine;
318 }
319
320 SourceCode m_source;
321 CodeFeatures m_features;
14957cd0 322 bool m_hasCapturedVariables;
f9bf01c6
A
323 int m_firstLine;
324 int m_lastLine;
325 };
326
327 class EvalExecutable : public ScriptExecutable {
6fe7ccc8 328 friend class LLIntOffsetsExtractor;
f9bf01c6 329 public:
6fe7ccc8 330 typedef ScriptExecutable Base;
f9bf01c6 331
6fe7ccc8 332 static void destroy(JSCell*);
f9bf01c6 333
14957cd0 334 JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
f9bf01c6 335 {
14957cd0
A
336 ASSERT(exec->globalData().dynamicGlobalObject);
337 JSObject* error = 0;
338 if (!m_evalCodeBlock)
6fe7ccc8 339 error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
14957cd0
A
340 ASSERT(!error == !!m_evalCodeBlock);
341 return error;
f9bf01c6 342 }
6fe7ccc8
A
343
344 JSObject* compileOptimized(ExecState*, ScopeChainNode*);
345
346#if ENABLE(JIT)
347 void jettisonOptimizedCode(JSGlobalData&);
348 bool jitCompile(JSGlobalData&);
349#endif
f9bf01c6 350
14957cd0 351 EvalCodeBlock& generatedBytecode()
f9bf01c6 352 {
14957cd0
A
353 ASSERT(m_evalCodeBlock);
354 return *m_evalCodeBlock;
f9bf01c6 355 }
14957cd0 356
6fe7ccc8
A
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 }
f9bf01c6
A
364
365#if ENABLE(JIT)
14957cd0 366 JITCode& generatedJITCode()
f9bf01c6 367 {
14957cd0 368 return generatedJITCodeForCall();
f9bf01c6 369 }
f9bf01c6 370#endif
6fe7ccc8 371 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
14957cd0 372 {
6fe7ccc8 373 return Structure::create(globalData, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
14957cd0
A
374 }
375
376 static const ClassInfo s_info;
6fe7ccc8
A
377
378 void unlinkCalls();
379
380 protected:
381 void clearCode();
382 static void finalize(JSCell*);
383
14957cd0
A
384 private:
385 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
386 EvalExecutable(ExecState*, const SourceCode&, bool);
387
6fe7ccc8
A
388 JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
389 static void visitChildren(JSCell*, SlotVisitor&);
14957cd0
A
390
391 OwnPtr<EvalCodeBlock> m_evalCodeBlock;
f9bf01c6
A
392 };
393
394 class ProgramExecutable : public ScriptExecutable {
6fe7ccc8 395 friend class LLIntOffsetsExtractor;
f9bf01c6 396 public:
6fe7ccc8
A
397 typedef ScriptExecutable Base;
398
14957cd0 399 static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
f9bf01c6 400 {
6fe7ccc8
A
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;
f9bf01c6
A
405 }
406
6fe7ccc8 407 static void destroy(JSCell*);
f9bf01c6 408
14957cd0
A
409 JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
410 {
411 ASSERT(exec->globalData().dynamicGlobalObject);
412 JSObject* error = 0;
413 if (!m_programCodeBlock)
6fe7ccc8 414 error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
14957cd0
A
415 ASSERT(!error == !!m_programCodeBlock);
416 return error;
417 }
418
6fe7ccc8
A
419 JSObject* compileOptimized(ExecState*, ScopeChainNode*);
420
421#if ENABLE(JIT)
422 void jettisonOptimizedCode(JSGlobalData&);
423 bool jitCompile(JSGlobalData&);
424#endif
425
14957cd0 426 ProgramCodeBlock& generatedBytecode()
f9bf01c6 427 {
14957cd0 428 ASSERT(m_programCodeBlock);
f9bf01c6
A
429 return *m_programCodeBlock;
430 }
431
432 JSObject* checkSyntax(ExecState*);
f9bf01c6 433
14957cd0
A
434#if ENABLE(JIT)
435 JITCode& generatedJITCode()
f9bf01c6 436 {
14957cd0 437 return generatedJITCodeForCall();
f9bf01c6 438 }
14957cd0
A
439#endif
440
6fe7ccc8 441 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
f9bf01c6 442 {
6fe7ccc8 443 return Structure::create(globalData, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
f9bf01c6 444 }
14957cd0
A
445
446 static const ClassInfo s_info;
6fe7ccc8
A
447
448 void unlinkCalls();
449
450 protected:
451 void clearCode();
452 static void finalize(JSCell*);
f9bf01c6
A
453
454 private:
14957cd0
A
455 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
456 ProgramExecutable(ExecState*, const SourceCode&);
457
6fe7ccc8
A
458 JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
459 static void visitChildren(JSCell*, SlotVisitor&);
14957cd0
A
460
461 OwnPtr<ProgramCodeBlock> m_programCodeBlock;
f9bf01c6
A
462 };
463
6fe7ccc8 464 class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
f9bf01c6 465 friend class JIT;
6fe7ccc8
A
466 friend class LLIntOffsetsExtractor;
467 friend class WTF::DoublyLinkedListNode<FunctionExecutable>;
f9bf01c6 468 public:
6fe7ccc8
A
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)
f9bf01c6 472 {
6fe7ccc8
A
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;
f9bf01c6
A
478 }
479
6fe7ccc8 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)
f9bf01c6 481 {
6fe7ccc8
A
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;
f9bf01c6
A
487 }
488
6fe7ccc8
A
489 static void destroy(JSCell*);
490
f9bf01c6
A
491 JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
492 {
6fe7ccc8 493 return JSFunction::create(exec, this, scopeChain);
f9bf01c6 494 }
14957cd0
A
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()
f9bf01c6 500 {
14957cd0
A
501 if (m_codeBlockForCall)
502 return *m_codeBlockForCall;
503 ASSERT(m_codeBlockForConstruct);
504 return *m_codeBlockForConstruct;
f9bf01c6 505 }
6fe7ccc8
A
506
507 FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind);
508
509 PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(ScopeChainNode*, CompilationKind, CodeSpecializationKind, JSObject*& exception);
f9bf01c6 510
14957cd0 511 JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
f9bf01c6 512 {
14957cd0
A
513 ASSERT(exec->globalData().dynamicGlobalObject);
514 JSObject* error = 0;
515 if (!m_codeBlockForCall)
6fe7ccc8 516 error = compileForCallInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
14957cd0
A
517 ASSERT(!error == !!m_codeBlockForCall);
518 return error;
f9bf01c6
A
519 }
520
6fe7ccc8
A
521 JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*);
522
523#if ENABLE(JIT)
524 void jettisonOptimizedCodeForCall(JSGlobalData&);
525 bool jitCompileForCall(JSGlobalData&);
526#endif
527
14957cd0 528 bool isGeneratedForCall() const
f9bf01c6 529 {
14957cd0 530 return m_codeBlockForCall;
f9bf01c6
A
531 }
532
14957cd0
A
533 FunctionCodeBlock& generatedBytecodeForCall()
534 {
535 ASSERT(m_codeBlockForCall);
536 return *m_codeBlockForCall;
537 }
f9bf01c6 538
14957cd0
A
539 JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
540 {
541 ASSERT(exec->globalData().dynamicGlobalObject);
542 JSObject* error = 0;
543 if (!m_codeBlockForConstruct)
6fe7ccc8 544 error = compileForConstructInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
14957cd0
A
545 ASSERT(!error == !!m_codeBlockForConstruct);
546 return error;
547 }
f9bf01c6 548
6fe7ccc8
A
549 JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*);
550
551#if ENABLE(JIT)
552 void jettisonOptimizedCodeForConstruct(JSGlobalData&);
553 bool jitCompileForConstruct(JSGlobalData&);
554#endif
555
14957cd0 556 bool isGeneratedForConstruct() const
f9bf01c6 557 {
14957cd0 558 return m_codeBlockForConstruct;
f9bf01c6
A
559 }
560
14957cd0 561 FunctionCodeBlock& generatedBytecodeForConstruct()
f9bf01c6 562 {
14957cd0
A
563 ASSERT(m_codeBlockForConstruct);
564 return *m_codeBlockForConstruct;
f9bf01c6 565 }
6fe7ccc8
A
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 }
f9bf01c6 627
6fe7ccc8
A
628 FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
629
630 FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
631 {
632 return baselineCodeBlockFor(kind);
633 }
634
14957cd0 635 const Identifier& name() { return m_name; }
6fe7ccc8
A
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'!
14957cd0
A
639 unsigned capturedVariableCount() const { return m_numCapturedVariables; }
640 UString paramString() const;
641 SharedSymbolTable* symbolTable() const { return m_symbolTable; }
642
643 void discardCode();
6fe7ccc8 644 static void visitChildren(JSCell*, SlotVisitor&);
14957cd0 645 static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
6fe7ccc8 646 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
14957cd0 647 {
6fe7ccc8 648 return Structure::create(globalData, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
14957cd0
A
649 }
650
651 static const ClassInfo s_info;
6fe7ccc8
A
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 }
f9bf01c6 666
14957cd0 667 private:
6fe7ccc8
A
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);
14957cd0 670
6fe7ccc8
A
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 }
14957cd0
A
681
682 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
683 unsigned m_numCapturedVariables : 31;
4e4e5a6f
A
684 bool m_forceUsesArguments : 1;
685
f9bf01c6 686 RefPtr<FunctionParameters> m_parameters;
14957cd0
A
687 OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
688 OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
f9bf01c6 689 Identifier m_name;
6fe7ccc8
A
690 Identifier m_inferredName;
691 WriteBarrier<JSString> m_nameValue;
14957cd0 692 SharedSymbolTable* m_symbolTable;
6fe7ccc8
A
693 FunctionExecutable* m_next;
694 FunctionExecutable* m_prev;
f9bf01c6
A
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
14957cd0
A
709 inline NativeFunction JSFunction::nativeFunction()
710 {
711 ASSERT(isHostFunction());
712 return static_cast<NativeExecutable*>(m_executable.get())->function();
713 }
6fe7ccc8
A
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
f9bf01c6
A
743}
744
745#endif