Executable.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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. #ifndef Executable_h
  26. #define Executable_h
  27. #include "CallData.h"
  28. #include "CodeBlockHash.h"
  29. #include "CodeSpecializationKind.h"
  30. #include "HandlerInfo.h"
  31. #include "JSFunction.h"
  32. #include "Interpreter.h"
  33. #include "JITCode.h"
  34. #include "JSGlobalObject.h"
  35. #include "LLIntCLoop.h"
  36. #include "SamplingTool.h"
  37. #include "SourceCode.h"
  38. #include "UnlinkedCodeBlock.h"
  39. #include <wtf/PassOwnPtr.h>
  40. namespace JSC {
  41. class CodeBlock;
  42. class Debugger;
  43. class EvalCodeBlock;
  44. class FunctionCodeBlock;
  45. class LLIntOffsetsExtractor;
  46. class ProgramCodeBlock;
  47. class JSScope;
  48. enum CompilationKind { FirstCompilation, OptimizingCompilation };
  49. inline bool isCall(CodeSpecializationKind kind)
  50. {
  51. if (kind == CodeForCall)
  52. return true;
  53. ASSERT(kind == CodeForConstruct);
  54. return false;
  55. }
  56. class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
  57. friend class WTF::DoublyLinkedListNode<ExecutableBase>;
  58. friend class JIT;
  59. protected:
  60. static const int NUM_PARAMETERS_IS_HOST = 0;
  61. static const int NUM_PARAMETERS_NOT_COMPILED = -1;
  62. ExecutableBase(VM& vm, Structure* structure, int numParameters)
  63. : JSCell(vm, structure)
  64. , m_numParametersForCall(numParameters)
  65. , m_numParametersForConstruct(numParameters)
  66. {
  67. }
  68. void finishCreation(VM& vm)
  69. {
  70. Base::finishCreation(vm);
  71. }
  72. public:
  73. typedef JSCell Base;
  74. #if ENABLE(JIT)
  75. static const bool needsDestruction = true;
  76. static const bool hasImmortalStructure = true;
  77. static void destroy(JSCell*);
  78. #endif
  79. CodeBlockHash hashFor(CodeSpecializationKind) const;
  80. bool isFunctionExecutable()
  81. {
  82. return structure()->typeInfo().type() == FunctionExecutableType;
  83. }
  84. bool isHostFunction() const
  85. {
  86. ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
  87. return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
  88. }
  89. static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
  90. void clearCode();
  91. static JS_EXPORTDATA const ClassInfo s_info;
  92. protected:
  93. static const unsigned StructureFlags = 0;
  94. int m_numParametersForCall;
  95. int m_numParametersForConstruct;
  96. public:
  97. static void clearCodeVirtual(ExecutableBase*);
  98. #if ENABLE(JIT)
  99. JITCode& generatedJITCodeForCall()
  100. {
  101. ASSERT(m_jitCodeForCall);
  102. return m_jitCodeForCall;
  103. }
  104. JITCode& generatedJITCodeForConstruct()
  105. {
  106. ASSERT(m_jitCodeForConstruct);
  107. return m_jitCodeForConstruct;
  108. }
  109. JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
  110. {
  111. if (kind == CodeForCall)
  112. return generatedJITCodeForCall();
  113. ASSERT(kind == CodeForConstruct);
  114. return generatedJITCodeForConstruct();
  115. }
  116. MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
  117. {
  118. ASSERT(m_jitCodeForCall);
  119. ASSERT(m_jitCodeForCallWithArityCheck);
  120. return m_jitCodeForCallWithArityCheck;
  121. }
  122. MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
  123. {
  124. ASSERT(m_jitCodeForConstruct);
  125. ASSERT(m_jitCodeForConstructWithArityCheck);
  126. return m_jitCodeForConstructWithArityCheck;
  127. }
  128. MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
  129. {
  130. if (kind == CodeForCall)
  131. return generatedJITCodeForCallWithArityCheck();
  132. ASSERT(kind == CodeForConstruct);
  133. return generatedJITCodeForConstructWithArityCheck();
  134. }
  135. bool hasJITCodeForCall() const
  136. {
  137. return m_numParametersForCall >= 0;
  138. }
  139. bool hasJITCodeForConstruct() const
  140. {
  141. return m_numParametersForConstruct >= 0;
  142. }
  143. bool hasJITCodeFor(CodeSpecializationKind kind) const
  144. {
  145. if (kind == CodeForCall)
  146. return hasJITCodeForCall();
  147. ASSERT(kind == CodeForConstruct);
  148. return hasJITCodeForConstruct();
  149. }
  150. static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind)
  151. {
  152. if (kind == CodeForCall)
  153. return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCall);
  154. ASSERT(kind == CodeForConstruct);
  155. return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstruct);
  156. }
  157. static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
  158. {
  159. if (kind == CodeForCall)
  160. return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
  161. ASSERT(kind == CodeForConstruct);
  162. return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
  163. }
  164. static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
  165. {
  166. if (kind == CodeForCall)
  167. return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForCall);
  168. ASSERT(kind == CodeForConstruct);
  169. return OBJECT_OFFSETOF(ExecutableBase, m_numParametersForConstruct);
  170. }
  171. #endif // ENABLE(JIT)
  172. // Intrinsics are only for calls, currently.
  173. Intrinsic intrinsic() const;
  174. Intrinsic intrinsicFor(CodeSpecializationKind kind) const
  175. {
  176. if (isCall(kind))
  177. return intrinsic();
  178. return NoIntrinsic;
  179. }
  180. #if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
  181. MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
  182. {
  183. #if ENABLE(JIT)
  184. return generatedJITCodeFor(kind).addressForCall();
  185. #else
  186. return LLInt::CLoop::hostCodeEntryFor(kind);
  187. #endif
  188. }
  189. MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
  190. {
  191. #if ENABLE(JIT)
  192. return generatedJITCodeFor(kind).addressForCall();
  193. #else
  194. return LLInt::CLoop::jsCodeEntryFor(kind);
  195. #endif
  196. }
  197. MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
  198. {
  199. #if ENABLE(JIT)
  200. return generatedJITCodeWithArityCheckFor(kind);
  201. #else
  202. return LLInt::CLoop::jsCodeEntryWithArityCheckFor(kind);
  203. #endif
  204. }
  205. static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
  206. {
  207. #if ENABLE(JIT)
  208. UNUSED_PARAM(catchPCForInterpreter);
  209. return handler->nativeCode.executableAddress();
  210. #else
  211. UNUSED_PARAM(handler);
  212. return LLInt::CLoop::catchRoutineFor(catchPCForInterpreter);
  213. #endif
  214. }
  215. #endif // ENABLE(JIT || ENABLE(LLINT_C_LOOP)
  216. protected:
  217. ExecutableBase* m_prev;
  218. ExecutableBase* m_next;
  219. #if ENABLE(JIT)
  220. JITCode m_jitCodeForCall;
  221. JITCode m_jitCodeForConstruct;
  222. MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
  223. MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
  224. #endif
  225. };
  226. class NativeExecutable : public ExecutableBase {
  227. friend class JIT;
  228. friend class LLIntOffsetsExtractor;
  229. public:
  230. typedef ExecutableBase Base;
  231. #if ENABLE(JIT)
  232. static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
  233. {
  234. NativeExecutable* executable;
  235. if (!callThunk) {
  236. executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
  237. executable->finishCreation(vm, JITCode(), JITCode(), intrinsic);
  238. } else {
  239. executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
  240. executable->finishCreation(vm, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
  241. }
  242. return executable;
  243. }
  244. #endif
  245. #if ENABLE(LLINT_C_LOOP)
  246. static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
  247. {
  248. ASSERT(!vm.canUseJIT());
  249. NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
  250. executable->finishCreation(vm);
  251. return executable;
  252. }
  253. #endif
  254. #if ENABLE(JIT)
  255. static void destroy(JSCell*);
  256. #endif
  257. CodeBlockHash hashFor(CodeSpecializationKind) const;
  258. NativeFunction function() { return m_function; }
  259. NativeFunction constructor() { return m_constructor; }
  260. NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
  261. {
  262. if (kind == CodeForCall)
  263. return function();
  264. ASSERT(kind == CodeForConstruct);
  265. return constructor();
  266. }
  267. static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
  268. {
  269. if (kind == CodeForCall)
  270. return OBJECT_OFFSETOF(NativeExecutable, m_function);
  271. ASSERT(kind == CodeForConstruct);
  272. return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
  273. }
  274. static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
  275. static const ClassInfo s_info;
  276. Intrinsic intrinsic() const;
  277. protected:
  278. #if ENABLE(JIT)
  279. void finishCreation(VM& vm, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
  280. {
  281. Base::finishCreation(vm);
  282. m_jitCodeForCall = callThunk;
  283. m_jitCodeForConstruct = constructThunk;
  284. m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
  285. m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
  286. m_intrinsic = intrinsic;
  287. }
  288. #endif
  289. private:
  290. NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
  291. : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
  292. , m_function(function)
  293. , m_constructor(constructor)
  294. {
  295. }
  296. NativeFunction m_function;
  297. NativeFunction m_constructor;
  298. Intrinsic m_intrinsic;
  299. };
  300. class ScriptExecutable : public ExecutableBase {
  301. public:
  302. typedef ExecutableBase Base;
  303. ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
  304. : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
  305. , m_source(source)
  306. , m_features(isInStrictContext ? StrictModeFeature : 0)
  307. {
  308. }
  309. ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
  310. : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
  311. , m_source(source)
  312. , m_features(isInStrictContext ? StrictModeFeature : 0)
  313. {
  314. }
  315. #if ENABLE(JIT)
  316. static void destroy(JSCell*);
  317. #endif
  318. CodeBlockHash hashFor(CodeSpecializationKind) const;
  319. const SourceCode& source() const { return m_source; }
  320. intptr_t sourceID() const { return m_source.providerID(); }
  321. const String& sourceURL() const { return m_source.provider()->url(); }
  322. int lineNo() const { return m_firstLine; }
  323. int lastLine() const { return m_lastLine; }
  324. unsigned startColumn() const { return m_startColumn; }
  325. bool usesEval() const { return m_features & EvalFeature; }
  326. bool usesArguments() const { return m_features & ArgumentsFeature; }
  327. bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
  328. bool isStrictMode() const { return m_features & StrictModeFeature; }
  329. void unlinkCalls();
  330. CodeFeatures features() const { return m_features; }
  331. static const ClassInfo s_info;
  332. void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
  333. {
  334. m_features = features;
  335. m_hasCapturedVariables = hasCapturedVariables;
  336. m_firstLine = firstLine;
  337. m_lastLine = lastLine;
  338. m_startColumn = startColumn;
  339. }
  340. protected:
  341. void finishCreation(VM& vm)
  342. {
  343. Base::finishCreation(vm);
  344. vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
  345. #if ENABLE(CODEBLOCK_SAMPLING)
  346. if (SamplingTool* sampler = vm.interpreter->sampler())
  347. sampler->notifyOfScope(vm, this);
  348. #endif
  349. }
  350. SourceCode m_source;
  351. CodeFeatures m_features;
  352. bool m_hasCapturedVariables;
  353. int m_firstLine;
  354. int m_lastLine;
  355. unsigned m_startColumn;
  356. };
  357. class EvalExecutable : public ScriptExecutable {
  358. friend class LLIntOffsetsExtractor;
  359. public:
  360. typedef ScriptExecutable Base;
  361. static void destroy(JSCell*);
  362. JSObject* compile(ExecState* exec, JSScope* scope)
  363. {
  364. RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
  365. JSObject* error = 0;
  366. if (!m_evalCodeBlock)
  367. error = compileInternal(exec, scope, JITCode::bottomTierJIT());
  368. ASSERT(!error == !!m_evalCodeBlock);
  369. return error;
  370. }
  371. JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
  372. #if ENABLE(JIT)
  373. void jettisonOptimizedCode(VM&);
  374. bool jitCompile(ExecState*);
  375. #endif
  376. EvalCodeBlock& generatedBytecode()
  377. {
  378. ASSERT(m_evalCodeBlock);
  379. return *m_evalCodeBlock;
  380. }
  381. static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
  382. {
  383. EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
  384. executable->finishCreation(exec->vm());
  385. return executable;
  386. }
  387. #if ENABLE(JIT)
  388. JITCode& generatedJITCode()
  389. {
  390. return generatedJITCodeForCall();
  391. }
  392. #endif
  393. static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
  394. {
  395. return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
  396. }
  397. static const ClassInfo s_info;
  398. void unlinkCalls();
  399. void clearCode();
  400. ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
  401. private:
  402. static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
  403. EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
  404. JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
  405. static void visitChildren(JSCell*, SlotVisitor&);
  406. OwnPtr<EvalCodeBlock> m_evalCodeBlock;
  407. WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
  408. RefPtr<CodeCache> m_codeCache;
  409. };
  410. class ProgramExecutable : public ScriptExecutable {
  411. friend class LLIntOffsetsExtractor;
  412. public:
  413. typedef ScriptExecutable Base;
  414. static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
  415. {
  416. ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
  417. executable->finishCreation(exec->vm());
  418. return executable;
  419. }
  420. JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
  421. static void destroy(JSCell*);
  422. JSObject* compile(ExecState* exec, JSScope* scope)
  423. {
  424. RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
  425. JSObject* error = 0;
  426. if (!m_programCodeBlock)
  427. error = compileInternal(exec, scope, JITCode::bottomTierJIT());
  428. ASSERT(!error == !!m_programCodeBlock);
  429. return error;
  430. }
  431. JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
  432. #if ENABLE(JIT)
  433. void jettisonOptimizedCode(VM&);
  434. bool jitCompile(ExecState*);
  435. #endif
  436. ProgramCodeBlock& generatedBytecode()
  437. {
  438. ASSERT(m_programCodeBlock);
  439. return *m_programCodeBlock;
  440. }
  441. JSObject* checkSyntax(ExecState*);
  442. #if ENABLE(JIT)
  443. JITCode& generatedJITCode()
  444. {
  445. return generatedJITCodeForCall();
  446. }
  447. #endif
  448. static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
  449. {
  450. return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
  451. }
  452. static const ClassInfo s_info;
  453. void unlinkCalls();
  454. void clearCode();
  455. ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
  456. private:
  457. static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
  458. ProgramExecutable(ExecState*, const SourceCode&);
  459. enum ConstantMode { IsConstant, IsVariable };
  460. enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
  461. int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
  462. JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
  463. static void visitChildren(JSCell*, SlotVisitor&);
  464. WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
  465. OwnPtr<ProgramCodeBlock> m_programCodeBlock;
  466. };
  467. class FunctionExecutable : public ScriptExecutable {
  468. friend class JIT;
  469. friend class LLIntOffsetsExtractor;
  470. public:
  471. typedef ScriptExecutable Base;
  472. static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
  473. {
  474. FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
  475. executable->finishCreation(vm);
  476. return executable;
  477. }
  478. static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
  479. static void destroy(JSCell*);
  480. UnlinkedFunctionExecutable* unlinkedExecutable()
  481. {
  482. return m_unlinkedExecutable.get();
  483. }
  484. // Returns either call or construct bytecode. This can be appropriate
  485. // for answering questions that that don't vary between call and construct --
  486. // for example, argumentsRegister().
  487. FunctionCodeBlock& generatedBytecode()
  488. {
  489. if (m_codeBlockForCall)
  490. return *m_codeBlockForCall;
  491. ASSERT(m_codeBlockForConstruct);
  492. return *m_codeBlockForConstruct;
  493. }
  494. PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
  495. JSObject* compileForCall(ExecState* exec, JSScope* scope)
  496. {
  497. RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
  498. JSObject* error = 0;
  499. if (!m_codeBlockForCall)
  500. error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
  501. ASSERT(!error == !!m_codeBlockForCall);
  502. return error;
  503. }
  504. JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex);
  505. #if ENABLE(JIT)
  506. void jettisonOptimizedCodeForCall(VM&);
  507. bool jitCompileForCall(ExecState*);
  508. #endif
  509. bool isGeneratedForCall() const
  510. {
  511. return m_codeBlockForCall;
  512. }
  513. FunctionCodeBlock& generatedBytecodeForCall()
  514. {
  515. ASSERT(m_codeBlockForCall);
  516. return *m_codeBlockForCall;
  517. }
  518. JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
  519. {
  520. RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
  521. JSObject* error = 0;
  522. if (!m_codeBlockForConstruct)
  523. error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
  524. ASSERT(!error == !!m_codeBlockForConstruct);
  525. return error;
  526. }
  527. JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex);
  528. #if ENABLE(JIT)
  529. void jettisonOptimizedCodeForConstruct(VM&);
  530. bool jitCompileForConstruct(ExecState*);
  531. #endif
  532. bool isGeneratedForConstruct() const
  533. {
  534. return m_codeBlockForConstruct;
  535. }
  536. FunctionCodeBlock& generatedBytecodeForConstruct()
  537. {
  538. ASSERT(m_codeBlockForConstruct);
  539. return *m_codeBlockForConstruct;
  540. }
  541. JSObject* compileFor(ExecState* exec, JSScope* scope, CodeSpecializationKind kind)
  542. {
  543. ASSERT(exec->callee());
  544. ASSERT(exec->callee()->inherits(&JSFunction::s_info));
  545. ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
  546. if (kind == CodeForCall)
  547. return compileForCall(exec, scope);
  548. ASSERT(kind == CodeForConstruct);
  549. return compileForConstruct(exec, scope);
  550. }
  551. JSObject* compileOptimizedFor(ExecState* exec, JSScope* scope, unsigned bytecodeIndex, CodeSpecializationKind kind)
  552. {
  553. ASSERT(exec->callee());
  554. ASSERT(exec->callee()->inherits(&JSFunction::s_info));
  555. ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
  556. if (kind == CodeForCall)
  557. return compileOptimizedForCall(exec, scope, bytecodeIndex);
  558. ASSERT(kind == CodeForConstruct);
  559. return compileOptimizedForConstruct(exec, scope, bytecodeIndex);
  560. }
  561. #if ENABLE(JIT)
  562. void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
  563. {
  564. if (kind == CodeForCall)
  565. jettisonOptimizedCodeForCall(vm);
  566. else {
  567. ASSERT(kind == CodeForConstruct);
  568. jettisonOptimizedCodeForConstruct(vm);
  569. }
  570. }
  571. bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind)
  572. {
  573. if (kind == CodeForCall)
  574. return jitCompileForCall(exec);
  575. ASSERT(kind == CodeForConstruct);
  576. return jitCompileForConstruct(exec);
  577. }
  578. #endif
  579. bool isGeneratedFor(CodeSpecializationKind kind)
  580. {
  581. if (kind == CodeForCall)
  582. return isGeneratedForCall();
  583. ASSERT(kind == CodeForConstruct);
  584. return isGeneratedForConstruct();
  585. }
  586. FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
  587. {
  588. if (kind == CodeForCall)
  589. return generatedBytecodeForCall();
  590. ASSERT(kind == CodeForConstruct);
  591. return generatedBytecodeForConstruct();
  592. }
  593. FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
  594. FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
  595. {
  596. return baselineCodeBlockFor(kind);
  597. }
  598. const Identifier& name() { return m_unlinkedExecutable->name(); }
  599. const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
  600. JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
  601. size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
  602. String paramString() const;
  603. SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
  604. void clearCodeIfNotCompiling();
  605. void clearUnlinkedCodeForRecompilationIfNotCompiling();
  606. static void visitChildren(JSCell*, SlotVisitor&);
  607. static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
  608. {
  609. return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
  610. }
  611. static const ClassInfo s_info;
  612. void unlinkCalls();
  613. void clearCode();
  614. private:
  615. FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
  616. JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
  617. JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
  618. OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
  619. {
  620. if (kind == CodeForCall)
  621. return m_codeBlockForCall;
  622. ASSERT(kind == CodeForConstruct);
  623. return m_codeBlockForConstruct;
  624. }
  625. bool isCompiling()
  626. {
  627. #if ENABLE(JIT)
  628. if (!m_jitCodeForCall && m_codeBlockForCall)
  629. return true;
  630. if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
  631. return true;
  632. #endif
  633. return false;
  634. }
  635. static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
  636. WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
  637. OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
  638. OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
  639. };
  640. inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
  641. : Base(vm, scope->globalObject()->functionStructure())
  642. , m_executable(vm, this, executable)
  643. , m_scope(vm, this, scope)
  644. , m_allocationProfileWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
  645. {
  646. }
  647. inline FunctionExecutable* JSFunction::jsExecutable() const
  648. {
  649. ASSERT(!isHostFunctionNonInline());
  650. return static_cast<FunctionExecutable*>(m_executable.get());
  651. }
  652. inline bool JSFunction::isHostFunction() const
  653. {
  654. ASSERT(m_executable);
  655. return m_executable->isHostFunction();
  656. }
  657. inline NativeFunction JSFunction::nativeFunction()
  658. {
  659. ASSERT(isHostFunction());
  660. return static_cast<NativeExecutable*>(m_executable.get())->function();
  661. }
  662. inline NativeFunction JSFunction::nativeConstructor()
  663. {
  664. ASSERT(isHostFunction());
  665. return static_cast<NativeExecutable*>(m_executable.get())->constructor();
  666. }
  667. inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
  668. {
  669. JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
  670. if (!function || !function->isHostFunction())
  671. return false;
  672. return function->nativeFunction() == nativeFunction;
  673. }
  674. inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
  675. {
  676. switch (executable->structure()->typeInfo().type()) {
  677. case EvalExecutableType:
  678. return jsCast<EvalExecutable*>(executable)->clearCode();
  679. case ProgramExecutableType:
  680. return jsCast<ProgramExecutable*>(executable)->clearCode();
  681. case FunctionExecutableType:
  682. return jsCast<FunctionExecutable*>(executable)->clearCode();
  683. default:
  684. return jsCast<NativeExecutable*>(executable)->clearCode();
  685. }
  686. }
  687. inline void ScriptExecutable::unlinkCalls()
  688. {
  689. switch (structure()->typeInfo().type()) {
  690. case EvalExecutableType:
  691. return jsCast<EvalExecutable*>(this)->unlinkCalls();
  692. case ProgramExecutableType:
  693. return jsCast<ProgramExecutable*>(this)->unlinkCalls();
  694. case FunctionExecutableType:
  695. return jsCast<FunctionExecutable*>(this)->unlinkCalls();
  696. default:
  697. RELEASE_ASSERT_NOT_REACHED();
  698. }
  699. }
  700. }
  701. #endif