+
+ const Identifier& variable(unsigned index) { return unlinkedEvalCodeBlock()->variable(index); }
+ unsigned numVariables() { return unlinkedEvalCodeBlock()->numVariables(); }
+
+#if ENABLE(JIT)
+protected:
+ virtual CodeBlock* replacement() override;
+ virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
+
+private:
+ UnlinkedEvalCodeBlock* unlinkedEvalCodeBlock() const { return jsCast<UnlinkedEvalCodeBlock*>(unlinkedCodeBlock()); }
+};
+
+class FunctionCodeBlock : public CodeBlock {
+public:
+ FunctionCodeBlock(CopyParsedBlockTag, FunctionCodeBlock& other)
+ : CodeBlock(CopyParsedBlock, other)
+ {
+ }
+
+ FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
+ : CodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
+ {
+ }
+
+#if ENABLE(JIT)
+protected:
+ virtual CodeBlock* replacement() override;
+ virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
+};
+
+inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
+{
+ RELEASE_ASSERT(inlineCallFrame);
+ ExecutableBase* executable = inlineCallFrame->executable.get();
+ RELEASE_ASSERT(executable->structure()->classInfo() == FunctionExecutable::info());
+ return static_cast<FunctionExecutable*>(executable)->baselineCodeBlockFor(inlineCallFrame->specializationKind());
+}
+
+inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
+{
+ if (codeOrigin.inlineCallFrame)
+ return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame);
+ return baselineCodeBlock;
+}
+
+inline Register& ExecState::r(int index)
+{
+ CodeBlock* codeBlock = this->codeBlock();
+ if (codeBlock->isConstantRegisterIndex(index))
+ return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index));
+ return this[index];
+}
+
+inline Register& ExecState::r(VirtualRegister reg)
+{
+ return r(reg.offset());
+}
+
+inline Register& ExecState::uncheckedR(int index)
+{
+ RELEASE_ASSERT(index < FirstConstantRegisterIndex);
+ return this[index];
+}
+
+inline Register& ExecState::uncheckedR(VirtualRegister reg)
+{
+ return uncheckedR(reg.offset());
+}
+
+inline void CodeBlockSet::mark(void* candidateCodeBlock)
+{
+ // We have to check for 0 and -1 because those are used by the HashMap as markers.
+ uintptr_t value = reinterpret_cast<uintptr_t>(candidateCodeBlock);
+
+ // This checks for both of those nasty cases in one go.
+ // 0 + 1 = 1
+ // -1 + 1 = 0
+ if (value + 1 <= 1)
+ return;
+
+ CodeBlock* codeBlock = static_cast<CodeBlock*>(candidateCodeBlock);
+ if (!m_oldCodeBlocks.contains(codeBlock) && !m_newCodeBlocks.contains(codeBlock))
+ return;
+
+ mark(codeBlock);
+}
+
+inline void CodeBlockSet::mark(CodeBlock* codeBlock)
+{
+ if (!codeBlock)
+ return;
+
+ if (codeBlock->m_mayBeExecuting)
+ return;
+
+ codeBlock->m_mayBeExecuting = true;
+ // We might not have cleared the marks for this CodeBlock, but we need to visit it.
+ codeBlock->m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
+#if ENABLE(GGC)
+ m_currentlyExecuting.append(codeBlock);
+#endif
+}
+
+template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Functor&& functor)
+{
+ switch (type()) {
+ case ProgramExecutableType: {
+ if (CodeBlock* codeBlock = jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get())
+ codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
+ break;
+ }
+
+ case EvalExecutableType: {
+ if (CodeBlock* codeBlock = jsCast<EvalExecutable*>(this)->m_evalCodeBlock.get())
+ codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
+ break;
+ }
+
+ case FunctionExecutableType: {
+ Functor f(std::forward<Functor>(functor));
+ FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
+ if (CodeBlock* codeBlock = executable->m_codeBlockForCall.get())
+ codeBlock->forEachRelatedCodeBlock(f);
+ if (CodeBlock* codeBlock = executable->m_codeBlockForConstruct.get())
+ codeBlock->forEachRelatedCodeBlock(f);
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+}