Executable.h 21.6 KB
Newer Older
1
/*
2
 * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#ifndef Executable_h
#define Executable_h

29
#include "CallData.h"
30
#include "CodeBlockHash.h"
31
#include "CodeSpecializationKind.h"
32 33
#include "CompilationResult.h"
#include "DFGPlan.h"
34
#include "HandlerInfo.h"
35
#include "JSFunction.h"
36
#include "Interpreter.h"
37
#include "JITCode.h"
38
#include "JSGlobalObject.h"
39
#include "SamplingTool.h"
40
#include "SourceCode.h"
41
#include "UnlinkedCodeBlock.h"
42
#include <wtf/PassOwnPtr.h>
43 44 45

namespace JSC {

46 47 48 49 50 51 52
class CodeBlock;
class Debugger;
class EvalCodeBlock;
class FunctionCodeBlock;
class LLIntOffsetsExtractor;
class ProgramCodeBlock;
class JSScope;
53
    
54 55 56 57 58 59 60 61 62
enum CompilationKind { FirstCompilation, OptimizingCompilation };

inline bool isCall(CodeSpecializationKind kind)
{
    if (kind == CodeForCall)
        return true;
    ASSERT(kind == CodeForConstruct);
    return false;
}
63

64 65 66
class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
    friend class WTF::DoublyLinkedListNode<ExecutableBase>;
    friend class JIT;
67

68 69 70
protected:
    static const int NUM_PARAMETERS_IS_HOST = 0;
    static const int NUM_PARAMETERS_NOT_COMPILED = -1;
71

72 73 74 75 76 77
    ExecutableBase(VM& vm, Structure* structure, int numParameters)
        : JSCell(vm, structure)
        , m_numParametersForCall(numParameters)
        , m_numParametersForConstruct(numParameters)
    {
    }
78

79 80 81 82
    void finishCreation(VM& vm)
    {
        Base::finishCreation(vm);
    }
83

84 85
public:
    typedef JSCell Base;
86

oliver@apple.com's avatar
oliver@apple.com committed
87
#if ENABLE(JIT)
88 89 90
    static const bool needsDestruction = true;
    static const bool hasImmortalStructure = true;
    static void destroy(JSCell*);
oliver@apple.com's avatar
oliver@apple.com committed
91
#endif
92
        
93
    CodeBlockHash hashFor(CodeSpecializationKind) const;
94

95 96 97 98
    bool isEvalExecutable()
    {
        return structure()->typeInfo().type() == EvalExecutableType;
    }
99 100 101 102
    bool isFunctionExecutable()
    {
        return structure()->typeInfo().type() == FunctionExecutableType;
    }
103 104 105 106
    bool isProgramExecutable()
    {
        return structure()->typeInfo().type() == ProgramExecutableType;
    }
107

108 109 110 111 112
    bool isHostFunction() const
    {
        ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
        return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
    }
113

114
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), info()); }
115
        
116
    void clearCode();
117

118
    DECLARE_EXPORT_INFO;
119

120 121 122 123
protected:
    static const unsigned StructureFlags = 0;
    int m_numParametersForCall;
    int m_numParametersForConstruct;
124

125 126
public:
    static void clearCodeVirtual(ExecutableBase*);
127

128 129 130 131 132
    PassRefPtr<JITCode> generatedJITCodeForCall()
    {
        ASSERT(m_jitCodeForCall);
        return m_jitCodeForCall;
    }
133

134 135 136 137 138
    PassRefPtr<JITCode> generatedJITCodeForConstruct()
    {
        ASSERT(m_jitCodeForConstruct);
        return m_jitCodeForConstruct;
    }
139
        
140 141 142 143 144 145 146
    PassRefPtr<JITCode> generatedJITCodeFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return generatedJITCodeForCall();
        ASSERT(kind == CodeForConstruct);
        return generatedJITCodeForConstruct();
    }
147

148 149 150 151 152 153
    MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
    {
        ASSERT(m_jitCodeForCall);
        ASSERT(m_jitCodeForCallWithArityCheck);
        return m_jitCodeForCallWithArityCheck;
    }
154

155 156 157 158 159 160
    MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
    {
        ASSERT(m_jitCodeForConstruct);
        ASSERT(m_jitCodeForConstructWithArityCheck);
        return m_jitCodeForConstructWithArityCheck;
    }
161
        
162 163 164 165 166 167 168
    MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return generatedJITCodeForCallWithArityCheck();
        ASSERT(kind == CodeForConstruct);
        return generatedJITCodeForConstructWithArityCheck();
    }
169
        
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
        ASSERT(kind == CodeForConstruct);
        return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
    }
        
    static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
        ASSERT(kind == CodeForConstruct);
        return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
    }

186 187 188 189
    bool hasJITCodeForCall() const
    {
        return m_numParametersForCall >= 0;
    }
190
        
191 192 193 194
    bool hasJITCodeForConstruct() const
    {
        return m_numParametersForConstruct >= 0;
    }
195
        
196 197 198 199 200 201 202
    bool hasJITCodeFor(CodeSpecializationKind kind) const
    {
        if (kind == CodeForCall)
            return hasJITCodeForCall();
        ASSERT(kind == CodeForConstruct);
        return hasJITCodeForConstruct();
    }
203

204 205
    // Intrinsics are only for calls, currently.
    Intrinsic intrinsic() const;
206
        
207 208 209 210 211 212
    Intrinsic intrinsicFor(CodeSpecializationKind kind) const
    {
        if (isCall(kind))
            return intrinsic();
        return NoIntrinsic;
    }
213
        
214 215 216 217
    MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
    {
        return generatedJITCodeFor(kind)->addressForCall();
    }
218

219 220 221 222
    MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
    {
        return generatedJITCodeFor(kind)->addressForCall();
    }
223

224 225 226 227
    MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
    {
        return generatedJITCodeWithArityCheckFor(kind);
    }
228

229 230 231
protected:
    ExecutableBase* m_prev;
    ExecutableBase* m_next;
232

233 234 235 236 237
    RefPtr<JITCode> m_jitCodeForCall;
    RefPtr<JITCode> m_jitCodeForConstruct;
    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
};
238

239 240 241 242 243
class NativeExecutable : public ExecutableBase {
    friend class JIT;
    friend class LLIntOffsetsExtractor;
public:
    typedef ExecutableBase Base;
244

245 246 247
    static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
    {
        NativeExecutable* executable;
248 249
        executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
        if (!callThunk)
250
            executable->finishCreation(vm, 0, 0, intrinsic);
251
        else
252 253 254
            executable->finishCreation(vm, JITCode::hostFunction(callThunk), JITCode::hostFunction(constructThunk), intrinsic);
        return executable;
    }
255

oliver@apple.com's avatar
oliver@apple.com committed
256
#if ENABLE(JIT)
257
    static void destroy(JSCell*);
oliver@apple.com's avatar
oliver@apple.com committed
258
#endif
259

260
    CodeBlockHash hashFor(CodeSpecializationKind) const;
261

262 263
    NativeFunction function() { return m_function; }
    NativeFunction constructor() { return m_constructor; }
264
        
265 266 267 268 269 270 271
    NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return function();
        ASSERT(kind == CodeForConstruct);
        return constructor();
    }
272
        
273 274 275 276 277 278 279
    static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return OBJECT_OFFSETOF(NativeExecutable, m_function);
        ASSERT(kind == CodeForConstruct);
        return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
    }
280

281
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), info()); }
282
        
283
    DECLARE_INFO;
284

285
    Intrinsic intrinsic() const;
286

287 288 289 290 291 292 293 294 295 296
protected:
    void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, Intrinsic intrinsic)
    {
        Base::finishCreation(vm);
        m_jitCodeForCallWithArityCheck = callThunk ? callThunk->addressForCall() : MacroAssemblerCodePtr();
        m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk->addressForCall() : MacroAssemblerCodePtr();
        m_jitCodeForCall = callThunk;
        m_jitCodeForConstruct = constructThunk;
        m_intrinsic = intrinsic;
    }
297

298 299 300 301 302 303 304
private:
    NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
        : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
        , m_function(function)
        , m_constructor(constructor)
    {
    }
305

306 307
    NativeFunction m_function;
    NativeFunction m_constructor;
308
        
309 310
    Intrinsic m_intrinsic;
};
311

312 313 314
class ScriptExecutable : public ExecutableBase {
public:
    typedef ExecutableBase Base;
315

316 317 318 319 320
    ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
        : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
        , m_source(source)
        , m_features(isInStrictContext ? StrictModeFeature : 0)
        , m_neverInline(false)
321 322
        , m_startColumn(UINT_MAX)
        , m_endColumn(UINT_MAX)
323 324
    {
    }
325

326 327 328 329 330
    ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
        : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
        , m_source(source)
        , m_features(isInStrictContext ? StrictModeFeature : 0)
        , m_neverInline(false)
331 332
        , m_startColumn(UINT_MAX)
        , m_endColumn(UINT_MAX)
333 334
    {
    }
335

oliver@apple.com's avatar
oliver@apple.com committed
336
#if ENABLE(JIT)
337
    static void destroy(JSCell*);
oliver@apple.com's avatar
oliver@apple.com committed
338
#endif
339
        
340
    CodeBlockHash hashFor(CodeSpecializationKind) const;
341

342 343 344 345 346 347
    const SourceCode& source() const { return m_source; }
    intptr_t sourceID() const { return m_source.providerID(); }
    const String& sourceURL() const { return m_source.provider()->url(); }
    int lineNo() const { return m_firstLine; }
    int lastLine() const { return m_lastLine; }
    unsigned startColumn() const { return m_startColumn; }
348
    unsigned endColumn() const { return m_endColumn; }
349

350 351 352 353
    bool usesEval() const { return m_features & EvalFeature; }
    bool usesArguments() const { return m_features & ArgumentsFeature; }
    bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
    bool isStrictMode() const { return m_features & StrictModeFeature; }
fpizlo@apple.com's avatar
fpizlo@apple.com committed
354
    ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
355
        
356 357 358
    void setNeverInline(bool value) { m_neverInline = value; }
    bool neverInline() const { return m_neverInline; }
    bool isInliningCandidate() const { return !neverInline(); }
359

360
    void unlinkCalls();
361
        
362
    CodeFeatures features() const { return m_features; }
363
        
364
    DECLARE_INFO;
365

366
    void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn, unsigned endColumn)
367 368 369 370 371
    {
        m_features = features;
        m_hasCapturedVariables = hasCapturedVariables;
        m_firstLine = firstLine;
        m_lastLine = lastLine;
372
        ASSERT(startColumn != UINT_MAX);
373
        m_startColumn = startColumn;
374 375
        ASSERT(endColumn != UINT_MAX);
        m_endColumn = endColumn;
376
    }
377

378 379 380 381 382 383 384 385 386 387 388 389 390 391
    void installCode(CodeBlock*);
    PassRefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSScope*, JSObject*& exception);
    PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
    
    JSObject* prepareForExecution(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
    {
        if (hasJITCodeFor(kind))
            return 0;
        return prepareForExecutionImpl(exec, scope, kind);
    }

private:
    JSObject* prepareForExecutionImpl(ExecState*, JSScope*, CodeSpecializationKind);

392 393 394 395 396
protected:
    void finishCreation(VM& vm)
    {
        Base::finishCreation(vm);
        vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
397

398
#if ENABLE(CODEBLOCK_SAMPLING)
399 400
        if (SamplingTool* sampler = vm.interpreter->sampler())
            sampler->notifyOfScope(vm, this);
401
#endif
402
    }
403

404 405 406 407 408 409 410
    SourceCode m_source;
    CodeFeatures m_features;
    bool m_hasCapturedVariables;
    bool m_neverInline;
    int m_firstLine;
    int m_lastLine;
    unsigned m_startColumn;
411
    unsigned m_endColumn;
412 413 414 415 416 417 418 419 420
};

class EvalExecutable : public ScriptExecutable {
    friend class LLIntOffsetsExtractor;
public:
    typedef ScriptExecutable Base;

    static void destroy(JSCell*);

421
    EvalCodeBlock* codeBlock()
422
    {
423
        return m_evalCodeBlock.get();
424
    }
425

426
    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext);
427

428 429 430 431
    PassRefPtr<JITCode> generatedJITCode()
    {
        return generatedJITCodeForCall();
    }
432

433 434 435 436
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
    {
        return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), info());
    }
437
        
438
    DECLARE_INFO;
439

440
    void unlinkCalls();
441

442
    void clearCode();
443

444
    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
445

446 447
    unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
    unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
448

449
private:
450
    friend class ScriptExecutable;
451 452
    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
    EvalExecutable(ExecState*, const SourceCode&, bool);
453

454
    static void visitChildren(JSCell*, SlotVisitor&);
455

456 457 458
    RefPtr<EvalCodeBlock> m_evalCodeBlock;
    WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
};
459

460 461 462 463
class ProgramExecutable : public ScriptExecutable {
    friend class LLIntOffsetsExtractor;
public:
    typedef ScriptExecutable Base;
464

465 466 467 468 469 470
    static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
    {
        ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
        executable->finishCreation(exec->vm());
        return executable;
    }
oliver@apple.com's avatar
oliver@apple.com committed
471

472

473
    JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
474

475
    static void destroy(JSCell*);
barraclough@apple.com's avatar
barraclough@apple.com committed
476

477
    ProgramCodeBlock* codeBlock()
478
    {
479
        return m_programCodeBlock.get();
480
    }
481

482
    JSObject* checkSyntax(ExecState*);
483

484 485 486 487
    PassRefPtr<JITCode> generatedJITCode()
    {
        return generatedJITCodeForCall();
    }
488
        
489 490 491 492
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
    {
        return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), info());
    }
493
        
494
    DECLARE_INFO;
495
        
496
    void unlinkCalls();
497

498
    void clearCode();
499

500
    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
501

502
private:
503 504
    friend class ScriptExecutable;
    
505
    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
506

507
    ProgramExecutable(ExecState*, const SourceCode&);
508

509
    static void visitChildren(JSCell*, SlotVisitor&);
510

511 512 513
    WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
    RefPtr<ProgramCodeBlock> m_programCodeBlock;
};
514

515 516 517 518 519
class FunctionExecutable : public ScriptExecutable {
    friend class JIT;
    friend class LLIntOffsetsExtractor;
public:
    typedef ScriptExecutable Base;
520

521
    static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces = true)
522
    {
523
        FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn, endColumn, bodyIncludesBraces);
524 525 526 527
        executable->finishCreation(vm);
        return executable;
    }
    static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
528

529
    static void destroy(JSCell*);
530
        
531 532 533 534
    UnlinkedFunctionExecutable* unlinkedExecutable()
    {
        return m_unlinkedExecutable.get();
    }
535

536 537 538
    // Returns either call or construct bytecode. This can be appropriate
    // for answering questions that that don't vary between call and construct --
    // for example, argumentsRegister().
539
    FunctionCodeBlock* eitherCodeBlock()
540 541
    {
        if (m_codeBlockForCall)
542 543
            return m_codeBlockForCall.get();
        return m_codeBlockForConstruct.get();
544
    }
545
        
546 547 548 549
    bool isGeneratedForCall() const
    {
        return m_codeBlockForCall;
    }
550

551
    FunctionCodeBlock* codeBlockForCall()
552
    {
553
        return m_codeBlockForCall.get();
554
    }
555

556 557 558 559
    bool isGeneratedForConstruct() const
    {
        return m_codeBlockForConstruct;
    }
560

561
    FunctionCodeBlock* codeBlockForConstruct()
562
    {
563
        return m_codeBlockForConstruct.get();
564
    }
565
        
566 567 568 569 570 571 572
    bool isGeneratedFor(CodeSpecializationKind kind)
    {
        if (kind == CodeForCall)
            return isGeneratedForCall();
        ASSERT(kind == CodeForConstruct);
        return isGeneratedForConstruct();
    }
573
        
574
    FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
575 576
    {
        if (kind == CodeForCall)
577
            return codeBlockForCall();
578
        ASSERT(kind == CodeForConstruct);
579
        return codeBlockForConstruct();
580
    }
581

582
    FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
fpizlo@apple.com's avatar
fpizlo@apple.com committed
583
        
584 585 586 587
    FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
    {
        return baselineCodeBlockFor(kind);
    }
fpizlo@apple.com's avatar
fpizlo@apple.com committed
588
        
589 590 591 592 593
    const Identifier& name() { return m_unlinkedExecutable->name(); }
    const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
    JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
    size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
    String paramString() const;
594
    SymbolTable* symbolTable(CodeSpecializationKind);
595 596 597 598 599 600 601 602

    void clearCodeIfNotCompiling();
    void clearUnlinkedCodeForRecompilationIfNotCompiling();
    static void visitChildren(JSCell*, SlotVisitor&);
    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
    {
        return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
    }
603
        
604
    DECLARE_INFO;
605
        
606
    void unlinkCalls();
607

608
    void clearCode();
609

610 611
    bool bodyIncludesBraces() const { return m_bodyIncludesBraces; }

612
private:
613
    FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, bool bodyIncludesBraces);
614

615 616
    bool isCompiling()
    {
617
#if ENABLE(JIT)
618 619 620 621
        if (!m_jitCodeForCall && m_codeBlockForCall)
            return true;
        if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
            return true;
622
#endif
623 624
        return false;
    }
625

626 627
    friend class ScriptExecutable;

628 629 630 631
    static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
    WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
    RefPtr<FunctionCodeBlock> m_codeBlockForCall;
    RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
632
    bool m_bodyIncludesBraces;
633
};
634

635 636 637 638 639 640 641
inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
{
    JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
    if (!function || !function->isHostFunction())
        return false;
    return function->nativeFunction() == nativeFunction;
}
642

643 644 645 646 647 648 649 650 651 652 653
inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
{
    switch (executable->structure()->typeInfo().type()) {
    case EvalExecutableType:
        return jsCast<EvalExecutable*>(executable)->clearCode();
    case ProgramExecutableType:
        return jsCast<ProgramExecutable*>(executable)->clearCode();
    case FunctionExecutableType:
        return jsCast<FunctionExecutable*>(executable)->clearCode();
    default:
        return jsCast<NativeExecutable*>(executable)->clearCode();
654
    }
655
}
656

657 658 659 660 661 662 663 664 665 666 667
inline void ScriptExecutable::unlinkCalls()
{
    switch (structure()->typeInfo().type()) {
    case EvalExecutableType:
        return jsCast<EvalExecutable*>(this)->unlinkCalls();
    case ProgramExecutableType:
        return jsCast<ProgramExecutable*>(this)->unlinkCalls();
    case FunctionExecutableType:
        return jsCast<FunctionExecutable*>(this)->unlinkCalls();
    default:
        RELEASE_ASSERT_NOT_REACHED();
668
    }
669
}
670

671
}
672 673

#endif