summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode/CodeBlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/bytecode/CodeBlock.h')
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h1061
1 files changed, 461 insertions, 600 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index 96cee40c7..0d9868079 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
@@ -11,7 +11,7 @@
* 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.
- * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -38,30 +38,34 @@
#include "CallReturnOffsetToBytecodeOffset.h"
#include "CodeBlockHash.h"
#include "CodeBlockSet.h"
+#include "ConcurrentJITLock.h"
#include "CodeOrigin.h"
#include "CodeType.h"
#include "CompactJITCodeMap.h"
-#include "ConcurrentJITLock.h"
#include "DFGCommon.h"
+#include "DFGCommonData.h"
#include "DFGExitProfile.h"
+#include "DFGMinifiedGraph.h"
+#include "DFGOSREntry.h"
+#include "DFGOSRExit.h"
+#include "DFGVariableEventStream.h"
#include "DeferredCompilationCallback.h"
#include "EvalCodeCache.h"
#include "ExecutionCounter.h"
#include "ExpressionRangeInfo.h"
#include "HandlerInfo.h"
+#include "ObjectAllocationProfile.h"
+#include "Options.h"
+#include "Operations.h"
+#include "PutPropertySlot.h"
#include "Instruction.h"
#include "JITCode.h"
#include "JITWriteBarrier.h"
-#include "JSCell.h"
#include "JSGlobalObject.h"
#include "JumpTable.h"
#include "LLIntCallLinkInfo.h"
#include "LazyOperandValueProfile.h"
-#include "ObjectAllocationProfile.h"
-#include "Options.h"
#include "ProfilerCompilation.h"
-#include "ProfilerJettisonReason.h"
-#include "PutPropertySlot.h"
#include "RegExpObject.h"
#include "StructureStubInfo.h"
#include "UnconditionalFinalizer.h"
@@ -69,8 +73,8 @@
#include "VirtualRegister.h"
#include "Watchpoint.h"
#include <wtf/Bag.h>
-#include <wtf/FastBitVector.h>
#include <wtf/FastMalloc.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/RefCountedArray.h>
#include <wtf/RefPtr.h>
#include <wtf/SegmentedVector.h>
@@ -81,51 +85,31 @@ namespace JSC {
class ExecState;
class LLIntOffsetsExtractor;
-class RegisterAtOffsetList;
-class TypeLocation;
-class JSModuleEnvironment;
-class PCToCodeOriginMap;
+class RepatchBuffer;
+
+inline VirtualRegister unmodifiedArgumentsRegister(VirtualRegister argumentsRegister) { return VirtualRegister(argumentsRegister.offset() + 1); }
+
+static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };
-class CodeBlock : public JSCell {
- typedef JSCell Base;
+class CodeBlock : public ThreadSafeRefCounted<CodeBlock>, public UnconditionalFinalizer, public WeakReferenceHarvester {
+ WTF_MAKE_FAST_ALLOCATED;
friend class BytecodeLivenessAnalysis;
friend class JIT;
friend class LLIntOffsetsExtractor;
-
- class UnconditionalFinalizer : public JSC::UnconditionalFinalizer {
- virtual void finalizeUnconditionally() override;
- };
-
- class WeakReferenceHarvester : public JSC::WeakReferenceHarvester {
- virtual void visitWeakReferences(SlotVisitor&) override;
- };
-
public:
enum CopyParsedBlockTag { CopyParsedBlock };
-
- static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
-
- DECLARE_INFO;
-
protected:
- CodeBlock(VM*, Structure*, CopyParsedBlockTag, CodeBlock& other);
- CodeBlock(VM*, Structure*, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
-#if ENABLE(WEBASSEMBLY)
- CodeBlock(VM*, Structure*, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);
-#endif
-
- void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);
- void finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
-#if ENABLE(WEBASSEMBLY)
- void finishCreation(VM&, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);
-#endif
+ CodeBlock(CopyParsedBlockTag, CodeBlock& other);
+
+ CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
WriteBarrier<JSGlobalObject> m_globalObject;
+ Heap* m_heap;
public:
- JS_EXPORT_PRIVATE ~CodeBlock();
+ JS_EXPORT_PRIVATE virtual ~CodeBlock();
UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
@@ -133,7 +117,6 @@ public:
CodeBlockHash hash() const;
bool hasHash() const;
bool isSafeToComputeHash() const;
- CString hashAsStringIfPossible() const;
CString sourceCodeForTools() const; // Not quite the actual source we parsed; this will do things like prefix the source for a function with a reified signature.
CString sourceCodeOnOneLine() const; // As sourceCodeForTools(), but replaces all whitespace runs with a single space.
void dumpAssumingJITType(PrintStream&, JITCode::JITType) const;
@@ -142,58 +125,28 @@ public:
int numParameters() const { return m_numParameters; }
void setNumParameters(int newValue);
- int numCalleeLocals() const { return m_numCalleeLocals; }
-
int* addressOfNumParameters() { return &m_numParameters; }
static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
- CodeBlock* alternative() const { return static_cast<CodeBlock*>(m_alternative.get()); }
- void setAlternative(VM&, CodeBlock*);
-
- template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)
- {
- Functor f(std::forward<Functor>(functor));
- Vector<CodeBlock*, 4> codeBlocks;
- codeBlocks.append(this);
-
- while (!codeBlocks.isEmpty()) {
- CodeBlock* currentCodeBlock = codeBlocks.takeLast();
- f(currentCodeBlock);
-
- if (CodeBlock* alternative = currentCodeBlock->alternative())
- codeBlocks.append(alternative);
- if (CodeBlock* osrEntryBlock = currentCodeBlock->specialOSREntryBlockOrNull())
- codeBlocks.append(osrEntryBlock);
- }
- }
+ CodeBlock* alternative() { return m_alternative.get(); }
+ PassRefPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
+ void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
CodeSpecializationKind specializationKind() const
{
return specializationFromIsConstruct(m_isConstructor);
}
-
- CodeBlock* alternativeForJettison();
- JS_EXPORT_PRIVATE CodeBlock* baselineAlternative();
+
+ CodeBlock* baselineAlternative();
// FIXME: Get rid of this.
// https://bugs.webkit.org/show_bug.cgi?id=123677
CodeBlock* baselineVersion();
- static size_t estimatedSize(JSCell*);
- static void visitChildren(JSCell*, SlotVisitor&);
- void visitChildren(SlotVisitor&);
- void visitWeakly(SlotVisitor&);
- void clearVisitWeaklyHasBeenCalled();
-
- void dumpSource();
- void dumpSource(PrintStream&);
-
- void dumpBytecode();
- void dumpBytecode(PrintStream&);
- void dumpBytecode(
- PrintStream&, unsigned bytecodeOffset,
- const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap());
- void dumpExceptionHandlers(PrintStream&);
+ void visitAggregate(SlotVisitor&);
+
+ void dumpBytecode(PrintStream& = WTF::dataFile());
+ void dumpBytecode(PrintStream&, unsigned bytecodeOffset);
void printStructures(PrintStream&, const Instruction*);
void printStructure(PrintStream&, const char* name, const Instruction*, int operand);
@@ -216,72 +169,72 @@ public:
return index >= m_numVars;
}
- enum class RequiredHandler {
- CatchHandler,
- AnyHandler
- };
- HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);
- HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);
- void removeExceptionHandlerForCallSite(CallSiteIndex);
+ HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
unsigned lineNumberForBytecodeOffset(unsigned bytecodeOffset);
unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset);
void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
int& startOffset, int& endOffset, unsigned& line, unsigned& column);
- void getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result);
- void getStubInfoMap(StubInfoMap& result);
-
- void getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result);
- void getCallLinkInfoMap(CallLinkInfoMap& result);
-
- void getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result);
- void getByValInfoMap(ByValInfoMap& result);
-
#if ENABLE(JIT)
- StructureStubInfo* addStubInfo(AccessType);
- Bag<StructureStubInfo>::iterator stubInfoBegin() { return m_stubInfos.begin(); }
- Bag<StructureStubInfo>::iterator stubInfoEnd() { return m_stubInfos.end(); }
+ StructureStubInfo* addStubInfo();
+ Bag<StructureStubInfo>::iterator begin() { return m_stubInfos.begin(); }
+ Bag<StructureStubInfo>::iterator end() { return m_stubInfos.end(); }
+
+ void resetStub(StructureStubInfo&);
- // O(n) operation. Use getStubInfoMap() unless you really only intend to get one
- // stub info.
- StructureStubInfo* findStubInfo(CodeOrigin);
+ void getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result);
- ByValInfo* addByValInfo();
+ ByValInfo& getByValInfo(unsigned bytecodeIndex)
+ {
+ return *(binarySearch<ByValInfo, unsigned>(m_byValInfos, m_byValInfos.size(), bytecodeIndex, getByValInfoBytecodeIndex));
+ }
- CallLinkInfo* addCallLinkInfo();
- Bag<CallLinkInfo>::iterator callLinkInfosBegin() { return m_callLinkInfos.begin(); }
- Bag<CallLinkInfo>::iterator callLinkInfosEnd() { return m_callLinkInfos.end(); }
+ CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
+ {
+ return *(binarySearch<CallLinkInfo, void*>(m_callLinkInfos, m_callLinkInfos.size(), returnAddress.value(), getCallLinkInfoReturnLocation));
+ }
- // This is a slow function call used primarily for compiling OSR exits in the case
- // that there had been inlining. Chances are if you want to use this, you're really
- // looking for a CallLinkInfoMap to amortize the cost of calling this.
- CallLinkInfo* getCallLinkInfoForBytecodeIndex(unsigned bytecodeIndex);
+ CallLinkInfo& getCallLinkInfo(unsigned bytecodeIndex)
+ {
+ ASSERT(!JITCode::isOptimizingJIT(jitType()));
+ return *(binarySearch<CallLinkInfo, unsigned>(m_callLinkInfos, m_callLinkInfos.size(), bytecodeIndex, getCallLinkInfoBytecodeIndex));
+ }
#endif // ENABLE(JIT)
void unlinkIncomingCalls();
#if ENABLE(JIT)
+ void unlinkCalls();
+
void linkIncomingCall(ExecState* callerFrame, CallLinkInfo*);
- void linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode*);
+
+ bool isIncomingCallAlreadyLinked(CallLinkInfo* incoming)
+ {
+ return m_incomingCalls.isOnList(incoming);
+ }
#endif // ENABLE(JIT)
+#if ENABLE(LLINT)
void linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo*);
+#endif // ENABLE(LLINT)
- void setJITCodeMap(std::unique_ptr<CompactJITCodeMap> jitCodeMap)
+ void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
{
- m_jitCodeMap = WTFMove(jitCodeMap);
+ m_jitCodeMap = jitCodeMap;
}
CompactJITCodeMap* jitCodeMap()
{
return m_jitCodeMap.get();
}
-
+
unsigned bytecodeOffset(Instruction* returnAddress)
{
RELEASE_ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());
return static_cast<Instruction*>(returnAddress) - instructions().begin();
}
+ bool isNumericCompareFunction() { return m_unlinkedCode->isNumericCompareFunction(); }
+
unsigned numberOfInstructions() const { return m_instructions.size(); }
RefCountedArray<Instruction>& instructions() { return m_instructions; }
const RefCountedArray<Instruction>& instructions() const { return m_instructions; }
@@ -292,19 +245,28 @@ public:
unsigned instructionCount() const { return m_instructions.size(); }
+ int argumentIndexAfterCapture(size_t argument);
+
+ bool hasSlowArguments();
+ const SlowArgument* machineSlowArguments();
+
+ // Exactly equivalent to codeBlock->ownerExecutable()->installCode(codeBlock);
+ void install();
+
// Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())
- CodeBlock* newReplacement();
+ PassRefPtr<CodeBlock> newReplacement();
- void setJITCode(PassRefPtr<JITCode> code)
+ void setJITCode(PassRefPtr<JITCode> code, MacroAssemblerCodePtr codeWithArityCheck)
{
- ASSERT(heap()->isDeferred());
- heap()->reportExtraMemoryAllocated(code->size());
+ ASSERT(m_heap->isDeferred());
+ m_heap->reportExtraMemoryCost(code->size());
ConcurrentJITLocker locker(m_lock);
WTF::storeStoreFence(); // This is probably not needed because the lock will also do something similar, but it's good to be paranoid.
m_jitCode = code;
+ m_jitCodeWithArityCheck = codeWithArityCheck;
}
PassRefPtr<JITCode> jitCode() { return m_jitCode; }
- static ptrdiff_t jitCodeOffset() { return OBJECT_OFFSETOF(CodeBlock, m_jitCode); }
+ MacroAssemblerCodePtr jitCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
JITCode::JITType jitType() const
{
JITCode* jitCode = m_jitCode.get();
@@ -320,20 +282,24 @@ public:
}
#if ENABLE(JIT)
- CodeBlock* replacement();
+ virtual CodeBlock* replacement() = 0;
- DFG::CapabilityLevel computeCapabilityLevel();
- DFG::CapabilityLevel capabilityLevel();
- DFG::CapabilityLevel capabilityLevelState() { return static_cast<DFG::CapabilityLevel>(m_capabilityLevelState); }
+ virtual DFG::CapabilityLevel capabilityLevelInternal() = 0;
+ DFG::CapabilityLevel capabilityLevel()
+ {
+ DFG::CapabilityLevel result = capabilityLevelInternal();
+ m_capabilityLevelState = result;
+ return result;
+ }
+ DFG::CapabilityLevel capabilityLevelState() { return m_capabilityLevelState; }
bool hasOptimizedReplacement(JITCode::JITType typeToReplace);
bool hasOptimizedReplacement(); // the typeToReplace is my JITType
#endif
- void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr);
+ void jettison(ReoptimizationMode = DontCountReoptimization);
- ExecutableBase* ownerExecutable() const { return m_ownerExecutable.get(); }
- ScriptExecutable* ownerScriptExecutable() const { return jsCast<ScriptExecutable*>(m_ownerExecutable.get()); }
+ ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
void setVM(VM* vm) { m_vm = vm; }
VM* vm() { return m_vm; }
@@ -341,24 +307,78 @@ public:
void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
VirtualRegister thisRegister() const { return m_thisRegister; }
+ bool needsFullScopeChain() const { return m_unlinkedCode->needsFullScopeChain(); }
bool usesEval() const { return m_unlinkedCode->usesEval(); }
- void setScopeRegister(VirtualRegister scopeRegister)
+ void setArgumentsRegister(VirtualRegister argumentsRegister)
+ {
+ ASSERT(argumentsRegister.isValid());
+ m_argumentsRegister = argumentsRegister;
+ ASSERT(usesArguments());
+ }
+ VirtualRegister argumentsRegister() const
+ {
+ ASSERT(usesArguments());
+ return m_argumentsRegister;
+ }
+ VirtualRegister uncheckedArgumentsRegister()
+ {
+ if (!usesArguments())
+ return VirtualRegister();
+ return argumentsRegister();
+ }
+ void setActivationRegister(VirtualRegister activationRegister)
+ {
+ m_activationRegister = activationRegister;
+ }
+
+ VirtualRegister activationRegister() const
+ {
+ ASSERT(needsFullScopeChain());
+ return m_activationRegister;
+ }
+
+ VirtualRegister uncheckedActivationRegister()
{
- ASSERT(scopeRegister.isLocal() || !scopeRegister.isValid());
- m_scopeRegister = scopeRegister;
+ if (!needsFullScopeChain())
+ return VirtualRegister();
+ return activationRegister();
}
- VirtualRegister scopeRegister() const
+ bool usesArguments() const { return m_argumentsRegister.isValid(); }
+
+ bool needsActivation() const
+ {
+ return m_needsActivation;
+ }
+
+ unsigned captureCount() const
{
- return m_scopeRegister;
+ if (!symbolTable())
+ return 0;
+ return symbolTable()->captureCount();
+ }
+
+ int captureStart() const
+ {
+ if (!symbolTable())
+ return 0;
+ return symbolTable()->captureStart();
}
- CodeType codeType() const
+ int captureEnd() const
{
- return static_cast<CodeType>(m_codeType);
+ if (!symbolTable())
+ return 0;
+ return symbolTable()->captureEnd();
}
+ bool isCaptured(VirtualRegister operand, InlineCallFrame* = 0) const;
+
+ int framePointerOffsetToGetActivationRegisters(int machineCaptureStart);
+ int framePointerOffsetToGetActivationRegisters();
+
+ CodeType codeType() const { return m_unlinkedCode->codeType(); }
PutPropertySlot::Context putByIdContext() const
{
if (codeType() == EvalCode)
@@ -373,8 +393,20 @@ public:
size_t numberOfJumpTargets() const { return m_unlinkedCode->numberOfJumpTargets(); }
unsigned jumpTarget(int index) const { return m_unlinkedCode->jumpTarget(index); }
+ void clearEvalCache();
+
String nameForRegister(VirtualRegister);
+#if ENABLE(JIT)
+ void setNumberOfByValInfos(size_t size) { m_byValInfos.resizeToFit(size); }
+ size_t numberOfByValInfos() const { return m_byValInfos.size(); }
+ ByValInfo& byValInfo(size_t index) { return m_byValInfos[index]; }
+
+ void setNumberOfCallLinkInfos(size_t size) { m_callLinkInfos.resizeToFit(size); }
+ size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
+ CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
+#endif
+
unsigned numberOfArgumentValueProfiles()
{
ASSERT(m_numParameters >= 0);
@@ -390,7 +422,17 @@ public:
unsigned numberOfValueProfiles() { return m_valueProfiles.size(); }
ValueProfile* valueProfile(int index) { return &m_valueProfiles[index]; }
- ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset);
+ ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset)
+ {
+ ValueProfile* result = binarySearch<ValueProfile, int>(
+ m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
+ getValueProfileBytecodeOffset<ValueProfile>);
+ ASSERT(result->m_bytecodeOffset != -1);
+ ASSERT(instructions()[bytecodeOffset + opcodeLength(
+ m_vm->interpreter->getOpcodeID(
+ instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result);
+ return result;
+ }
SpeculatedType valueProfilePredictionForBytecodeOffset(const ConcurrentJITLocker& locker, int bytecodeOffset)
{
return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction(locker);
@@ -413,14 +455,19 @@ public:
return &m_rareCaseProfiles.last();
}
unsigned numberOfRareCaseProfiles() { return m_rareCaseProfiles.size(); }
- RareCaseProfile* rareCaseProfileForBytecodeOffset(int bytecodeOffset);
- unsigned rareCaseProfileCountForBytecodeOffset(int bytecodeOffset);
+ RareCaseProfile* rareCaseProfile(int index) { return &m_rareCaseProfiles[index]; }
+ RareCaseProfile* rareCaseProfileForBytecodeOffset(int bytecodeOffset)
+ {
+ return tryBinarySearch<RareCaseProfile, int>(
+ m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset,
+ getRareCaseProfileBytecodeOffset);
+ }
bool likelyToTakeSlowCase(int bytecodeOffset)
{
if (!hasBaselineJITProfiling())
return false;
- unsigned value = rareCaseProfileCountForBytecodeOffset(bytecodeOffset);
+ unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return value >= Options::likelyToTakeSlowCaseMinimumCount();
}
@@ -428,42 +475,60 @@ public:
{
if (!hasBaselineJITProfiling())
return false;
- unsigned value = rareCaseProfileCountForBytecodeOffset(bytecodeOffset);
+ unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return value >= Options::couldTakeSlowCaseMinimumCount();
}
- ResultProfile* ensureResultProfile(int bytecodeOffset)
+ RareCaseProfile* addSpecialFastCaseProfile(int bytecodeOffset)
+ {
+ m_specialFastCaseProfiles.append(RareCaseProfile(bytecodeOffset));
+ return &m_specialFastCaseProfiles.last();
+ }
+ unsigned numberOfSpecialFastCaseProfiles() { return m_specialFastCaseProfiles.size(); }
+ RareCaseProfile* specialFastCaseProfile(int index) { return &m_specialFastCaseProfiles[index]; }
+ RareCaseProfile* specialFastCaseProfileForBytecodeOffset(int bytecodeOffset)
{
- ResultProfile* profile = resultProfileForBytecodeOffset(bytecodeOffset);
- if (!profile) {
- m_resultProfiles.append(ResultProfile(bytecodeOffset));
- profile = &m_resultProfiles.last();
- ASSERT(&m_resultProfiles.last() == &m_resultProfiles[m_resultProfiles.size() - 1]);
- if (!m_bytecodeOffsetToResultProfileIndexMap)
- m_bytecodeOffsetToResultProfileIndexMap = std::make_unique<BytecodeOffsetToResultProfileIndexMap>();
- m_bytecodeOffsetToResultProfileIndexMap->add(bytecodeOffset, m_resultProfiles.size() - 1);
- }
- return profile;
+ return tryBinarySearch<RareCaseProfile, int>(
+ m_specialFastCaseProfiles, m_specialFastCaseProfiles.size(), bytecodeOffset,
+ getRareCaseProfileBytecodeOffset);
}
- unsigned numberOfResultProfiles() { return m_resultProfiles.size(); }
- ResultProfile* resultProfileForBytecodeOffset(int bytecodeOffset);
- unsigned specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset)
+ bool likelyToTakeSpecialFastCase(int bytecodeOffset)
{
- ResultProfile* profile = resultProfileForBytecodeOffset(bytecodeOffset);
- if (!profile)
- return 0;
- return profile->specialFastPathCount();
+ if (!hasBaselineJITProfiling())
+ return false;
+ unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+ return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount();
}
bool couldTakeSpecialFastCase(int bytecodeOffset)
{
if (!hasBaselineJITProfiling())
return false;
- unsigned specialFastCaseCount = specialFastCaseProfileCountForBytecodeOffset(bytecodeOffset);
+ unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
return specialFastCaseCount >= Options::couldTakeSlowCaseMinimumCount();
}
+ bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
+ {
+ if (!hasBaselineJITProfiling())
+ return false;
+ unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+ unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+ unsigned value = slowCaseCount - specialFastCaseCount;
+ return value >= Options::likelyToTakeSlowCaseMinimumCount();
+ }
+
+ bool likelyToTakeAnySlowCase(int bytecodeOffset)
+ {
+ if (!hasBaselineJITProfiling())
+ return false;
+ unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+ unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+ unsigned value = slowCaseCount + specialFastCaseCount;
+ return value >= Options::likelyToTakeSlowCaseMinimumCount();
+ }
+
unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); }
const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; }
ArrayProfile* addArrayProfile(unsigned bytecodeOffset)
@@ -482,7 +547,10 @@ public:
bool hasExpressionInfo() { return m_unlinkedCode->hasExpressionInfo(); }
#if ENABLE(DFG_JIT)
- Vector<CodeOrigin, 0, UnsafeVectorOverflow>& codeOrigins();
+ Vector<CodeOrigin, 0, UnsafeVectorOverflow>& codeOrigins()
+ {
+ return m_jitCode->dfgCommon()->codeOrigins;
+ }
// Having code origins implies that there has been some inlining.
bool hasCodeOrigins()
@@ -490,16 +558,16 @@ public:
return JITCode::isOptimizingJIT(jitType());
}
- bool canGetCodeOrigin(CallSiteIndex index)
+ bool canGetCodeOrigin(unsigned index)
{
if (!hasCodeOrigins())
return false;
- return index.bits() < codeOrigins().size();
+ return index < codeOrigins().size();
}
- CodeOrigin codeOrigin(CallSiteIndex index)
+ CodeOrigin codeOrigin(unsigned index)
{
- return codeOrigins()[index.bits()];
+ return codeOrigins()[index];
}
bool addFrequentExitSite(const DFG::FrequentExitSite& site)
@@ -508,15 +576,11 @@ public:
ConcurrentJITLocker locker(m_lock);
return m_exitProfile.add(locker, site);
}
-
- bool hasExitSite(const ConcurrentJITLocker& locker, const DFG::FrequentExitSite& site) const
- {
- return m_exitProfile.hasExitSite(locker, site);
- }
+
bool hasExitSite(const DFG::FrequentExitSite& site) const
{
ConcurrentJITLocker locker(m_lock);
- return hasExitSite(locker, site);
+ return m_exitProfile.hasExitSite(locker, site);
}
DFG::ExitProfile& exitProfile() { return m_exitProfile; }
@@ -525,26 +589,44 @@ public:
{
return m_lazyOperandValueProfiles;
}
+#else // ENABLE(DFG_JIT)
+ bool addFrequentExitSite(const DFG::FrequentExitSite&)
+ {
+ return false;
+ }
#endif // ENABLE(DFG_JIT)
// Constant Pool
#if ENABLE(DFG_JIT)
size_t numberOfIdentifiers() const { return m_unlinkedCode->numberOfIdentifiers() + numberOfDFGIdentifiers(); }
- size_t numberOfDFGIdentifiers() const;
- const Identifier& identifier(int index) const;
+ size_t numberOfDFGIdentifiers() const
+ {
+ if (!JITCode::isOptimizingJIT(jitType()))
+ return 0;
+
+ return m_jitCode->dfgCommon()->dfgIdentifiers.size();
+ }
+
+ const Identifier& identifier(int index) const
+ {
+ size_t unlinkedIdentifiers = m_unlinkedCode->numberOfIdentifiers();
+ if (static_cast<unsigned>(index) < unlinkedIdentifiers)
+ return m_unlinkedCode->identifier(index);
+ ASSERT(JITCode::isOptimizingJIT(jitType()));
+ return m_jitCode->dfgCommon()->dfgIdentifiers[index - unlinkedIdentifiers];
+ }
#else
size_t numberOfIdentifiers() const { return m_unlinkedCode->numberOfIdentifiers(); }
const Identifier& identifier(int index) const { return m_unlinkedCode->identifier(index); }
#endif
Vector<WriteBarrier<Unknown>>& constants() { return m_constantRegisters; }
- Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; }
+ size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
unsigned addConstant(JSValue v)
{
unsigned result = m_constantRegisters.size();
m_constantRegisters.append(WriteBarrier<Unknown>());
- m_constantRegisters.last().set(m_globalObject->vm(), this, v);
- m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
+ m_constantRegisters.last().set(m_globalObject->vm(), m_ownerExecutable.get(), v);
return result;
}
@@ -552,19 +634,19 @@ public:
{
unsigned result = m_constantRegisters.size();
m_constantRegisters.append(WriteBarrier<Unknown>());
- m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
return result;
}
+ bool findConstant(JSValue, unsigned& result);
+ unsigned addOrFindConstant(JSValue);
WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
- ALWAYS_INLINE SourceCodeRepresentation constantSourceCodeRepresentation(int index) const { return m_constantsSourceCodeRepresentation[index - FirstConstantRegisterIndex]; }
FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
int numberOfFunctionDecls() { return m_functionDecls.size(); }
FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
-
+
RegExp* regexp(int index) const { return m_unlinkedCode->regexp(index); }
unsigned numberOfConstantBuffers() const
@@ -591,26 +673,15 @@ public:
return constantBufferAsVector(index).data();
}
- Heap* heap() const { return &m_vm->heap; }
JSGlobalObject* globalObject() { return m_globalObject.get(); }
JSGlobalObject* globalObjectFor(CodeOrigin);
BytecodeLivenessAnalysis& livenessAnalysis()
{
- {
- ConcurrentJITLocker locker(m_lock);
- if (!!m_livenessAnalysis)
- return *m_livenessAnalysis;
- }
- std::unique_ptr<BytecodeLivenessAnalysis> analysis =
- std::make_unique<BytecodeLivenessAnalysis>(this);
- {
- ConcurrentJITLocker locker(m_lock);
- if (!m_livenessAnalysis)
- m_livenessAnalysis = WTFMove(analysis);
- return *m_livenessAnalysis;
- }
+ if (!m_livenessAnalysis)
+ m_livenessAnalysis = std::make_unique<BytecodeLivenessAnalysis>(this);
+ return *m_livenessAnalysis;
}
void validate();
@@ -631,17 +702,8 @@ public:
StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
StringJumpTable& stringSwitchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
- // Live callee registers at yield points.
- const FastBitVector& liveCalleeLocalsAtYield(unsigned index) const
- {
- RELEASE_ASSERT(m_rareData);
- return m_rareData->m_liveCalleeLocalsAtYield[index];
- }
- FastBitVector& liveCalleeLocalsAtYield(unsigned index)
- {
- RELEASE_ASSERT(m_rareData);
- return m_rareData->m_liveCalleeLocalsAtYield[index];
- }
+
+ SymbolTable* symbolTable() const { return m_symbolTable.get(); }
EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
@@ -679,7 +741,7 @@ public:
m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon(), this);
}
- const BaselineExecutionCounter& llintExecuteCounter() const
+ const ExecutionCounter& llintExecuteCounter() const
{
return m_llintExecuteCounter;
}
@@ -705,13 +767,9 @@ public:
// When we observe a lot of speculation failures, we trigger a
// reoptimization. But each time, we increase the optimization trigger
// to avoid thrashing.
- JS_EXPORT_PRIVATE unsigned reoptimizationRetryCounter() const;
+ unsigned reoptimizationRetryCounter() const;
void countReoptimization();
#if ENABLE(JIT)
- static unsigned numberOfLLIntBaselineCalleeSaveRegisters() { return RegisterSet::llintBaselineCalleeSaveRegisters().numberOfSetRegisters(); }
- static size_t llintBaselineCalleeSaveSpaceAsVirtualRegisters();
- size_t calleeSaveSpaceAsVirtualRegisters();
-
unsigned numberOfDFGCompiles();
int32_t codeTypeThresholdMultiplier() const;
@@ -723,11 +781,11 @@ public:
return &m_jitExecuteCounter.m_counter;
}
- static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_counter); }
- static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_activeThreshold); }
- static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_totalCount); }
+ static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_counter); }
+ static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_activeThreshold); }
+ static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_totalCount); }
- const BaselineExecutionCounter& jitExecuteCounter() const { return m_jitExecuteCounter; }
+ const ExecutionCounter& jitExecuteCounter() const { return m_jitExecuteCounter; }
unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }
@@ -797,14 +855,7 @@ public:
uint32_t exitCountThresholdForReoptimizationFromLoop();
bool shouldReoptimizeNow();
bool shouldReoptimizeFromLoopNow();
-
- void setCalleeSaveRegisters(RegisterSet);
- void setCalleeSaveRegisters(std::unique_ptr<RegisterAtOffsetList>);
-
- RegisterAtOffsetList* calleeSaveRegisters() const { return m_calleeSaveRegisters.get(); }
#else // No JIT
- static unsigned numberOfLLIntBaselineCalleeSaveRegisters() { return 0; }
- static size_t llintBaselineCalleeSaveSpaceAsVirtualRegisters() { return 0; };
void optimizeAfterWarmUp() { }
unsigned numberOfDFGCompiles() { return 0; }
#endif
@@ -815,11 +866,10 @@ public:
void updateAllPredictions();
unsigned frameRegisterCount();
- int stackPointerOffset();
bool hasOpDebugForLineAndColumn(unsigned line, unsigned column);
- bool hasDebuggerRequests() const { return m_debuggerRequests; }
+ int hasDebuggerRequests() const { return !!m_debuggerRequests; }
void* debuggerRequestsAddress() { return &m_debuggerRequests; }
void addBreakpoint(unsigned numBreakpoints);
@@ -835,16 +885,13 @@ public:
};
void setSteppingMode(SteppingMode);
- void clearDebuggerRequests()
- {
- m_steppingMode = SteppingModeDisabled;
- m_numBreakpoints = 0;
- }
-
+ void clearDebuggerRequests() { m_debuggerRequests = 0; }
+
// FIXME: Make these remaining members private.
- int m_numCalleeLocals;
+ int m_numCalleeRegisters;
int m_numVars;
+ bool m_isConstructor;
// This is intentionally public; it's the responsibility of anyone doing any
// of the following to hold the lock:
@@ -863,67 +910,20 @@ public:
// without holding any locks, because the GC is guaranteed to wait until any
// concurrent compilation threads finish what they're doing.
mutable ConcurrentJITLock m_lock;
-
- Atomic<bool> m_visitWeaklyHasBeenCalled;
-
- bool m_shouldAlwaysBeInlined; // Not a bitfield because the JIT wants to store to it.
-
-#if ENABLE(JIT)
- unsigned m_capabilityLevelState : 2; // DFG::CapabilityLevel
-#endif
-
- bool m_allTransitionsHaveBeenMarked : 1; // Initialized and used on every GC.
-
- bool m_didFailFTLCompilation : 1;
- bool m_hasBeenCompiledWithFTL : 1;
- bool m_isConstructor : 1;
- bool m_isStrictMode : 1;
- unsigned m_codeType : 2; // CodeType
+
+ bool m_shouldAlwaysBeInlined;
+ bool m_allTransitionsHaveBeenMarked; // Initialized and used on every GC.
+
+ bool m_didFailFTLCompilation;
// Internal methods for use by validation code. It would be private if it wasn't
// for the fact that we use it from anonymous namespaces.
void beginValidationDidFail();
NO_RETURN_DUE_TO_CRASH void endValidationDidFail();
- struct RareData {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- Vector<HandlerInfo> m_exceptionHandlers;
-
- // Buffers used for large array literals
- Vector<Vector<JSValue>> m_constantBuffers;
-
- // Jump Tables
- Vector<SimpleJumpTable> m_switchJumpTables;
- Vector<StringJumpTable> m_stringSwitchJumpTables;
-
- Vector<FastBitVector> m_liveCalleeLocalsAtYield;
-
- EvalCodeCache m_evalCodeCache;
- };
-
- void clearExceptionHandlers()
- {
- if (m_rareData)
- m_rareData->m_exceptionHandlers.clear();
- }
-
- void appendExceptionHandler(const HandlerInfo& handler)
- {
- createRareDataIfNecessary(); // We may be handling the exception of an inlined call frame.
- m_rareData->m_exceptionHandlers.append(handler);
- }
-
- CallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);
-
-#if ENABLE(JIT)
- void setPCToCodeOriginMap(std::unique_ptr<PCToCodeOriginMap>&&);
- Optional<CodeOrigin> findPC(void* pc);
-#endif
-
protected:
- void finalizeLLIntInlineCaches();
- void finalizeBaselineJITInlineCaches();
+ virtual void visitWeakReferences(SlotVisitor&) override;
+ virtual void finalizeUnconditionally() override;
#if ENABLE(DFG_JIT)
void tallyFrequentExitSites();
@@ -940,386 +940,298 @@ private:
double optimizationThresholdScalingFactor();
+#if ENABLE(JIT)
+ ClosureCallStubRoutine* findClosureCallForReturnPC(ReturnAddressPtr);
+#endif
+
void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);
- void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
+ void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants)
{
- ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
size_t count = constants.size();
- m_constantRegisters.resizeToFit(count);
+ m_constantRegisters.resize(count);
for (size_t i = 0; i < count; i++)
- m_constantRegisters[i].set(*m_vm, this, constants[i].get());
- m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation;
+ m_constantRegisters[i].set(*m_vm, ownerExecutable(), constants[i].get());
}
- void replaceConstant(int index, JSValue value)
- {
- ASSERT(isConstantRegisterIndex(index) && static_cast<size_t>(index - FirstConstantRegisterIndex) < m_constantRegisters.size());
- m_constantRegisters[index - FirstConstantRegisterIndex].set(m_globalObject->vm(), this, value);
- }
-
- void dumpBytecode(
- PrintStream&, ExecState*, const Instruction* begin, const Instruction*&,
- const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap());
+ void dumpBytecode(PrintStream&, ExecState*, const Instruction* begin, const Instruction*&, const StubInfoMap& = StubInfoMap());
CString registerName(int r) const;
- CString constantName(int index) const;
void printUnaryOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
void printBinaryOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
void printConditionalJump(PrintStream&, ExecState*, const Instruction*, const Instruction*&, int location, const char* op);
void printGetByIdOp(PrintStream&, ExecState*, int location, const Instruction*&);
void printGetByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);
enum CacheDumpMode { DumpCaches, DontDumpCaches };
- void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
+ void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling);
void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
- void printPutByIdCacheStatus(PrintStream&, int location, const StubInfoMap&);
- void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
- void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
+ void printLocationAndOp(PrintStream& out, ExecState*, int location, const Instruction*&, const char* op)
+ {
+ out.printf("[%4d] %-17s ", location, op);
+ }
+
+ void printLocationOpAndRegisterOperand(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, int operand)
+ {
+ printLocationAndOp(out, exec, location, it, op);
+ out.printf("%s", registerName(operand).data());
+ }
void beginDumpProfiling(PrintStream&, bool& hasPrintedProfiling);
void dumpValueProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);
void dumpArrayProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);
void dumpRareCaseProfile(PrintStream&, const char* name, RareCaseProfile*, bool& hasPrintedProfiling);
- void dumpResultProfile(PrintStream&, ResultProfile*, bool& hasPrintedProfiling);
+
+#if ENABLE(DFG_JIT)
+ bool shouldImmediatelyAssumeLivenessDuringScan()
+ {
+ // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
+ // their weak references go stale. So if a basline JIT CodeBlock gets
+ // scanned, we can assume that this means that it's live.
+ if (!JITCode::isOptimizingJIT(jitType()))
+ return true;
- bool shouldVisitStrongly();
- bool shouldJettisonDueToWeakReference();
- bool shouldJettisonDueToOldAge();
+ // For simplicity, we don't attempt to jettison code blocks during GC if
+ // they are executing. Instead we strongly mark their weak references to
+ // allow them to continue to execute soundly.
+ if (m_mayBeExecuting)
+ return true;
+
+ if (Options::forceDFGCodeBlockLiveness())
+ return true;
+
+ return false;
+ }
+#else
+ bool shouldImmediatelyAssumeLivenessDuringScan() { return true; }
+#endif
void propagateTransitions(SlotVisitor&);
void determineLiveness(SlotVisitor&);
void stronglyVisitStrongReferences(SlotVisitor&);
void stronglyVisitWeakReferences(SlotVisitor&);
- void visitOSRExitTargets(SlotVisitor&);
-
- std::chrono::milliseconds timeSinceCreation()
- {
- return std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now() - m_creationTime);
- }
void createRareDataIfNecessary()
{
if (!m_rareData)
- m_rareData = std::make_unique<RareData>();
+ m_rareData = adoptPtr(new RareData);
}
-
- void insertBasicBlockBoundariesForControlFlowProfiler(RefCountedArray<Instruction>&);
-
+
+#if ENABLE(JIT)
+ void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
+ void resetStubDuringGCInternal(RepatchBuffer&, StructureStubInfo&);
+#endif
WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;
int m_numParameters;
union {
unsigned m_debuggerRequests;
struct {
- unsigned m_hasDebuggerStatement : 1;
unsigned m_steppingMode : 1;
- unsigned m_numBreakpoints : 30;
+ unsigned m_numBreakpoints : 31;
};
};
- WriteBarrier<ExecutableBase> m_ownerExecutable;
+ WriteBarrier<ScriptExecutable> m_ownerExecutable;
VM* m_vm;
RefCountedArray<Instruction> m_instructions;
+ WriteBarrier<SymbolTable> m_symbolTable;
VirtualRegister m_thisRegister;
- VirtualRegister m_scopeRegister;
- mutable CodeBlockHash m_hash;
+ VirtualRegister m_argumentsRegister;
+ VirtualRegister m_activationRegister;
+
+ bool m_isStrictMode;
+ bool m_needsActivation;
+ bool m_mayBeExecuting;
+ uint8_t m_visitAggregateHasBeenCalled;
RefPtr<SourceProvider> m_source;
unsigned m_sourceOffset;
unsigned m_firstLineColumnOffset;
+ unsigned m_codeType;
- RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos;
+#if ENABLE(LLINT)
+ Vector<LLIntCallLinkInfo> m_llintCallLinkInfos;
SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;
+#endif
RefPtr<JITCode> m_jitCode;
+ MacroAssemblerCodePtr m_jitCodeWithArityCheck;
#if ENABLE(JIT)
- std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters;
Bag<StructureStubInfo> m_stubInfos;
- Bag<ByValInfo> m_byValInfos;
- Bag<CallLinkInfo> m_callLinkInfos;
+ Vector<ByValInfo> m_byValInfos;
+ Vector<CallLinkInfo> m_callLinkInfos;
SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls;
- SentinelLinkedList<PolymorphicCallNode, BasicRawSentinelNode<PolymorphicCallNode>> m_incomingPolymorphicCalls;
- std::unique_ptr<PCToCodeOriginMap> m_pcToCodeOriginMap;
#endif
- std::unique_ptr<CompactJITCodeMap> m_jitCodeMap;
+ OwnPtr<CompactJITCodeMap> m_jitCodeMap;
#if ENABLE(DFG_JIT)
// This is relevant to non-DFG code blocks that serve as the profiled code block
// for DFG code blocks.
DFG::ExitProfile m_exitProfile;
CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;
#endif
- RefCountedArray<ValueProfile> m_argumentValueProfiles;
- RefCountedArray<ValueProfile> m_valueProfiles;
+ Vector<ValueProfile> m_argumentValueProfiles;
+ Vector<ValueProfile> m_valueProfiles;
SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
- SegmentedVector<ResultProfile, 8> m_resultProfiles;
- typedef HashMap<unsigned, unsigned, IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> BytecodeOffsetToResultProfileIndexMap;
- std::unique_ptr<BytecodeOffsetToResultProfileIndexMap> m_bytecodeOffsetToResultProfileIndexMap;
- RefCountedArray<ArrayAllocationProfile> m_arrayAllocationProfiles;
+ SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
+ Vector<ArrayAllocationProfile> m_arrayAllocationProfiles;
ArrayProfileVector m_arrayProfiles;
- RefCountedArray<ObjectAllocationProfile> m_objectAllocationProfiles;
+ Vector<ObjectAllocationProfile> m_objectAllocationProfiles;
// Constant Pool
COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);
// TODO: This could just be a pointer to m_unlinkedCodeBlock's data, but the DFG mutates
// it, so we're stuck with it for now.
Vector<WriteBarrier<Unknown>> m_constantRegisters;
- Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;
- RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionDecls;
- RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionExprs;
+ Vector<WriteBarrier<FunctionExecutable>> m_functionDecls;
+ Vector<WriteBarrier<FunctionExecutable>> m_functionExprs;
- WriteBarrier<CodeBlock> m_alternative;
+ RefPtr<CodeBlock> m_alternative;
- BaselineExecutionCounter m_llintExecuteCounter;
+ ExecutionCounter m_llintExecuteCounter;
- BaselineExecutionCounter m_jitExecuteCounter;
+ ExecutionCounter m_jitExecuteCounter;
+ int32_t m_totalJITExecutions;
uint32_t m_osrExitCounter;
uint16_t m_optimizationDelayCounter;
uint16_t m_reoptimizationRetryCounter;
-
- std::chrono::steady_clock::time_point m_creationTime;
+
+ mutable CodeBlockHash m_hash;
std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
- std::unique_ptr<RareData> m_rareData;
+ struct RareData {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+ Vector<HandlerInfo> m_exceptionHandlers;
+
+ // Buffers used for large array literals
+ Vector<Vector<JSValue>> m_constantBuffers;
+
+ // Jump Tables
+ Vector<SimpleJumpTable> m_switchJumpTables;
+ Vector<StringJumpTable> m_stringSwitchJumpTables;
- UnconditionalFinalizer m_unconditionalFinalizer;
- WeakReferenceHarvester m_weakReferenceHarvester;
+ EvalCodeCache m_evalCodeCache;
+ };
+#if COMPILER(MSVC)
+ friend void WTF::deleteOwnedPtr<RareData>(RareData*);
+#endif
+ OwnPtr<RareData> m_rareData;
+#if ENABLE(JIT)
+ DFG::CapabilityLevel m_capabilityLevelState;
+#endif
};
// Program code is not marked by any function, so we make the global object
// responsible for marking it.
class GlobalCodeBlock : public CodeBlock {
- typedef CodeBlock Base;
- DECLARE_INFO;
-
protected:
- GlobalCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, GlobalCodeBlock& other)
- : CodeBlock(vm, structure, CopyParsedBlock, other)
+ GlobalCodeBlock(CopyParsedBlockTag, GlobalCodeBlock& other)
+ : CodeBlock(CopyParsedBlock, other)
{
}
-
- GlobalCodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
- : CodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
+
+ GlobalCodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
+ : CodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
{
}
};
class ProgramCodeBlock : public GlobalCodeBlock {
public:
- typedef GlobalCodeBlock Base;
- DECLARE_INFO;
-
- static ProgramCodeBlock* create(VM* vm, CopyParsedBlockTag, ProgramCodeBlock& other)
- {
- ProgramCodeBlock* instance = new (NotNull, allocateCell<ProgramCodeBlock>(vm->heap))
- ProgramCodeBlock(vm, vm->programCodeBlockStructure.get(), CopyParsedBlock, other);
- instance->finishCreation(*vm, CopyParsedBlock, other);
- return instance;
- }
-
- static ProgramCodeBlock* create(VM* vm, ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
- {
- ProgramCodeBlock* instance = new (NotNull, allocateCell<ProgramCodeBlock>(vm->heap))
- ProgramCodeBlock(vm, vm->programCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
- return instance;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
- }
-
-private:
- ProgramCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, ProgramCodeBlock& other)
- : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)
- {
- }
-
- ProgramCodeBlock(VM* vm, Structure* structure, ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
- : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
- {
- }
-
- static void destroy(JSCell*);
-};
-
-class ModuleProgramCodeBlock : public GlobalCodeBlock {
-public:
- typedef GlobalCodeBlock Base;
- DECLARE_INFO;
-
- static ModuleProgramCodeBlock* create(VM* vm, CopyParsedBlockTag, ModuleProgramCodeBlock& other)
- {
- ModuleProgramCodeBlock* instance = new (NotNull, allocateCell<ModuleProgramCodeBlock>(vm->heap))
- ModuleProgramCodeBlock(vm, vm->moduleProgramCodeBlockStructure.get(), CopyParsedBlock, other);
- instance->finishCreation(*vm, CopyParsedBlock, other);
- return instance;
- }
-
- static ModuleProgramCodeBlock* create(VM* vm, ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
- {
- ModuleProgramCodeBlock* instance = new (NotNull, allocateCell<ModuleProgramCodeBlock>(vm->heap))
- ModuleProgramCodeBlock(vm, vm->moduleProgramCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
- return instance;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
- }
-
-private:
- ModuleProgramCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, ModuleProgramCodeBlock& other)
- : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)
+ ProgramCodeBlock(CopyParsedBlockTag, ProgramCodeBlock& other)
+ : GlobalCodeBlock(CopyParsedBlock, other)
{
}
- ModuleProgramCodeBlock(VM* vm, Structure* structure, ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
- : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
+ ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
+ : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
{
}
- static void destroy(JSCell*);
+#if ENABLE(JIT)
+protected:
+ virtual CodeBlock* replacement() override;
+ virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
};
class EvalCodeBlock : public GlobalCodeBlock {
public:
- typedef GlobalCodeBlock Base;
- DECLARE_INFO;
-
- static EvalCodeBlock* create(VM* vm, CopyParsedBlockTag, EvalCodeBlock& other)
+ EvalCodeBlock(CopyParsedBlockTag, EvalCodeBlock& other)
+ : GlobalCodeBlock(CopyParsedBlock, other)
{
- EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))
- EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), CopyParsedBlock, other);
- instance->finishCreation(*vm, CopyParsedBlock, other);
- return instance;
}
-
- static EvalCodeBlock* create(VM* vm, EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)
- {
- EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))
- EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
- return instance;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+
+ EvalCodeBlock(EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)
+ : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, 1)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}
-
+
const Identifier& variable(unsigned index) { return unlinkedEvalCodeBlock()->variable(index); }
unsigned numVariables() { return unlinkedEvalCodeBlock()->numVariables(); }
-private:
- EvalCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, EvalCodeBlock& other)
- : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)
- {
- }
-
- EvalCodeBlock(VM* vm, Structure* structure, EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock,
- JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)
- : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, 1)
- {
- }
+#if ENABLE(JIT)
+protected:
+ virtual CodeBlock* replacement() override;
+ virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
- static void destroy(JSCell*);
-
private:
UnlinkedEvalCodeBlock* unlinkedEvalCodeBlock() const { return jsCast<UnlinkedEvalCodeBlock*>(unlinkedCodeBlock()); }
};
class FunctionCodeBlock : public CodeBlock {
public:
- typedef CodeBlock Base;
- DECLARE_INFO;
-
- static FunctionCodeBlock* create(VM* vm, CopyParsedBlockTag, FunctionCodeBlock& other)
- {
- FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))
- FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), CopyParsedBlock, other);
- instance->finishCreation(*vm, CopyParsedBlock, other);
- return instance;
- }
-
- static FunctionCodeBlock* create(VM* vm, FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope,
- PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
- {
- FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))
- FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset);
- instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
- return instance;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
- }
-
-private:
- FunctionCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, FunctionCodeBlock& other)
- : CodeBlock(vm, structure, CopyParsedBlock, other)
+ FunctionCodeBlock(CopyParsedBlockTag, FunctionCodeBlock& other)
+ : CodeBlock(CopyParsedBlock, other)
{
}
- FunctionCodeBlock(VM* vm, Structure* structure, FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope,
- PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
- : CodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
+ FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
+ : CodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
{
}
- static void destroy(JSCell*);
+#if ENABLE(JIT)
+protected:
+ virtual CodeBlock* replacement() override;
+ virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
};
-#if ENABLE(WEBASSEMBLY)
-class WebAssemblyCodeBlock : public CodeBlock {
-public:
- typedef CodeBlock Base;
- DECLARE_INFO;
-
- static WebAssemblyCodeBlock* create(VM* vm, CopyParsedBlockTag, WebAssemblyCodeBlock& other)
- {
- WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))
- WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), CopyParsedBlock, other);
- instance->finishCreation(*vm, CopyParsedBlock, other);
- return instance;
- }
-
- static WebAssemblyCodeBlock* create(VM* vm, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
- {
- WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))
- WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), ownerExecutable, globalObject);
- instance->finishCreation(*vm, ownerExecutable, globalObject);
- return instance;
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
- }
+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->isCall ? CodeForCall : CodeForConstruct);
+}
-private:
- WebAssemblyCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, WebAssemblyCodeBlock& other)
- : CodeBlock(vm, structure, CopyParsedBlock, other)
- {
- }
+inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
+{
+ if (codeOrigin.inlineCallFrame)
+ return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame);
+ return baselineCodeBlock;
+}
- WebAssemblyCodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
- : CodeBlock(vm, structure, ownerExecutable, globalObject)
- {
- }
+inline int CodeBlock::argumentIndexAfterCapture(size_t argument)
+{
+ if (argument >= static_cast<size_t>(symbolTable()->parameterCount()))
+ return CallFrame::argumentOffset(argument);
+
+ const SlowArgument* slowArguments = symbolTable()->slowArguments();
+ if (!slowArguments || slowArguments[argument].status == SlowArgument::Normal)
+ return CallFrame::argumentOffset(argument);
+
+ ASSERT(slowArguments[argument].status == SlowArgument::Captured);
+ return slowArguments[argument].index;
+}
- static void destroy(JSCell*);
-};
-#endif
+inline bool CodeBlock::hasSlowArguments()
+{
+ return !!symbolTable()->slowArguments();
+}
inline Register& ExecState::r(int index)
{
@@ -1329,30 +1241,25 @@ inline Register& ExecState::r(int 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)
+inline JSValue ExecState::argumentAfterCapture(size_t argument)
{
- return uncheckedR(reg.offset());
-}
-
-inline void CodeBlock::clearVisitWeaklyHasBeenCalled()
-{
- m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
+ if (argument >= argumentCount())
+ return jsUndefined();
+
+ if (!codeBlock())
+ return this[argumentOffset(argument)].jsValue();
+
+ return this[codeBlock()->argumentIndexAfterCapture(argument)].jsValue();
}
-inline void CodeBlockSet::mark(const LockHolder& locker, void* candidateCodeBlock)
+inline void CodeBlockSet::mark(void* candidateCodeBlock)
{
- ASSERT(m_lock.isLocked());
// 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);
@@ -1361,61 +1268,15 @@ inline void CodeBlockSet::mark(const LockHolder& locker, void* candidateCodeBloc
// -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(locker, codeBlock);
-}
-
-inline void CodeBlockSet::mark(const LockHolder&, CodeBlock* codeBlock)
-{
- if (!codeBlock)
+
+ HashSet<CodeBlock*>::iterator iter = m_set.find(static_cast<CodeBlock*>(candidateCodeBlock));
+ if (iter == m_set.end())
return;
-
- // Try to recover gracefully if we forget to execute a barrier for a
- // CodeBlock that does value profiling. This is probably overkill, but we
- // have always done it.
- Heap::heap(codeBlock)->writeBarrier(codeBlock);
-
- m_currentlyExecuting.add(codeBlock);
-}
-
-template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Functor&& functor)
-{
- switch (type()) {
- case ProgramExecutableType: {
- if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get()))
- codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
- break;
- }
-
- case EvalExecutableType: {
- if (CodeBlock* codeBlock = static_cast<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 = static_cast<CodeBlock*>(executable->m_codeBlockForCall.get()))
- codeBlock->forEachRelatedCodeBlock(f);
- if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForConstruct.get()))
- codeBlock->forEachRelatedCodeBlock(f);
- break;
- }
-
- case ModuleProgramExecutableType: {
- if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get()))
- codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
- break;
- }
-
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
+
+ (*iter)->m_mayBeExecuting = true;
+#if ENABLE(GGC)
+ m_currentlyExecuting.append(static_cast<CodeBlock*>(candidateCodeBlock));
+#endif
}
} // namespace JSC