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