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