]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Executable.h
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / runtime / Executable.h
CommitLineData
f9bf01c6 1/*
93a37866 2 * Copyright (C) 2009, 2010, 2013 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"
93a37866 30#include "CodeBlockHash.h"
6fe7ccc8 31#include "CodeSpecializationKind.h"
93a37866 32#include "HandlerInfo.h"
f9bf01c6
A
33#include "JSFunction.h"
34#include "Interpreter.h"
93a37866
A
35#include "JITCode.h"
36#include "JSGlobalObject.h"
37#include "LLIntCLoop.h"
f9bf01c6 38#include "SamplingTool.h"
93a37866
A
39#include "SourceCode.h"
40#include "UnlinkedCodeBlock.h"
14957cd0 41#include <wtf/PassOwnPtr.h>
f9bf01c6
A
42
43namespace JSC {
44
45 class CodeBlock;
46 class Debugger;
47 class EvalCodeBlock;
14957cd0 48 class FunctionCodeBlock;
6fe7ccc8 49 class LLIntOffsetsExtractor;
f9bf01c6 50 class ProgramCodeBlock;
93a37866 51 class JSScope;
6fe7ccc8
A
52
53 enum CompilationKind { FirstCompilation, OptimizingCompilation };
f9bf01c6 54
6fe7ccc8
A
55 inline bool isCall(CodeSpecializationKind kind)
56 {
57 if (kind == CodeForCall)
58 return true;
59 ASSERT(kind == CodeForConstruct);
60 return false;
61 }
f9bf01c6 62
93a37866
A
63 class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
64 friend class WTF::DoublyLinkedListNode<ExecutableBase>;
f9bf01c6
A
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;
6fe7ccc8 70
93a37866
A
71 ExecutableBase(VM& vm, Structure* structure, int numParameters)
72 : JSCell(vm, structure)
14957cd0
A
73 , m_numParametersForCall(numParameters)
74 , m_numParametersForConstruct(numParameters)
f9bf01c6 75 {
6fe7ccc8
A
76 }
77
93a37866 78 void finishCreation(VM& vm)
6fe7ccc8 79 {
93a37866 80 Base::finishCreation(vm);
6fe7ccc8
A
81 }
82
83 public:
84 typedef JSCell Base;
85
14957cd0 86#if ENABLE(JIT)
93a37866
A
87 static const bool needsDestruction = true;
88 static const bool hasImmortalStructure = true;
6fe7ccc8 89 static void destroy(JSCell*);
14957cd0 90#endif
93a37866
A
91
92 CodeBlockHash hashFor(CodeSpecializationKind) const;
93
94 bool isFunctionExecutable()
95 {
96 return structure()->typeInfo().type() == FunctionExecutableType;
97 }
f9bf01c6 98
14957cd0
A
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 }
f9bf01c6 104
93a37866 105 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
14957cd0 106
93a37866
A
107 void clearCode();
108
6fe7ccc8 109 static JS_EXPORTDATA const ClassInfo s_info;
f9bf01c6
A
110
111 protected:
14957cd0
A
112 static const unsigned StructureFlags = 0;
113 int m_numParametersForCall;
114 int m_numParametersForConstruct;
f9bf01c6 115
f9bf01c6 116 public:
93a37866
A
117 static void clearCodeVirtual(ExecutableBase*);
118
119#if ENABLE(JIT)
14957cd0 120 JITCode& generatedJITCodeForCall()
f9bf01c6 121 {
14957cd0
A
122 ASSERT(m_jitCodeForCall);
123 return m_jitCodeForCall;
f9bf01c6
A
124 }
125
14957cd0 126 JITCode& generatedJITCodeForConstruct()
f9bf01c6 127 {
14957cd0
A
128 ASSERT(m_jitCodeForConstruct);
129 return m_jitCodeForConstruct;
130 }
6fe7ccc8
A
131
132 JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
133 {
134 if (kind == CodeForCall)
135 return generatedJITCodeForCall();
136 ASSERT(kind == CodeForConstruct);
137 return generatedJITCodeForConstruct();
138 }
14957cd0 139
6fe7ccc8 140 MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
14957cd0 141 {
6fe7ccc8
A
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
93a37866
A
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
6fe7ccc8
A
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;
f9bf01c6 213 }
93a37866
A
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)
f9bf01c6
A
254
255 protected:
93a37866
A
256 ExecutableBase* m_prev;
257 ExecutableBase* m_next;
258
259#if ENABLE(JIT)
14957cd0
A
260 JITCode m_jitCodeForCall;
261 JITCode m_jitCodeForConstruct;
262 MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
263 MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
f9bf01c6
A
264#endif
265 };
266
f9bf01c6 267 class NativeExecutable : public ExecutableBase {
14957cd0 268 friend class JIT;
6fe7ccc8 269 friend class LLIntOffsetsExtractor;
f9bf01c6 270 public:
6fe7ccc8
A
271 typedef ExecutableBase Base;
272
14957cd0 273#if ENABLE(JIT)
93a37866 274 static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
6fe7ccc8 275 {
6fe7ccc8
A
276 NativeExecutable* executable;
277 if (!callThunk) {
93a37866
A
278 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
279 executable->finishCreation(vm, JITCode(), JITCode(), intrinsic);
6fe7ccc8 280 } else {
93a37866
A
281 executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
282 executable->finishCreation(vm, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
6fe7ccc8 283 }
6fe7ccc8 284 return executable;
f9bf01c6 285 }
6fe7ccc8
A
286#endif
287
93a37866
A
288#if ENABLE(LLINT_C_LOOP)
289 static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
14957cd0 290 {
93a37866
A
291 ASSERT(!vm.canUseJIT());
292 NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
293 executable->finishCreation(vm);
6fe7ccc8 294 return executable;
14957cd0
A
295 }
296#endif
f9bf01c6 297
6fe7ccc8
A
298#if ENABLE(JIT)
299 static void destroy(JSCell*);
300#endif
f9bf01c6 301
93a37866
A
302 CodeBlockHash hashFor(CodeSpecializationKind) const;
303
14957cd0 304 NativeFunction function() { return m_function; }
6fe7ccc8 305 NativeFunction constructor() { return m_constructor; }
93a37866
A
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 }
14957cd0 322
93a37866 323 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
14957cd0
A
324
325 static const ClassInfo s_info;
6fe7ccc8
A
326
327 Intrinsic intrinsic() const;
328
329 protected:
14957cd0 330#if ENABLE(JIT)
93a37866 331 void finishCreation(VM& vm, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
14957cd0 332 {
93a37866 333 Base::finishCreation(vm);
14957cd0
A
334 m_jitCodeForCall = callThunk;
335 m_jitCodeForConstruct = constructThunk;
336 m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
337 m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
6fe7ccc8
A
338 m_intrinsic = intrinsic;
339 }
340#endif
341
6fe7ccc8 342 private:
93a37866
A
343 NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
344 : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
14957cd0
A
345 , m_function(function)
346 , m_constructor(constructor)
f9bf01c6
A
347 {
348 }
349
14957cd0 350 NativeFunction m_function;
14957cd0 351 NativeFunction m_constructor;
6fe7ccc8
A
352
353 Intrinsic m_intrinsic;
f9bf01c6
A
354 };
355
356 class ScriptExecutable : public ExecutableBase {
357 public:
6fe7ccc8
A
358 typedef ExecutableBase Base;
359
93a37866
A
360 ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
361 : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
f9bf01c6 362 , m_source(source)
14957cd0 363 , m_features(isInStrictContext ? StrictModeFeature : 0)
f9bf01c6 364 {
f9bf01c6
A
365 }
366
14957cd0 367 ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
93a37866 368 : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
f9bf01c6 369 , m_source(source)
14957cd0 370 , m_features(isInStrictContext ? StrictModeFeature : 0)
f9bf01c6 371 {
f9bf01c6
A
372 }
373
6fe7ccc8
A
374#if ENABLE(JIT)
375 static void destroy(JSCell*);
376#endif
93a37866
A
377
378 CodeBlockHash hashFor(CodeSpecializationKind) const;
6fe7ccc8 379
93a37866 380 const SourceCode& source() const { return m_source; }
6fe7ccc8 381 intptr_t sourceID() const { return m_source.providerID(); }
93a37866 382 const String& sourceURL() const { return m_source.provider()->url(); }
f9bf01c6
A
383 int lineNo() const { return m_firstLine; }
384 int lastLine() const { return m_lastLine; }
93a37866 385 unsigned startColumn() const { return m_startColumn; }
f9bf01c6
A
386
387 bool usesEval() const { return m_features & EvalFeature; }
388 bool usesArguments() const { return m_features & ArgumentsFeature; }
14957cd0
A
389 bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
390 bool isStrictMode() const { return m_features & StrictModeFeature; }
f9bf01c6 391
6fe7ccc8 392 void unlinkCalls();
93a37866
A
393
394 CodeFeatures features() const { return m_features; }
14957cd0
A
395
396 static const ClassInfo s_info;
6fe7ccc8 397
93a37866 398 void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
f9bf01c6
A
399 {
400 m_features = features;
14957cd0 401 m_hasCapturedVariables = hasCapturedVariables;
f9bf01c6
A
402 m_firstLine = firstLine;
403 m_lastLine = lastLine;
93a37866
A
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
f9bf01c6
A
417 }
418
419 SourceCode m_source;
420 CodeFeatures m_features;
14957cd0 421 bool m_hasCapturedVariables;
f9bf01c6
A
422 int m_firstLine;
423 int m_lastLine;
93a37866 424 unsigned m_startColumn;
f9bf01c6
A
425 };
426
427 class EvalExecutable : public ScriptExecutable {
6fe7ccc8 428 friend class LLIntOffsetsExtractor;
f9bf01c6 429 public:
6fe7ccc8 430 typedef ScriptExecutable Base;
f9bf01c6 431
6fe7ccc8 432 static void destroy(JSCell*);
f9bf01c6 433
93a37866 434 JSObject* compile(ExecState* exec, JSScope* scope)
f9bf01c6 435 {
93a37866 436 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
14957cd0
A
437 JSObject* error = 0;
438 if (!m_evalCodeBlock)
93a37866 439 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
14957cd0
A
440 ASSERT(!error == !!m_evalCodeBlock);
441 return error;
f9bf01c6 442 }
6fe7ccc8 443
93a37866 444 JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
6fe7ccc8
A
445
446#if ENABLE(JIT)
93a37866
A
447 void jettisonOptimizedCode(VM&);
448 bool jitCompile(ExecState*);
6fe7ccc8 449#endif
f9bf01c6 450
14957cd0 451 EvalCodeBlock& generatedBytecode()
f9bf01c6 452 {
14957cd0
A
453 ASSERT(m_evalCodeBlock);
454 return *m_evalCodeBlock;
f9bf01c6 455 }
14957cd0 456
93a37866 457 static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
6fe7ccc8 458 {
93a37866
A
459 EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
460 executable->finishCreation(exec->vm());
6fe7ccc8
A
461 return executable;
462 }
f9bf01c6
A
463
464#if ENABLE(JIT)
14957cd0 465 JITCode& generatedJITCode()
f9bf01c6 466 {
14957cd0 467 return generatedJITCodeForCall();
f9bf01c6 468 }
f9bf01c6 469#endif
93a37866 470 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
14957cd0 471 {
93a37866 472 return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
14957cd0
A
473 }
474
475 static const ClassInfo s_info;
6fe7ccc8
A
476
477 void unlinkCalls();
478
6fe7ccc8 479 void clearCode();
93a37866
A
480
481 ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
6fe7ccc8 482
14957cd0
A
483 private:
484 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
93a37866 485 EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
14957cd0 486
93a37866 487 JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
6fe7ccc8 488 static void visitChildren(JSCell*, SlotVisitor&);
14957cd0
A
489
490 OwnPtr<EvalCodeBlock> m_evalCodeBlock;
93a37866
A
491 WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
492 RefPtr<CodeCache> m_codeCache;
f9bf01c6
A
493 };
494
495 class ProgramExecutable : public ScriptExecutable {
6fe7ccc8 496 friend class LLIntOffsetsExtractor;
f9bf01c6 497 public:
6fe7ccc8
A
498 typedef ScriptExecutable Base;
499
14957cd0 500 static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
f9bf01c6 501 {
6fe7ccc8 502 ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
93a37866 503 executable->finishCreation(exec->vm());
6fe7ccc8 504 return executable;
f9bf01c6
A
505 }
506
93a37866
A
507
508 JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
509
6fe7ccc8 510 static void destroy(JSCell*);
f9bf01c6 511
93a37866 512 JSObject* compile(ExecState* exec, JSScope* scope)
14957cd0 513 {
93a37866 514 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
14957cd0
A
515 JSObject* error = 0;
516 if (!m_programCodeBlock)
93a37866 517 error = compileInternal(exec, scope, JITCode::bottomTierJIT());
14957cd0
A
518 ASSERT(!error == !!m_programCodeBlock);
519 return error;
520 }
521
93a37866 522 JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
6fe7ccc8
A
523
524#if ENABLE(JIT)
93a37866
A
525 void jettisonOptimizedCode(VM&);
526 bool jitCompile(ExecState*);
6fe7ccc8
A
527#endif
528
14957cd0 529 ProgramCodeBlock& generatedBytecode()
f9bf01c6 530 {
14957cd0 531 ASSERT(m_programCodeBlock);
f9bf01c6
A
532 return *m_programCodeBlock;
533 }
534
535 JSObject* checkSyntax(ExecState*);
f9bf01c6 536
14957cd0
A
537#if ENABLE(JIT)
538 JITCode& generatedJITCode()
f9bf01c6 539 {
14957cd0 540 return generatedJITCodeForCall();
f9bf01c6 541 }
14957cd0
A
542#endif
543
93a37866 544 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
f9bf01c6 545 {
93a37866 546 return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
f9bf01c6 547 }
14957cd0
A
548
549 static const ClassInfo s_info;
6fe7ccc8
A
550
551 void unlinkCalls();
552
6fe7ccc8 553 void clearCode();
93a37866
A
554
555 ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
f9bf01c6
A
556
557 private:
14957cd0 558 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
93a37866 559
14957cd0
A
560 ProgramExecutable(ExecState*, const SourceCode&);
561
93a37866
A
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);
6fe7ccc8 567 static void visitChildren(JSCell*, SlotVisitor&);
14957cd0 568
93a37866 569 WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
14957cd0 570 OwnPtr<ProgramCodeBlock> m_programCodeBlock;
f9bf01c6
A
571 };
572
93a37866 573 class FunctionExecutable : public ScriptExecutable {
f9bf01c6 574 friend class JIT;
6fe7ccc8 575 friend class LLIntOffsetsExtractor;
f9bf01c6 576 public:
6fe7ccc8
A
577 typedef ScriptExecutable Base;
578
93a37866 579 static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
f9bf01c6 580 {
93a37866
A
581 FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
582 executable->finishCreation(vm);
6fe7ccc8 583 return executable;
f9bf01c6 584 }
93a37866 585 static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
f9bf01c6 586
6fe7ccc8 587 static void destroy(JSCell*);
93a37866
A
588
589 UnlinkedFunctionExecutable* unlinkedExecutable()
f9bf01c6 590 {
93a37866 591 return m_unlinkedExecutable.get();
f9bf01c6 592 }
93a37866 593
14957cd0
A
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()
f9bf01c6 598 {
14957cd0
A
599 if (m_codeBlockForCall)
600 return *m_codeBlockForCall;
601 ASSERT(m_codeBlockForConstruct);
602 return *m_codeBlockForConstruct;
f9bf01c6 603 }
6fe7ccc8 604
93a37866 605 PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
f9bf01c6 606
93a37866 607 JSObject* compileForCall(ExecState* exec, JSScope* scope)
f9bf01c6 608 {
93a37866 609 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
14957cd0
A
610 JSObject* error = 0;
611 if (!m_codeBlockForCall)
93a37866 612 error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
14957cd0
A
613 ASSERT(!error == !!m_codeBlockForCall);
614 return error;
f9bf01c6
A
615 }
616
93a37866 617 JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex);
6fe7ccc8
A
618
619#if ENABLE(JIT)
93a37866
A
620 void jettisonOptimizedCodeForCall(VM&);
621 bool jitCompileForCall(ExecState*);
6fe7ccc8
A
622#endif
623
14957cd0 624 bool isGeneratedForCall() const
f9bf01c6 625 {
14957cd0 626 return m_codeBlockForCall;
f9bf01c6
A
627 }
628
14957cd0
A
629 FunctionCodeBlock& generatedBytecodeForCall()
630 {
631 ASSERT(m_codeBlockForCall);
632 return *m_codeBlockForCall;
633 }
f9bf01c6 634
93a37866 635 JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
14957cd0 636 {
93a37866 637 RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
14957cd0
A
638 JSObject* error = 0;
639 if (!m_codeBlockForConstruct)
93a37866 640 error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
14957cd0
A
641 ASSERT(!error == !!m_codeBlockForConstruct);
642 return error;
643 }
f9bf01c6 644
93a37866 645 JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex);
6fe7ccc8
A
646
647#if ENABLE(JIT)
93a37866
A
648 void jettisonOptimizedCodeForConstruct(VM&);
649 bool jitCompileForConstruct(ExecState*);
6fe7ccc8
A
650#endif
651
14957cd0 652 bool isGeneratedForConstruct() const
f9bf01c6 653 {
14957cd0 654 return m_codeBlockForConstruct;
f9bf01c6
A
655 }
656
14957cd0 657 FunctionCodeBlock& generatedBytecodeForConstruct()
f9bf01c6 658 {
14957cd0
A
659 ASSERT(m_codeBlockForConstruct);
660 return *m_codeBlockForConstruct;
f9bf01c6 661 }
6fe7ccc8 662
93a37866 663 JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
6fe7ccc8
A
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)
93a37866 670 return compileForCall(exec, scope);
6fe7ccc8 671 ASSERT(kind == CodeForConstruct);
93a37866 672 return compileForConstruct(exec, scope);
6fe7ccc8
A
673 }
674
93a37866 675 JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, unsigned bytecodeIndex, CodeSpecializationKind kind)
6fe7ccc8
A
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)
93a37866 682 return compileOptimizedForCall(exec, scope, bytecodeIndex);
6fe7ccc8 683 ASSERT(kind == CodeForConstruct);
93a37866 684 return compileOptimizedForConstruct(exec, scope, bytecodeIndex);
6fe7ccc8
A
685 }
686
687
688#if ENABLE(JIT)
93a37866 689 void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
6fe7ccc8
A
690 {
691 if (kind == CodeForCall)
93a37866 692 jettisonOptimizedCodeForCall(vm);
6fe7ccc8
A
693 else {
694 ASSERT(kind == CodeForConstruct);
93a37866 695 jettisonOptimizedCodeForConstruct(vm);
6fe7ccc8
A
696 }
697 }
698
93a37866 699 bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
6fe7ccc8
A
700 {
701 if (kind == CodeForCall)
93a37866 702 return jitCompileForCall(exec);
6fe7ccc8 703 ASSERT(kind == CodeForConstruct);
93a37866 704 return jitCompileForConstruct(exec);
6fe7ccc8
A
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 }
f9bf01c6 723
6fe7ccc8
A
724 FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
725
726 FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
727 {
728 return baselineCodeBlockFor(kind);
729 }
730
93a37866
A
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); }
14957cd0 737
93a37866
A
738 void clearCodeIfNotCompiling();
739 void clearUnlinkedCodeForRecompilationIfNotCompiling();
6fe7ccc8 740 static void visitChildren(JSCell*, SlotVisitor&);
93a37866 741 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
14957cd0 742 {
93a37866 743 return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
14957cd0
A
744 }
745
746 static const ClassInfo s_info;
6fe7ccc8
A
747
748 void unlinkCalls();
749
6fe7ccc8 750 void clearCode();
f9bf01c6 751
14957cd0 752 private:
93a37866 753 FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
14957cd0 754
93a37866
A
755 JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
756 JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
6fe7ccc8
A
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 }
93a37866
A
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 }
4e4e5a6f 776
93a37866
A
777 static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
778 WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
14957cd0
A
779 OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
780 OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
f9bf01c6
A
781 };
782
93a37866
A
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
f9bf01c6
A
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
14957cd0
A
803 inline NativeFunction JSFunction::nativeFunction()
804 {
805 ASSERT(isHostFunction());
806 return static_cast<NativeExecutable*>(m_executable.get())->function();
807 }
6fe7ccc8
A
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
93a37866
A
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
6fe7ccc8
A
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:
93a37866 847 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
848 }
849 }
850
f9bf01c6
A
851}
852
853#endif