2015-10-09 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Oct 2015 17:54:16 +0000 (17:54 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Oct 2015 17:54:16 +0000 (17:54 +0000)
        Unreviewed, rolling out r190694
        https://bugs.webkit.org/show_bug.cgi?id=148560

        Crashes seen on PLT bots and facebook.com.

        Reverted changesets:

        "CodeBlock should be a GC object"
        https://bugs.webkit.org/show_bug.cgi?id=149727
        http://trac.webkit.org/changeset/190694

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@190809 268f45cc-cd09-0410-ab3c-d52691b4dbfc

57 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/CodeOrigin.cpp
Source/JavaScriptCore/bytecode/CodeOrigin.h
Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp
Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h
Source/JavaScriptCore/bytecode/EvalCodeCache.h
Source/JavaScriptCore/bytecode/InlineCallFrame.cpp
Source/JavaScriptCore/bytecode/InlineCallFrame.h
Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCommonData.cpp
Source/JavaScriptCore/dfg/DFGDesiredTransitions.cpp
Source/JavaScriptCore/dfg/DFGDesiredTransitions.h
Source/JavaScriptCore/dfg/DFGDesiredWeakReferences.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGJITCode.h
Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp
Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp
Source/JavaScriptCore/dfg/DFGOSRExitPreparation.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp
Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.h
Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp
Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/dfg/DFGWorklist.h
Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp
Source/JavaScriptCore/heap/CodeBlockSet.cpp
Source/JavaScriptCore/heap/CodeBlockSet.h
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/StackVisitor.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.h
Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp
Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.h
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/profiler/ProfilerOriginStack.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h

index 2529ec3..483fb14 100644 (file)
@@ -1,3 +1,16 @@
+2015-10-09  Geoffrey Garen  <ggaren@apple.com>
+
+        Unreviewed, rolling out r190694
+        https://bugs.webkit.org/show_bug.cgi?id=148560
+
+        Crashes seen on PLT bots and facebook.com.
+
+        Reverted changesets:
+
+        "CodeBlock should be a GC object"
+        https://bugs.webkit.org/show_bug.cgi?id=149727
+        http://trac.webkit.org/changeset/190694
+
 2015-10-09  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
         Automate WebCore JS builtins generation and build system
index ada6f15..bc19d15 100644 (file)
 
 namespace JSC {
 
-const ClassInfo CodeBlock::s_info = {
-    "CodeBlock", 0, 0,
-    CREATE_METHOD_TABLE(CodeBlock)
-};
-
-const ClassInfo FunctionCodeBlock::s_info = {
-    "FunctionCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(FunctionCodeBlock)
-};
-
-#if ENABLE(WEBASSEMBLY)
-const ClassInfo WebAssemblyCodeBlock::s_info = {
-    "WebAssemblyCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(WebAssemblyCodeBlock)
-};
-#endif
-
-const ClassInfo GlobalCodeBlock::s_info = {
-    "GlobalCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(GlobalCodeBlock)
-};
-
-const ClassInfo ProgramCodeBlock::s_info = {
-    "ProgramCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(ProgramCodeBlock)
-};
-
-const ClassInfo ModuleProgramCodeBlock::s_info = {
-    "ModuleProgramCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(ModuleProgramCodeBlock)
-};
-
-const ClassInfo EvalCodeBlock::s_info = {
-    "EvalCodeBlock", &Base::s_info, 0,
-    CREATE_METHOD_TABLE(EvalCodeBlock)
-};
-
-void FunctionCodeBlock::destroy(JSCell* cell)
-{
-    jsCast<FunctionCodeBlock*>(cell)->~FunctionCodeBlock();
-}
-
-#if ENABLE(WEBASSEMBLY)
-void WebAssemblyCodeBlock::destroy(JSCell* cell)
-{
-    jsCast<WebAssemblyCodeBlock*>(cell)->~WebAssemblyCodeBlock();
-}
-#endif
-
-void ProgramCodeBlock::destroy(JSCell* cell)
-{
-    jsCast<ProgramCodeBlock*>(cell)->~ProgramCodeBlock();
-}
-
-void ModuleProgramCodeBlock::destroy(JSCell* cell)
-{
-    jsCast<ModuleProgramCodeBlock*>(cell)->~ModuleProgramCodeBlock();
-}
-
-void EvalCodeBlock::destroy(JSCell* cell)
-{
-    jsCast<EvalCodeBlock*>(cell)->~EvalCodeBlock();
-}
-
 CString CodeBlock::inferredName() const
 {
     switch (codeType()) {
@@ -217,7 +153,7 @@ void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType)
     out.print(inferredName(), "#", hashAsStringIfPossible());
     out.print(":[", RawPointer(this), "->");
     if (!!m_alternative)
-        out.print(RawPointer(alternative()), "->");
+        out.print(RawPointer(m_alternative.get()), "->");
     out.print(RawPointer(ownerExecutable()), ", ", jitType, codeType());
 
     if (codeType() == FunctionCode)
@@ -1645,9 +1581,8 @@ private:
 
 } // anonymous namespace
 
-CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock& other)
-    : JSCell(*vm, structure)
-    , m_globalObject(other.m_globalObject)
+CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
+    : m_globalObject(other.m_globalObject)
     , m_heap(other.m_heap)
     , m_numCalleeRegisters(other.m_numCalleeRegisters)
     , m_numVars(other.m_numVars)
@@ -1655,11 +1590,11 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_hasBeenCompiledWithFTL(false)
-    , m_unlinkedCode(*other.m_vm, this, other.m_unlinkedCode.get())
+    , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(*other.m_vm, this, other.m_ownerExecutable.get())
+    , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
     , m_vm(other.m_vm)
     , m_instructions(other.m_instructions)
     , m_thisRegister(other.m_thisRegister)
@@ -1684,18 +1619,13 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
-    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
 
     ASSERT(m_heap->isDeferred());
     ASSERT(m_scopeRegister.isLocal());
 
     setNumParameters(other.numParameters());
-}
-
-void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
-{
-    Base::finishCreation(vm);
-
     optimizeAfterWarmUp();
     jitAfterWarmUp();
 
@@ -1709,12 +1639,11 @@ void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
     }
     
     m_heap->m_codeBlocks.add(this);
+    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
 }
 
-CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
-    JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
-    : JSCell(*vm, structure)
-    , m_globalObject(scope->globalObject()->vm(), this, scope->globalObject())
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
+    : m_globalObject(scope->globalObject()->vm(), ownerExecutable, scope->globalObject())
     , m_heap(&m_globalObject->vm().heap)
     , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
     , m_numVars(unlinkedCodeBlock->m_numVars)
@@ -1722,11 +1651,11 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecut
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_hasBeenCompiledWithFTL(false)
-    , m_unlinkedCode(m_globalObject->vm(), this, unlinkedCodeBlock)
+    , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
+    , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
     , m_vm(unlinkedCodeBlock->vm())
     , m_thisRegister(unlinkedCodeBlock->thisRegister())
     , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
@@ -1745,31 +1674,26 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecut
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
-    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
 
     ASSERT(m_heap->isDeferred());
     ASSERT(m_scopeRegister.isLocal());
 
     ASSERT(m_source);
     setNumParameters(unlinkedCodeBlock->numParameters());
-}
-
-void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
-    JSScope* scope)
-{
-    Base::finishCreation(vm);
 
-    if (vm.typeProfiler() || vm.controlFlowProfiler())
-        vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
+    if (vm()->typeProfiler() || vm()->controlFlowProfiler())
+        vm()->functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
 
     setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
     if (unlinkedCodeBlock->usesGlobalObject())
-        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
+        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
 
     for (unsigned i = 0; i < LinkTimeConstantCount; i++) {
         LinkTimeConstant type = static_cast<LinkTimeConstant>(i);
         if (unsigned registerIndex = unlinkedCodeBlock->registerIndexForLinkTimeConstant(type))
-            m_constantRegisters[registerIndex].set(*m_vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
+            m_constantRegisters[registerIndex].set(*m_vm, ownerExecutable, m_globalObject->jsCellForLinkTimeConstant(type));
     }
 
     HashSet<int, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> clonedConstantSymbolTables;
@@ -1784,7 +1708,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                     ConcurrentJITLocker locker(symbolTable->m_lock);
                     symbolTable->prepareForTypeProfiling(locker);
                 }
-                m_constantRegisters[i].set(*m_vm, this, symbolTable->cloneScopePart(*m_vm));
+                m_constantRegisters[i].set(*m_vm, ownerExecutable, symbolTable->cloneScopePart(*m_vm));
                 clonedConstantSymbolTables.add(i + FirstConstantRegisterIndex);
             }
         }
@@ -1804,17 +1728,17 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
     m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
-        if (vm.typeProfiler() || vm.controlFlowProfiler())
-            vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
-        m_functionDecls[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
+        if (vm()->typeProfiler() || vm()->controlFlowProfiler())
+            vm()->functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
+        m_functionDecls[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
     }
 
     m_functionExprs.resizeToFit(unlinkedCodeBlock->numberOfFunctionExprs());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
-        if (vm.typeProfiler() || vm.controlFlowProfiler())
-            vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
-        m_functionExprs[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
+        if (vm()->typeProfiler() || vm()->controlFlowProfiler())
+            vm()->functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
+        m_functionExprs[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
     }
 
     if (unlinkedCodeBlock->hasRareData()) {
@@ -1893,7 +1817,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
         unsigned opLength = opcodeLength(pc[0].u.opcode);
 
-        instructions[i] = vm.interpreter->getOpcode(pc[0].u.opcode);
+        instructions[i] = vm()->interpreter->getOpcode(pc[0].u.opcode);
         for (size_t j = 1; j < opLength; ++j) {
             if (sizeof(int32_t) != sizeof(intptr_t))
                 instructions[i + j].u.pointer = 0;
@@ -1952,8 +1876,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             int inferredInlineCapacity = pc[opLength - 2].u.operand;
 
             instructions[i + opLength - 1] = objectAllocationProfile;
-            objectAllocationProfile->initialize(vm,
-                this, m_globalObject->objectPrototype(), inferredInlineCapacity);
+            objectAllocationProfile->initialize(*vm(),
+                ownerExecutable, m_globalObject->objectPrototype(), inferredInlineCapacity);
             break;
         }
 
@@ -2001,11 +1925,11 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                     // Keep the linked module environment strongly referenced.
                     if (stronglyReferencedModuleEnvironments.add(jsCast<JSModuleEnvironment*>(op.lexicalEnvironment)).isNewEntry)
                         addConstant(op.lexicalEnvironment);
-                    instructions[i + 6].u.jsCell.set(vm, this, op.lexicalEnvironment);
+                    instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, op.lexicalEnvironment);
                 } else
-                    instructions[i + 6].u.symbolTable.set(vm, this, op.lexicalEnvironment->symbolTable());
+                    instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable());
             } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this))
-                instructions[i + 6].u.jsCell.set(vm, this, constantScope);
+                instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, constantScope);
             else
                 instructions[i + 6].u.pointer = nullptr;
             break;
@@ -2038,7 +1962,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
                 instructions[i + 5].u.watchpointSet = op.watchpointSet;
             else if (op.structure)
-                instructions[i + 5].u.structure.set(vm, this, op.structure);
+                instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
             break;
         }
@@ -2075,14 +1999,14 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                 if (op.watchpointSet)
                     op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
             } else if (op.structure)
-                instructions[i + 5].u.structure.set(vm, this, op.structure);
+                instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
 
             break;
         }
 
         case op_profile_type: {
-            RELEASE_ASSERT(vm.typeProfiler());
+            RELEASE_ASSERT(vm()->typeProfiler());
             // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
             size_t instructionOffset = i + opLength - 1;
             unsigned divotStart, divotEnd;
@@ -2112,8 +2036,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                     ConcurrentJITLocker locker(symbolTable->m_lock);
                     // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
                     symbolTable->prepareForTypeProfiling(locker);
-                    globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, vm);
-                    globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, vm);
+                    globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, *vm());
+                    globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, *vm());
                 } else
                     globalVariableID = TypeProfilerNoGlobalIDExists;
 
@@ -2126,8 +2050,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                 const Identifier& ident = identifier(pc[4].u.operand);
                 ConcurrentJITLocker locker(symbolTable->m_lock);
                 // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
-                globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), vm);
-                globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), vm);
+                globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
+                globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
 
                 break;
             }
@@ -2153,8 +2077,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             }
             }
 
-            std::pair<TypeLocation*, bool> locationPair = vm.typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID,
-                ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, &vm);
+            std::pair<TypeLocation*, bool> locationPair = vm()->typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID,
+                ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm());
             TypeLocation* location = locationPair.first;
             bool isNewLocation = locationPair.second;
 
@@ -2162,7 +2086,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();
 
             if (shouldAnalyze && isNewLocation)
-                vm.typeProfiler()->insertNewLocation(location);
+                vm()->typeProfiler()->insertNewLocation(location);
 
             instructions[i + 2].u.location = location;
             break;
@@ -2180,7 +2104,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         i += opLength;
     }
 
-    if (vm.controlFlowProfiler())
+    if (vm()->controlFlowProfiler())
         insertBasicBlockBoundariesForControlFlowProfiler(instructions);
 
     m_instructions = WTF::RefCountedArray<Instruction>(instructions);
@@ -2200,13 +2124,12 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         dumpBytecode();
     
     m_heap->m_codeBlocks.add(this);
-    m_heap->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
+    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
 }
 
 #if ENABLE(WEBASSEMBLY)
-CodeBlock::CodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
-    : JSCell(vm, structure)
-    , m_globalObject(globalObject->vm(), this, globalObject)
+CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
+    : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
     , m_heap(&m_globalObject->vm().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
@@ -2217,7 +2140,7 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerE
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
+    , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
     , m_vm(&vm)
     , m_isStrictMode(false)
     , m_needsActivation(false)
@@ -2231,13 +2154,9 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerE
 #endif
 {
     ASSERT(m_heap->isDeferred());
-}
-
-void CodeBlock::finishCreation(VM& vm, WebAssemblyExecutable*, JSGlobalObject*)
-{
-    Base::finishCreation(vm);
 
     m_heap->m_codeBlocks.add(this);
+    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
 }
 #endif
 
@@ -2249,20 +2168,24 @@ CodeBlock::~CodeBlock()
 #if ENABLE(VERBOSE_VALUE_PROFILE)
     dumpValueProfiles();
 #endif
-
+    while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
+        m_incomingLLIntCalls.begin()->remove();
+#if ENABLE(JIT)
     // We may be destroyed before any CodeBlocks that refer to us are destroyed.
     // Consider that two CodeBlocks become unreachable at the same time. There
     // is no guarantee about the order in which the CodeBlocks are destroyed.
     // So, if we don't remove incoming calls, and get destroyed before the
     // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
     // destructor will try to remove nodes from our (no longer valid) linked list.
-    unlinkIncomingCalls();
+    while (m_incomingCalls.begin() != m_incomingCalls.end())
+        m_incomingCalls.begin()->remove();
+    while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
+        m_incomingPolymorphicCalls.begin()->remove();
     
     // Note that our outgoing calls will be removed from other CodeBlocks'
     // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
     // destructors.
 
-#if ENABLE(JIT)
     for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
         StructureStubInfo* stub = *iter;
         stub->aboutToDie();
@@ -2271,11 +2194,6 @@ CodeBlock::~CodeBlock()
 #endif // ENABLE(JIT)
 }
 
-void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
-{
-    m_alternative.set(vm, this, alternative);
-}
-
 void CodeBlock::setNumParameters(int newValue)
 {
     m_numParameters = newValue;
@@ -2296,43 +2214,73 @@ CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
     if (jitType() != JITCode::DFGJIT)
         return 0;
     DFG::JITCode* jitCode = m_jitCode->dfg();
-    return jitCode->osrEntryBlock();
+    return jitCode->osrEntryBlock.get();
 #else // ENABLE(FTL_JIT)
     return 0;
 #endif // ENABLE(FTL_JIT)
 }
 
-void CodeBlock::visitWeakly(SlotVisitor& visitor)
+void CodeBlock::visitStrongly(SlotVisitor& visitor)
 {
-    bool setByMe = m_visitWeaklyHasBeenCalled.compareExchangeStrong(false, true);
+    bool setByMe = m_visitStronglyHasBeenCalled.compareExchangeStrong(false, true);
     if (!setByMe)
         return;
 
-    if (Heap::isMarked(this))
-        return;
+    visitAggregate(visitor);
 
-    if (shouldVisitStrongly()) {
-        visitor.appendUnbarrieredReadOnlyPointer(this);
+    stronglyVisitStrongReferences(visitor);
+    stronglyVisitWeakReferences(visitor);
+    propagateTransitions(visitor);
+}
+
+void CodeBlock::visitAggregate(SlotVisitor& visitor)
+{
+    // I may be asked to scan myself more than once, and it may even happen concurrently.
+    // To this end, use an atomic operation to check (and set) if I've been called already.
+    // Only one thread may proceed past this point - whichever one wins the atomic set race.
+    bool setByMe = m_visitAggregateHasBeenCalled.compareExchangeStrong(false, true);
+    if (!setByMe)
         return;
+    
+    if (!!m_alternative)
+        m_alternative->visitAggregate(visitor);
+    
+    if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
+        otherBlock->visitAggregate(visitor);
+
+    visitor.reportExtraMemoryVisited(sizeof(CodeBlock));
+    if (m_jitCode)
+        visitor.reportExtraMemoryVisited(m_jitCode->size());
+    if (m_instructions.size()) {
+        // Divide by refCount() because m_instructions points to something that is shared
+        // by multiple CodeBlocks, and we only want to count it towards the heap size once.
+        // Having each CodeBlock report only its proportional share of the size is one way
+        // of accomplishing this.
+        visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
     }
 
+    visitor.append(&m_unlinkedCode);
+
     // There are two things that may use unconditional finalizers: inline cache clearing
     // and jettisoning. The probability of us wanting to do at least one of those things
     // is probably quite close to 1. So we add one no matter what and when it runs, it
     // figures out whether it has any work to do.
-    visitor.addUnconditionalFinalizer(&m_unconditionalFinalizer);
-
+    visitor.addUnconditionalFinalizer(this);
+    
+    m_allTransitionsHaveBeenMarked = false;
+    
+    if (shouldVisitStrongly()) {
+        visitStrongly(visitor);
+        return;
+    }
+    
     if (!JITCode::isOptimizingJIT(jitType()))
         return;
 
-    // If we jettison ourselves we'll install our alternative, so make sure that it
-    // survives GC even if we don't.
-    visitor.append(&m_alternative);
-    
     // There are two things that we use weak reference harvesters for: DFG fixpoint for
     // jettisoning, and trying to find structures that would be live based on some
     // inline cache. So it makes sense to register them regardless.
-    visitor.addWeakReferenceHarvester(&m_weakReferenceHarvester);
+    visitor.addWeakReferenceHarvester(this);
 
 #if ENABLE(DFG_JIT)
     // We get here if we're live in the sense that our owner executable is live,
@@ -2343,48 +2291,14 @@ void CodeBlock::visitWeakly(SlotVisitor& visitor)
     // either us marking additional objects, or by other objects being marked for
     // other reasons, that this iteration should run again; it will notify us of this
     // decision by calling harvestWeakReferences().
-
-    m_allTransitionsHaveBeenMarked = false;
-    propagateTransitions(visitor);
-
+    
     m_jitCode->dfgCommon()->livenessHasBeenProved = false;
+    
+    propagateTransitions(visitor);
     determineLiveness(visitor);
 #endif // ENABLE(DFG_JIT)
 }
 
-void CodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
-    CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
-    JSCell::visitChildren(thisObject, visitor);
-    thisObject->visitChildren(visitor);
-}
-
-void CodeBlock::visitChildren(SlotVisitor& visitor)
-{
-    // There are two things that may use unconditional finalizers: inline cache clearing
-    // and jettisoning. The probability of us wanting to do at least one of those things
-    // is probably quite close to 1. So we add one no matter what and when it runs, it
-    // figures out whether it has any work to do.
-    visitor.addUnconditionalFinalizer(&m_unconditionalFinalizer);
-
-    if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
-        visitor.appendUnbarrieredReadOnlyPointer(otherBlock);
-
-    if (m_jitCode)
-        visitor.reportExtraMemoryVisited(m_jitCode->size());
-    if (m_instructions.size())
-        visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
-
-    visitor.append(&m_unlinkedCode);
-
-    stronglyVisitStrongReferences(visitor);
-    stronglyVisitWeakReferences(visitor);
-
-    m_allTransitionsHaveBeenMarked = false;
-    propagateTransitions(visitor);
-}
-
 bool CodeBlock::shouldVisitStrongly()
 {
     if (Options::forceCodeBlockLiveness())
@@ -2412,7 +2326,17 @@ bool CodeBlock::isKnownToBeLiveDuringGC()
     //   because livenessHasBeenProved would have survived as true.
     // - Code blocks that don't have any dead weak references.
 
-    return Heap::isMarked(this);
+    if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
+        return true;
+
+#if ENABLE(DFG_JIT)
+    if (JITCode::isOptimizingJIT(jitType())) {
+        if (m_jitCode->dfgCommon()->livenessHasBeenProved)
+            return true;
+    }
+#endif
+
+    return false;
 }
 
 bool CodeBlock::shouldJettisonDueToWeakReference()
@@ -2422,34 +2346,12 @@ bool CodeBlock::shouldJettisonDueToWeakReference()
     return !isKnownToBeLiveDuringGC();
 }
 
-static std::chrono::milliseconds timeToLive(JITCode::JITType jitType)
-{
-    switch (jitType) {
-    case JITCode::InterpreterThunk:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::seconds(5));
-    case JITCode::BaselineJIT:
-        // Effectively 10 additional seconds, since BaselineJIT and
-        // InterpreterThunk share a CodeBlock.
-        return std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::seconds(15));
-    case JITCode::DFGJIT:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::seconds(20));
-    case JITCode::FTLJIT:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(
-            std::chrono::seconds(60));
-    default:
-        return std::chrono::milliseconds::max();
-    }
-}
-
 bool CodeBlock::shouldJettisonDueToOldAge()
 {
-    if (Heap::isMarked(this))
+    if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
         return false;
 
-    if (timeSinceCreation() < timeToLive(jitType()))
+    if (timeSinceCreation() < JITCode::timeToLive(jitType()))
         return false;
 
     return true;
@@ -2602,18 +2504,14 @@ void CodeBlock::determineLiveness(SlotVisitor& visitor)
     // All weak references are live. Record this information so we don't
     // come back here again, and scan the strong references.
     dfgCommon->livenessHasBeenProved = true;
-    visitor.appendUnbarrieredReadOnlyPointer(this);
+    stronglyVisitStrongReferences(visitor);
 #endif // ENABLE(DFG_JIT)
 }
 
-void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)
+void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
 {
-    CodeBlock* codeBlock =
-        bitwise_cast<CodeBlock*>(
-            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_weakReferenceHarvester));
-
-    codeBlock->propagateTransitions(visitor);
-    codeBlock->determineLiveness(visitor);
+    propagateTransitions(visitor);
+    determineLiveness(visitor);
 }
 
 void CodeBlock::finalizeLLIntInlineCaches()
@@ -2733,29 +2631,26 @@ void CodeBlock::finalizeBaselineJITInlineCaches()
 #endif
 }
 
-void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
+void CodeBlock::finalizeUnconditionally()
 {
-    CodeBlock* codeBlock = bitwise_cast<CodeBlock*>(
-        bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_unconditionalFinalizer));
-
 #if ENABLE(DFG_JIT)
-    if (codeBlock->shouldJettisonDueToWeakReference()) {
-        codeBlock->jettison(Profiler::JettisonDueToWeakReference);
+    if (shouldJettisonDueToWeakReference()) {
+        jettison(Profiler::JettisonDueToWeakReference);
         return;
     }
 #endif // ENABLE(DFG_JIT)
 
-    if (codeBlock->shouldJettisonDueToOldAge()) {
-        codeBlock->jettison(Profiler::JettisonDueToOldAge);
+    if (shouldJettisonDueToOldAge()) {
+        jettison(Profiler::JettisonDueToOldAge);
         return;
     }
 
-    if (JITCode::couldBeInterpreted(codeBlock->jitType()))
-        codeBlock->finalizeLLIntInlineCaches();
+    if (JITCode::couldBeInterpreted(jitType()))
+        finalizeLLIntInlineCaches();
 
 #if ENABLE(JIT)
-    if (!!codeBlock->jitCode())
-        codeBlock->finalizeBaselineJITInlineCaches();
+    if (!!jitCode())
+        finalizeBaselineJITInlineCaches();
 #endif
 }
 
@@ -2850,14 +2745,14 @@ void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor)
     // guaranteeing that it matches the details of the CodeBlock we compiled
     // the OSR exit against.
 
-    visitor.append(&m_alternative);
+    alternative()->visitStrongly(visitor);
 
 #if ENABLE(DFG_JIT)
     DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
     if (dfgCommon->inlineCallFrames) {
         for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
-            ASSERT(inlineCallFrame->baselineCodeBlock);
-            visitor.append(&inlineCallFrame->baselineCodeBlock);
+            ASSERT(inlineCallFrame->baselineCodeBlock());
+            inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
         }
     }
 #endif
@@ -3099,6 +2994,8 @@ void CodeBlock::unlinkIncomingCalls()
     while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
         m_incomingLLIntCalls.begin()->unlink();
 #if ENABLE(JIT)
+    if (m_incomingCalls.isEmpty() && m_incomingPolymorphicCalls.isEmpty())
+        return;
     while (m_incomingCalls.begin() != m_incomingCalls.end())
         m_incomingCalls.begin()->unlink(*vm());
     while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
@@ -3112,66 +3009,66 @@ void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* inco
     m_incomingLLIntCalls.push(incoming);
 }
 
-CodeBlock* CodeBlock::newReplacement()
+PassRefPtr<CodeBlock> CodeBlock::newReplacement()
 {
     return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
 }
 
 #if ENABLE(JIT)
-CodeBlock* CodeBlock::replacement()
+CodeBlock* ProgramCodeBlock::replacement()
 {
-    const ClassInfo* classInfo = this->classInfo();
-
-    if (classInfo == FunctionCodeBlock::info())
-        return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
-
-    if (classInfo == EvalCodeBlock::info())
-        return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
-
-    if (classInfo == ProgramCodeBlock::info())
-        return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
-
-    if (classInfo == ModuleProgramCodeBlock::info())
-        return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
+    return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
+}
 
-#if ENABLE(WEBASSEMBLY)
-    if (classInfo == WebAssemblyCodeBlock::info())
-        return nullptr;
-#endif
+CodeBlock* ModuleProgramCodeBlock::replacement()
+{
+    return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
+}
 
-    RELEASE_ASSERT_NOT_REACHED();
-    return nullptr;
+CodeBlock* EvalCodeBlock::replacement()
+{
+    return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
 }
 
-DFG::CapabilityLevel CodeBlock::computeCapabilityLevel()
+CodeBlock* FunctionCodeBlock::replacement()
 {
-    const ClassInfo* classInfo = this->classInfo();
+    return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
+}
 
-    if (classInfo == FunctionCodeBlock::info()) {
-        if (m_isConstructor)
-            return DFG::functionForConstructCapabilityLevel(this);
-        return DFG::functionForCallCapabilityLevel(this);
-    }
+DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
+{
+    return DFG::programCapabilityLevel(this);
+}
 
-    if (classInfo == EvalCodeBlock::info())
-        return DFG::evalCapabilityLevel(this);
+DFG::CapabilityLevel ModuleProgramCodeBlock::capabilityLevelInternal()
+{
+    return DFG::programCapabilityLevel(this);
+}
 
-    if (classInfo == ProgramCodeBlock::info())
-        return DFG::programCapabilityLevel(this);
+DFG::CapabilityLevel EvalCodeBlock::capabilityLevelInternal()
+{
+    return DFG::evalCapabilityLevel(this);
+}
 
-    if (classInfo == ModuleProgramCodeBlock::info())
-        return DFG::programCapabilityLevel(this);
+DFG::CapabilityLevel FunctionCodeBlock::capabilityLevelInternal()
+{
+    if (m_isConstructor)
+        return DFG::functionForConstructCapabilityLevel(this);
+    return DFG::functionForCallCapabilityLevel(this);
+}
 
 #if ENABLE(WEBASSEMBLY)
-    if (classInfo == WebAssemblyCodeBlock::info())
-        return DFG::CannotCompile;
-#endif
+CodeBlock* WebAssemblyCodeBlock::replacement()
+{
+    return nullptr;
+}
 
-    RELEASE_ASSERT_NOT_REACHED();
+DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()
+{
     return DFG::CannotCompile;
 }
-
-#endif // ENABLE(JIT)
+#endif
+#endif
 
 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
 {
@@ -3275,7 +3172,7 @@ JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
 {
     if (!codeOrigin.inlineCallFrame)
         return globalObject();
-    return codeOrigin.inlineCallFrame->baselineCodeBlock->globalObject();
+    return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->eitherCodeBlock()->globalObject();
 }
 
 class RecursionCheckFunctor {
@@ -4115,7 +4012,7 @@ unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
 #if ENABLE(JIT)
 DFG::CapabilityLevel CodeBlock::capabilityLevel()
 {
-    DFG::CapabilityLevel result = computeCapabilityLevel();
+    DFG::CapabilityLevel result = capabilityLevelInternal();
     m_capabilityLevelState = result;
     return result;
 }
index 3fffdbd..9256ad7 100644 (file)
 #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 "DFGExitProfile.h"
 #include "DeferredCompilationCallback.h"
 #include "ExecutionCounter.h"
 #include "ExpressionRangeInfo.h"
 #include "HandlerInfo.h"
+#include "ObjectAllocationProfile.h"
+#include "Options.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"
@@ -86,45 +85,26 @@ class JSModuleEnvironment;
 
 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, VM&, JSGlobalObject*);
-#endif
-
-    void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);
-    void finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
+    CodeBlock(CopyParsedBlockTag, CodeBlock& other);
+        
+    CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
 #if ENABLE(WEBASSEMBLY)
-    void finishCreation(VM&, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);
+    CodeBlock(WebAssemblyExecutable* ownerExecutable, VM&, JSGlobalObject*);
 #endif
 
     WriteBarrier<JSGlobalObject> m_globalObject;
     Heap* m_heap;
 
 public:
-    JS_EXPORT_PRIVATE ~CodeBlock();
+    JS_EXPORT_PRIVATE virtual ~CodeBlock();
 
     UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
 
@@ -144,8 +124,8 @@ public:
     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*);
+    CodeBlock* alternative() { return m_alternative.get(); }
+    void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
 
     template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)
     {
@@ -168,18 +148,16 @@ public:
     {
         return specializationFromIsConstruct(m_isConstructor);
     }
-
-    CodeBlock* alternativeForJettison();    
+    
     CodeBlock* baselineAlternative();
     
     // FIXME: Get rid of this.
     // https://bugs.webkit.org/show_bug.cgi?id=123677
     CodeBlock* baselineVersion();
 
-    static void visitChildren(JSCell*, SlotVisitor&);
-    void visitChildren(SlotVisitor&);
-    void visitWeakly(SlotVisitor&);
-    void clearVisitWeaklyHasBeenCalled();
+    void clearMarks();
+    void visitAggregate(SlotVisitor&);
+    void visitStrongly(SlotVisitor&);
 
     void dumpSource();
     void dumpSource(PrintStream&);
@@ -288,7 +266,7 @@ public:
     unsigned instructionCount() const { return m_instructions.size(); }
 
     // Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())
-    CodeBlock* newReplacement();
+    PassRefPtr<CodeBlock> newReplacement();
     
     void setJITCode(PassRefPtr<JITCode> code)
     {
@@ -314,9 +292,9 @@ public:
     }
     
 #if ENABLE(JIT)
-    CodeBlock* replacement();
+    virtual CodeBlock* replacement() = 0;
 
-    DFG::CapabilityLevel computeCapabilityLevel();
+    virtual DFG::CapabilityLevel capabilityLevelInternal() = 0;
     DFG::CapabilityLevel capabilityLevel();
     DFG::CapabilityLevel capabilityLevelState() { return m_capabilityLevelState; }
 
@@ -566,7 +544,7 @@ public:
     {
         unsigned result = m_constantRegisters.size();
         m_constantRegisters.append(WriteBarrier<Unknown>());
-        m_constantRegisters.last().set(m_globalObject->vm(), this, v);
+        m_constantRegisters.last().set(m_globalObject->vm(), m_ownerExecutable.get(), v);
         m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
         return result;
     }
@@ -920,6 +898,8 @@ public:
     CallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);
 
 protected:
+    virtual void visitWeakReferences(SlotVisitor&) override;
+    virtual void finalizeUnconditionally() override;
     void finalizeLLIntInlineCaches();
     void finalizeBaselineJITInlineCaches();
 
@@ -946,14 +926,14 @@ private:
         size_t count = constants.size();
         m_constantRegisters.resizeToFit(count);
         for (size_t i = 0; i < count; i++)
-            m_constantRegisters[i].set(*m_vm, this, constants[i].get());
+            m_constantRegisters[i].set(*m_vm, ownerExecutable(), constants[i].get());
         m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation;
     }
 
     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);
+        m_constantRegisters[index - FirstConstantRegisterIndex].set(m_globalObject->vm(), m_ownerExecutable.get(), value);
     }
 
     void dumpBytecode(
@@ -1025,7 +1005,8 @@ private:
     bool m_isStrictMode;
     bool m_needsActivation;
 
-    Atomic<bool> m_visitWeaklyHasBeenCalled;
+    Atomic<bool> m_visitAggregateHasBeenCalled;
+    Atomic<bool> m_visitStronglyHasBeenCalled;
 
     RefPtr<SourceProvider> m_source;
     unsigned m_sourceOffset;
@@ -1067,7 +1048,7 @@ private:
     Vector<WriteBarrier<FunctionExecutable>> m_functionDecls;
     Vector<WriteBarrier<FunctionExecutable>> m_functionExprs;
 
-    WriteBarrier<CodeBlock> m_alternative;
+    RefPtr<CodeBlock> m_alternative;
     
     BaselineExecutionCounter m_llintExecuteCounter;
 
@@ -1087,242 +1068,124 @@ private:
 #if ENABLE(JIT)
     DFG::CapabilityLevel m_capabilityLevelState;
 #endif
-
-    UnconditionalFinalizer m_unconditionalFinalizer;
-    WeakReferenceHarvester m_weakReferenceHarvester;
 };
 
 // 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(CopyParsedBlockTag, ProgramCodeBlock& other)
+    : GlobalCodeBlock(CopyParsedBlock, other)
     {
-        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)
+    ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
+        : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
     {
-        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*);
+#if ENABLE(JIT)
+protected:
+    virtual CodeBlock* replacement() override;
+    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
 };
 
 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)
+    ModuleProgramCodeBlock(CopyParsedBlockTag, ModuleProgramCodeBlock& 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)
+    ModuleProgramCodeBlock(ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* 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* 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(CopyParsedBlockTag, EvalCodeBlock& other)
+        : GlobalCodeBlock(CopyParsedBlock, other)
     {
-        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(CopyParsedBlockTag, FunctionCodeBlock& other)
+        : CodeBlock(CopyParsedBlock, other)
     {
-        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(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:
-    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);
-        return instance;
-    }
-
-    static WebAssemblyCodeBlock* create(VM* vm, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
+    WebAssemblyCodeBlock(CopyParsedBlockTag, WebAssemblyCodeBlock& other)
+        : CodeBlock(CopyParsedBlock, other)
     {
-        WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))
-            WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), ownerExecutable, globalObject);
-        instance->finishCreation(*vm);
-        return instance;
     }
 
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    WebAssemblyCodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
+        : CodeBlock(ownerExecutable, vm, globalObject)
     {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
     }
 
-private:
-    WebAssemblyCodeBlock(VM& vm, Structure* structure, CopyParsedBlockTag, WebAssemblyCodeBlock& other)
-        : CodeBlock(vm, structure, CopyParsedBlock, other)
-    {
-    }
-
-    WebAssemblyCodeBlock(VM& vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
-        : CodeBlock(vm, structure, ownerExecutable, vm, globalObject)
-    {
-    }
-
-    static void destroy(JSCell*);
+#if ENABLE(JIT)
+protected:
+    virtual CodeBlock* replacement() override;
+    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
+#endif
 };
 #endif
 
@@ -1350,9 +1213,10 @@ inline Register& ExecState::uncheckedR(VirtualRegister reg)
     return uncheckedR(reg.offset());
 }
 
-inline void CodeBlock::clearVisitWeaklyHasBeenCalled()
+inline void CodeBlock::clearMarks()
 {
-    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
 }
 
 inline void CodeBlockSet::mark(void* candidateCodeBlock)
@@ -1377,11 +1241,12 @@ inline void CodeBlockSet::mark(CodeBlock* codeBlock)
 {
     if (!codeBlock)
         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);
+    
+    // Force GC to visit all CodeBlocks on the stack, including old CodeBlocks
+    // that have not executed a barrier. This is overkill, but we have always
+    // done this, and it might help us recover gracefully if we forget to execute
+    // a barrier when a CodeBlock needs it.
+    codeBlock->clearMarks();
 
     m_currentlyExecuting.add(codeBlock);
 }
@@ -1390,13 +1255,13 @@ template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Funct
 {
     switch (type()) {
     case ProgramExecutableType: {
-        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get()))
+        if (CodeBlock* 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()))
+        if (CodeBlock* codeBlock = jsCast<EvalExecutable*>(this)->m_evalCodeBlock.get())
             codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
         break;
     }
@@ -1404,15 +1269,15 @@ template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Funct
     case FunctionExecutableType: {
         Functor f(std::forward<Functor>(functor));
         FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
-        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForCall.get()))
+        if (CodeBlock* codeBlock = executable->m_codeBlockForCall.get())
             codeBlock->forEachRelatedCodeBlock(f);
-        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForConstruct.get()))
+        if (CodeBlock* codeBlock = executable->m_codeBlockForConstruct.get())
             codeBlock->forEachRelatedCodeBlock(f);
         break;
     }
 
     case ModuleProgramExecutableType: {
-        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get()))
+        if (CodeBlock* codeBlock = jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get())
             codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
         break;
     }
index d516950..5646a53 100644 (file)
@@ -75,7 +75,7 @@ bool CodeOrigin::isApproximatelyEqualTo(const CodeOrigin& other) const
         if (!a.inlineCallFrame)
             return true;
         
-        if (a.inlineCallFrame->baselineCodeBlock.get() != b.inlineCallFrame->baselineCodeBlock.get())
+        if (a.inlineCallFrame->executable.get() != b.inlineCallFrame->executable.get())
             return false;
         
         a = a.inlineCallFrame->directCaller;
@@ -98,7 +98,7 @@ unsigned CodeOrigin::approximateHash() const
         if (!codeOrigin.inlineCallFrame)
             return result;
         
-        result += WTF::PtrHash<JSCell*>::hash(codeOrigin.inlineCallFrame->baselineCodeBlock.get());
+        result += WTF::PtrHash<JSCell*>::hash(codeOrigin.inlineCallFrame->executable.get());
         
         codeOrigin = codeOrigin.inlineCallFrame->directCaller;
     }
@@ -115,11 +115,11 @@ Vector<CodeOrigin> CodeOrigin::inlineStack() const
     return result;
 }
 
-CodeBlock* CodeOrigin::codeOriginOwner() const
+ScriptExecutable* CodeOrigin::codeOriginOwner() const
 {
     if (!inlineCallFrame)
         return 0;
-    return inlineCallFrame->baselineCodeBlock.get();
+    return inlineCallFrame->executable.get();
 }
 
 int CodeOrigin::stackOffset() const
@@ -143,7 +143,7 @@ void CodeOrigin::dump(PrintStream& out) const
             out.print(" --> ");
         
         if (InlineCallFrame* frame = stack[i].inlineCallFrame) {
-            out.print(frame->briefFunctionInformation(), ":<", RawPointer(frame->baselineCodeBlock.get()), "> ");
+            out.print(frame->briefFunctionInformation(), ":<", RawPointer(frame->executable.get()), "> ");
             if (frame->isClosureCall)
                 out.print("(closure) ");
         }
index c944e81..a522ba9 100644 (file)
@@ -87,7 +87,7 @@ struct CodeOrigin {
     
     // If the code origin corresponds to inlined code, gives you the heap object that
     // would have owned the code if it had not been inlined. Otherwise returns 0.
-    CodeBlock* codeOriginOwner() const;
+    ScriptExecutable* codeOriginOwner() const;
     
     int stackOffset() const;
     
index 762387c..761e95b 100644 (file)
@@ -33,13 +33,15 @@ namespace JSC {
 DeferredCompilationCallback::DeferredCompilationCallback() { }
 DeferredCompilationCallback::~DeferredCompilationCallback() { }
 
-void DeferredCompilationCallback::compilationDidComplete(CodeBlock*, CodeBlock*, CompilationResult result)
+void DeferredCompilationCallback::compilationDidComplete(CodeBlock* codeBlock, CompilationResult result)
 {
     dumpCompiledSourcesIfNeeded();
 
     switch (result) {
     case CompilationFailed:
     case CompilationInvalidated:
+        codeBlock->heap()->removeCodeBlock(codeBlock);
+        break;
     case CompilationSuccessful:
         break;
     case CompilationDeferred:
index adecb82..37568d2 100644 (file)
@@ -42,8 +42,8 @@ protected:
 public:
     virtual ~DeferredCompilationCallback();
 
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock) = 0;
-    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) = 0;
+    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
 
     Vector<DeferredSourceDump>& ensureDeferredSourceDump();
 
index 62521fc..7a89898 100644 (file)
@@ -51,7 +51,7 @@ namespace JSC {
             return 0;
         }
         
-        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, const String& evalSource, JSScope* scope)
+        EvalExecutable* getSlow(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, ThisTDZMode thisTDZMode, const String& evalSource, JSScope* scope)
         {
             VariableEnvironment variablesUnderTDZ;
             JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ);
index 447bc7e..7a3d8af 100644 (file)
@@ -47,17 +47,24 @@ JSFunction* InlineCallFrame::calleeForCallFrame(ExecState* exec) const
 
 CodeBlockHash InlineCallFrame::hash() const
 {
-    return baselineCodeBlock->hash();
+    return jsCast<FunctionExecutable*>(executable.get())->codeBlockFor(
+        specializationKind())->hash();
 }
 
 CString InlineCallFrame::hashAsStringIfPossible() const
 {
-    return baselineCodeBlock->hashAsStringIfPossible();
+    return jsCast<FunctionExecutable*>(executable.get())->codeBlockFor(
+        specializationKind())->hashAsStringIfPossible();
 }
 
 CString InlineCallFrame::inferredName() const
 {
-    return jsCast<FunctionExecutable*>(baselineCodeBlock->ownerExecutable())->inferredName().utf8();
+    return jsCast<FunctionExecutable*>(executable.get())->inferredName().utf8();
+}
+
+CodeBlock* InlineCallFrame::baselineCodeBlock() const
+{
+    return jsCast<FunctionExecutable*>(executable.get())->baselineCodeBlockFor(specializationKind());
 }
 
 void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const
@@ -67,8 +74,8 @@ void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const
 
 void InlineCallFrame::dumpInContext(PrintStream& out, DumpContext* context) const
 {
-    out.print(briefFunctionInformation(), ":<", RawPointer(baselineCodeBlock.get()));
-    if (isStrictMode())
+    out.print(briefFunctionInformation(), ":<", RawPointer(executable.get()));
+    if (executable->isStrictMode())
         out.print(" (StrictMode)");
     out.print(", bc#", directCaller.bytecodeIndex, ", ", static_cast<Kind>(kind));
     if (isClosureCall)
index 9eb7fb3..62f25fc 100644 (file)
@@ -29,6 +29,7 @@
 #include "CodeBlock.h"
 #include "CodeBlockHash.h"
 #include "CodeOrigin.h"
+#include "Executable.h"
 #include "ValueRecovery.h"
 #include "WriteBarrier.h"
 #include <wtf/BitVector.h>
@@ -41,6 +42,7 @@ namespace JSC {
 
 struct InlineCallFrame;
 class ExecState;
+class ScriptExecutable;
 class JSFunction;
 
 struct InlineCallFrame {
@@ -172,7 +174,7 @@ struct InlineCallFrame {
     }
     
     Vector<ValueRecovery> arguments; // Includes 'this'.
-    WriteBarrier<CodeBlock> baselineCodeBlock;
+    WriteBarrier<ScriptExecutable> executable;
     ValueRecovery calleeRecovery;
     CodeOrigin directCaller;
 
@@ -207,6 +209,8 @@ struct InlineCallFrame {
     CodeBlockHash hash() const;
     CString hashAsStringIfPossible() const;
     
+    CodeBlock* baselineCodeBlock() const;
+    
     void setStackOffset(signed offset)
     {
         stackOffset = offset;
@@ -216,8 +220,6 @@ struct InlineCallFrame {
     ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); }
     ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); }
 
-    bool isStrictMode() const { return baselineCodeBlock->isStrictMode(); }
-
     void dumpBriefFunctionInformation(PrintStream&) const;
     void dump(PrintStream&) const;
     void dumpInContext(PrintStream&, DumpContext*) const;
@@ -229,7 +231,9 @@ struct InlineCallFrame {
 inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
 {
     RELEASE_ASSERT(inlineCallFrame);
-    return inlineCallFrame->baselineCodeBlock.get();
+    ScriptExecutable* 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)
index e394c16..420fc93 100644 (file)
@@ -539,7 +539,7 @@ void AccessCase::generate(AccessGenerationState& state)
         }
 
         // We will emit code that has a weak reference that isn't otherwise listed anywhere.
-        state.weakReferences.append(WriteBarrier<JSCell>(vm, codeBlock, structure));
+        state.weakReferences.append(WriteBarrier<JSCell>(vm, codeBlock->ownerExecutable(), structure));
         
         jit.move(CCallHelpers::TrustedImmPtr(condition.object()), scratchGPR);
         state.failAndRepatch.append(
@@ -1379,7 +1379,7 @@ MacroAssemblerCodePtr PolymorphicAccess::regenerate(
     bool doesCalls = false;
     for (auto& entry : cases)
         doesCalls |= entry->doesCalls();
-    
+
     CodeBlock* codeBlockThatOwnsExceptionHandlers = nullptr;
     CallSiteIndex callSiteIndexForExceptionHandling = state.originalCallSiteIndex();
     if (state.needsToRestoreRegistersIfException()) {
@@ -1388,7 +1388,7 @@ MacroAssemblerCodePtr PolymorphicAccess::regenerate(
         callSiteIndexForExceptionHandling = state.callSiteIndexForExceptionHandling();
     }
 
-    m_stubRoutine = createJITStubRoutine(code, vm, codeBlock, doesCalls, nullptr, codeBlockThatOwnsExceptionHandlers, callSiteIndexForExceptionHandling);
+    m_stubRoutine = createJITStubRoutine(code, vm, codeBlock->ownerExecutable(), doesCalls, nullptr, codeBlockThatOwnsExceptionHandlers, callSiteIndexForExceptionHandling);
     m_watchpoints = WTF::move(state.watchpoints);
     if (!state.weakReferences.isEmpty())
         m_weakReferences = std::make_unique<Vector<WriteBarrier<JSCell>>>(WTF::move(state.weakReferences));
index 4affa46..98250f1 100644 (file)
@@ -55,7 +55,7 @@ void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObj
     cacheType = CacheType::GetByIdSelf;
     
     u.byIdSelf.baseObjectStructure.set(
-        *codeBlock->vm(), codeBlock, baseObjectStructure);
+        *codeBlock->vm(), codeBlock->ownerExecutable(), baseObjectStructure);
     u.byIdSelf.offset = offset;
 }
 
@@ -64,7 +64,7 @@ void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* base
     cacheType = CacheType::PutByIdReplace;
     
     u.byIdSelf.baseObjectStructure.set(
-        *codeBlock->vm(), codeBlock, baseObjectStructure);
+        *codeBlock->vm(), codeBlock->ownerExecutable(), baseObjectStructure);
     u.byIdSelf.offset = offset;
 }
 
@@ -120,7 +120,7 @@ MacroAssemblerCodePtr StructureStubInfo::addAccessCase(
     Vector<std::unique_ptr<AccessCase>> accessCases;
     
     std::unique_ptr<AccessCase> previousCase =
-        AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
+        AccessCase::fromStructureStubInfo(vm, codeBlock->ownerExecutable(), *this);
     if (previousCase)
         accessCases.append(WTF::move(previousCase));
 
index 635751e..d4fc1a8 100644 (file)
@@ -4633,10 +4633,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         ASSERT(callsiteBlockHead);
         
         m_inlineCallFrame = byteCodeParser->m_graph.m_plan.inlineCallFrames->add();
-        byteCodeParser->m_graph.freeze(codeBlock->baselineVersion());
+        byteCodeParser->m_graph.freeze(codeBlock->ownerExecutable());
         // The owner is the machine code block, and we already have a barrier on that when the
         // plan finishes.
-        m_inlineCallFrame->baselineCodeBlock.setWithoutWriteBarrier(codeBlock->baselineVersion());
+        m_inlineCallFrame->executable.setWithoutWriteBarrier(codeBlock->ownerScriptExecutable());
         m_inlineCallFrame->setStackOffset(inlineCallFrameStart.offset() - JSStack::CallFrameHeaderSize);
         if (callee) {
             m_inlineCallFrame->calleeRecovery = ValueRecovery::constant(callee);
@@ -4828,7 +4828,7 @@ bool ByteCodeParser::parse()
     if (Options::verboseDFGByteCodeParsing())
         dataLog("Parsing ", *m_codeBlock, "\n");
     
-    m_dfgCodeBlock = m_graph.m_plan.profiledDFGCodeBlock;
+    m_dfgCodeBlock = m_graph.m_plan.profiledDFGCodeBlock.get();
     if (isFTL(m_graph.m_plan.mode) && m_dfgCodeBlock
         && Options::enablePolyvariantDevirtualization()) {
         if (Options::enablePolyvariantCallInlining())
index 751a061..c8bb0d4 100644 (file)
@@ -106,8 +106,8 @@ void CommonData::validateReferences(const TrackedReferences& trackedReferences)
                     trackedReferences.check(recovery.constant());
             }
             
-            if (CodeBlock* baselineCodeBlock = inlineCallFrame->baselineCodeBlock.get())
-                trackedReferences.check(baselineCodeBlock);
+            if (ScriptExecutable* executable = inlineCallFrame->executable.get())
+                trackedReferences.check(executable);
             
             if (inlineCallFrame->calleeRecovery.isConstant())
                 trackedReferences.check(inlineCallFrame->calleeRecovery.constant());
index e273ae8..91134cc 100644 (file)
@@ -34,7 +34,7 @@
 
 namespace JSC { namespace DFG {
 
-DesiredTransition::DesiredTransition(CodeBlock* codeBlock, CodeBlock* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
+DesiredTransition::DesiredTransition(CodeBlock* codeBlock, ScriptExecutable* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
     : m_codeBlock(codeBlock)
     , m_codeOriginOwner(codeOriginOwner)
     , m_oldStructure(oldStructure)
@@ -46,7 +46,7 @@ void DesiredTransition::reallyAdd(VM& vm, CommonData* common)
 {
     common->transitions.append(
         WeakReferenceTransition(
-            vm, m_codeBlock,
+            vm, m_codeBlock->ownerExecutable(),
             m_codeOriginOwner,
             m_oldStructure, m_newStructure));
 }
@@ -66,7 +66,7 @@ DesiredTransitions::~DesiredTransitions()
 {
 }
 
-void DesiredTransitions::addLazily(CodeBlock* codeBlock, CodeBlock* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
+void DesiredTransitions::addLazily(CodeBlock* codeBlock, ScriptExecutable* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
 {
     m_transitions.append(DesiredTransition(codeBlock, codeOriginOwner, oldStructure, newStructure));
 }
index 9ea6ada..addaf3e 100644 (file)
@@ -44,7 +44,7 @@ class CommonData;
 
 class DesiredTransition {
 public:
-    DesiredTransition(CodeBlock*, CodeBlock* codeOriginOwner, Structure*, Structure*);
+    DesiredTransition(CodeBlock*, ScriptExecutable*, Structure*, Structure*);
 
     void reallyAdd(VM&, CommonData*);
     
@@ -52,7 +52,7 @@ public:
 
 private:
     CodeBlock* m_codeBlock;
-    CodeBlock* m_codeOriginOwner;
+    ScriptExecutable* m_codeOriginOwner;
     Structure* m_oldStructure;
     Structure* m_newStructure;
 };
@@ -62,7 +62,7 @@ public:
     DesiredTransitions();
     ~DesiredTransitions();
 
-    void addLazily(CodeBlock*, CodeBlock* codeOriginOwner, Structure*, Structure*);
+    void addLazily(CodeBlock*, ScriptExecutable*, Structure*, Structure*);
     void reallyAdd(VM&, CommonData*);
     void visitChildren(SlotVisitor&);
 
index 1af13ef..0df9606 100644 (file)
@@ -70,10 +70,10 @@ void DesiredWeakReferences::reallyAdd(VM& vm, CommonData* common)
     for (JSCell* target : m_references) {
         if (Structure* structure = jsDynamicCast<Structure*>(target)) {
             common->weakStructureReferences.append(
-                WriteBarrier<Structure>(vm, m_codeBlock, structure));
+                WriteBarrier<Structure>(vm, m_codeBlock->ownerExecutable(), structure));
         } else {
             common->weakReferences.append(
-                WriteBarrier<JSCell>(vm, m_codeBlock, target));
+                WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target));
         }
     }
 }
index aca733a..fe407aa 100644 (file)
@@ -121,7 +121,7 @@ CompilationResult compile(
         vm, codeBlock, profiledDFGCodeBlock, mode, osrEntryBytecodeIndex, mustHandleValues,
         callback);
     if (result != CompilationDeferred)
-        callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
+        callback->compilationDidComplete(codeBlock, result);
     return result;
 }
 
index f2807e4..72bf31f 100644 (file)
@@ -61,7 +61,7 @@ static const char* dfgOpNames[] = {
 Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
     : m_vm(vm)
     , m_plan(plan)
-    , m_codeBlock(m_plan.codeBlock)
+    , m_codeBlock(m_plan.codeBlock.get())
     , m_profiledBlock(m_codeBlock->alternative())
     , m_allocator(longLivedState.m_allocator)
     , m_nextMachineLocal(0)
index 054ff07..8343341 100644 (file)
@@ -348,7 +348,7 @@ public:
         if (!inlineCallFrame)
             return m_codeBlock->ownerScriptExecutable();
         
-        return inlineCallFrame->baselineCodeBlock->ownerScriptExecutable();
+        return inlineCallFrame->executable.get();
     }
     
     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
@@ -372,7 +372,7 @@ public:
     {
         if (!codeOrigin.inlineCallFrame)
             return m_codeBlock->isStrictMode();
-        return codeOrigin.inlineCallFrame->isStrictMode();
+        return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
     }
     
     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
index de23428..3ff0616 100644 (file)
@@ -28,7 +28,6 @@
 
 #if ENABLE(DFG_JIT)
 
-#include "CodeBlock.h"
 #include "CompilationResult.h"
 #include "DFGCommonData.h"
 #include "DFGMinifiedGraph.h"
@@ -117,12 +116,7 @@ public:
     void shrinkToFit();
 
     RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex) override;
-#if ENABLE(FTL_JIT)
-    CodeBlock* osrEntryBlock() { return m_osrEntryBlock.get(); }
-    void setOSREntryBlock(VM& vm, const JSCell* owner, CodeBlock* osrEntryBlock) { m_osrEntryBlock.set(vm, owner, osrEntryBlock); }
-    void clearOSREntryBlock() { m_osrEntryBlock.clear(); }
-#endif
-    
+
 private:
     friend class JITCompiler; // Allow JITCompiler to call setCodeRef().
 
@@ -136,7 +130,7 @@ public:
 #if ENABLE(FTL_JIT)
     uint8_t nestedTriggerIsSet { 0 };
     UpperTierExecutionCounter tierUpCounter;
-    WriteBarrier<CodeBlock> m_osrEntryBlock;
+    RefPtr<CodeBlock> osrEntryBlock;
     unsigned osrEntryRetry;
     bool abandonOSREntry;
 #endif // ENABLE(FTL_JIT)
index 2d131c3..836c0e0 100644 (file)
@@ -57,7 +57,7 @@ size_t JITFinalizer::codeSize()
 bool JITFinalizer::finalize()
 {
     m_jitCode->initializeCodeRef(
-        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data())),
+        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::DFGJIT)).data())),
         MacroAssemblerCodePtr());
     
     m_plan.codeBlock->setJITCode(m_jitCode);
@@ -71,7 +71,7 @@ bool JITFinalizer::finalizeFunction()
 {
     RELEASE_ASSERT(!m_withArityCheck.isEmptyValue());
     m_jitCode->initializeCodeRef(
-        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data())),
+        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::DFGJIT)).data())),
         m_withArityCheck);
     m_plan.codeBlock->setJITCode(m_jitCode);
     
@@ -83,7 +83,7 @@ bool JITFinalizer::finalizeFunction()
 void JITFinalizer::finalizeCommon()
 {
 #if ENABLE(FTL_JIT)
-    m_jitCode->optimizeAfterWarmUp(m_plan.codeBlock);
+    m_jitCode->optimizeAfterWarmUp(m_plan.codeBlock.get());
 #endif // ENABLE(FTL_JIT)
     
     if (m_plan.compilation)
index 9a60560..12648bc 100644 (file)
@@ -69,7 +69,7 @@ void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit)
             jit.branchTest8(
                 AssemblyHelpers::NonZero,
                 AssemblyHelpers::AbsoluteAddress(
-                    inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->addressOfDidTryToEnterInLoop())));
+                    inlineCallFrame->executable->addressOfDidTryToEnterInLoop())));
     }
     
     jit.move(
@@ -268,14 +268,13 @@ static void osrWriteBarrier(CCallHelpers& jit, GPRReg owner, GPRReg scratch)
 
 void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit, bool isExitingToOpCatch)
 {
-    CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin);
-    jit.move(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), GPRInfo::argumentGPR1);
+    jit.move(AssemblyHelpers::TrustedImmPtr(jit.codeBlock()->ownerExecutable()), GPRInfo::argumentGPR1);
     osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
     InlineCallFrameSet* inlineCallFrames = jit.codeBlock()->jitCode()->dfgCommon()->inlineCallFrames.get();
     if (inlineCallFrames) {
         for (InlineCallFrame* inlineCallFrame : *inlineCallFrames) {
-            CodeBlock* baselineCodeBlock = inlineCallFrame->baselineCodeBlock.get();
-            jit.move(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), GPRInfo::argumentGPR1);
+            ScriptExecutable* ownerExecutable = inlineCallFrame->executable.get();
+            jit.move(AssemblyHelpers::TrustedImmPtr(ownerExecutable), GPRInfo::argumentGPR1);
             osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
         }
     }
@@ -283,6 +282,7 @@ void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit, bool isEx
     if (exit.m_codeOrigin.inlineCallFrame)
         jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
 
+    CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin);
     Vector<BytecodeAndMachineOffset>& decodedCodeMap = jit.decodedCodeMapFor(baselineCodeBlock);
     
     BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned>(decodedCodeMap, decodedCodeMap.size(), exit.m_codeOrigin.bytecodeIndex, BytecodeAndMachineOffset::getBytecodeIndex);
index ba2a0da..48e9f05 100644 (file)
@@ -42,7 +42,7 @@ void prepareCodeOriginForOSRExit(ExecState* exec, CodeOrigin codeOrigin)
     DeferGC deferGC(vm.heap);
     
     for (; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->directCaller) {
-        CodeBlock* codeBlock = codeOrigin.inlineCallFrame->baselineCodeBlock.get();
+        CodeBlock* codeBlock = codeOrigin.inlineCallFrame->baselineCodeBlock();
         if (codeBlock->jitType() == JSC::JITCode::BaselineJIT)
             continue;
 
index d6c4740..7e0f07d 100644 (file)
@@ -1307,7 +1307,7 @@ extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSR
     
     bool didTryToEnterIntoInlinedLoops = false;
     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
-        if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
+        if (inlineCallFrame->executable->didTryToEnterInLoop()) {
             didTryToEnterIntoInlinedLoops = true;
             break;
         }
@@ -1377,8 +1377,8 @@ static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode*
 
     // We need to compile the code.
     compile(
-        *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
-        Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
+        *vm, codeBlock->newReplacement().get(), codeBlock, FTLMode, UINT_MAX,
+        Operands<JSValue>(), ToFTLDeferredCompilationCallback::create(codeBlock));
 }
 
 static void triggerTierUpNowCommon(ExecState* exec, bool inLoop)
@@ -1463,7 +1463,7 @@ char* JIT_OPERATION triggerOSREntryNow(
     if (worklistState == Worklist::Compiling)
         return 0;
     
-    if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
+    if (CodeBlock* entryBlock = jitCode->osrEntryBlock.get()) {
         void* address = FTL::prepareOSREntry(
             exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
         if (address)
@@ -1477,7 +1477,7 @@ char* JIT_OPERATION triggerOSREntryNow(
         
         // OSR entry failed. Oh no! This implies that we need to retry. We retry
         // without exponential backoff and we only do this for the entry code block.
-        jitCode->clearOSREntryBlock();
+        jitCode->osrEntryBlock = nullptr;
         jitCode->osrEntryRetry = 0;
         return 0;
     }
@@ -1494,19 +1494,21 @@ char* JIT_OPERATION triggerOSREntryNow(
     Operands<JSValue> mustHandleValues;
     jitCode->reconstruct(
         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
-    CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
+    RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
     CompilationResult forEntryResult = compile(
-        *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
-        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create());
+        *vm, replacementCodeBlock.get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,
+        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock));
     
-    if (forEntryResult != CompilationSuccessful)
+    if (forEntryResult != CompilationSuccessful) {
+        ASSERT(forEntryResult == CompilationDeferred || replacementCodeBlock->hasOneRef());
         return 0;
+    }
 
     // It's possible that the for-entry compile already succeeded. In that case OSR
     // entry will succeed unless we ran out of stack. It's not clear what we should do.
     // We signal to try again after a while if that happens.
     void* address = FTL::prepareOSREntry(
-        exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
+        exec, codeBlock, jitCode->osrEntryBlock.get(), bytecodeIndex, streamIndex);
     return static_cast<char*>(address);
 }
 #endif // ENABLE(FTL_JIT)
index 53e106c..a98cd45 100644 (file)
@@ -131,7 +131,7 @@ Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode)
 
 } // anonymous namespace
 
-Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
+Plan::Plan(PassRefPtr<CodeBlock> passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
     CompilationMode mode, unsigned osrEntryBytecodeIndex,
     const Operands<JSValue>& mustHandleValues)
     : vm(*passedCodeBlock->vm())
@@ -140,10 +140,10 @@ Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
     , mode(mode)
     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
     , mustHandleValues(mustHandleValues)
-    , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0)
+    , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), profilerCompilationKindForMode(mode))) : 0)
     , inlineCallFrames(adoptRef(new InlineCallFrameSet()))
-    , identifiers(codeBlock)
-    , weakReferences(codeBlock)
+    , identifiers(codeBlock.get())
+    , weakReferences(codeBlock.get())
     , willTryToTierUp(false)
     , stage(Preparing)
 {
@@ -535,7 +535,7 @@ bool Plan::isStillValid()
 
 void Plan::reallyAdd(CommonData* commonData)
 {
-    watchpoints.reallyAdd(codeBlock, *commonData);
+    watchpoints.reallyAdd(codeBlock.get(), *commonData);
     identifiers.reallyAdd(vm, commonData);
     weakReferences.reallyAdd(vm, commonData);
     transitions.reallyAdd(vm, commonData);
@@ -553,14 +553,14 @@ void Plan::notifyCompiled()
 
 void Plan::notifyReady()
 {
-    callback->compilationDidBecomeReadyAsynchronously(codeBlock, profiledDFGCodeBlock);
+    callback->compilationDidBecomeReadyAsynchronously(codeBlock.get());
     stage = Ready;
 }
 
 CompilationResult Plan::finalizeWithoutNotifyingCallback()
 {
     // We will establish new references from the code block to things. So, we need a barrier.
-    vm.heap.writeBarrier(codeBlock);
+    vm.heap.writeBarrier(codeBlock->ownerExecutable());
     
     if (!isStillValid())
         return CompilationInvalidated;
@@ -596,7 +596,7 @@ CompilationResult Plan::finalizeWithoutNotifyingCallback()
 
 void Plan::finalizeAndNotifyCallback()
 {
-    callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, finalizeWithoutNotifyingCallback());
+    callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
 }
 
 CompilationKey Plan::key()
@@ -604,15 +604,16 @@ CompilationKey Plan::key()
     return CompilationKey(codeBlock->alternative(), mode);
 }
 
-void Plan::rememberCodeBlocks()
+void Plan::clearCodeBlockMarks()
 {
     // Compilation writes lots of values to a CodeBlock without performing
     // an explicit barrier. So, we need to be pessimistic and assume that
     // all our CodeBlocks must be visited during GC.
 
-    Heap::heap(codeBlock)->writeBarrier(codeBlock);
+    codeBlock->clearMarks();
+    codeBlock->alternative()->clearMarks();
     if (profiledDFGCodeBlock)
-        Heap::heap(profiledDFGCodeBlock)->writeBarrier(profiledDFGCodeBlock);
+        profiledDFGCodeBlock->clearMarks();
 }
 
 void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
@@ -623,13 +624,15 @@ void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
     for (unsigned i = mustHandleValues.size(); i--;)
         visitor.appendUnbarrieredValue(&mustHandleValues[i]);
 
-    visitor.appendUnbarrieredReadOnlyPointer(codeBlock);
-    visitor.appendUnbarrieredReadOnlyPointer(profiledDFGCodeBlock);
+    codeBlock->visitStrongly(visitor);
+    codeBlock->alternative()->visitStrongly(visitor);
+    if (profiledDFGCodeBlock)
+        profiledDFGCodeBlock->visitStrongly(visitor);
 
     if (inlineCallFrames) {
         for (auto* inlineCallFrame : *inlineCallFrames) {
-            ASSERT(inlineCallFrame->baselineCodeBlock.get());
-            visitor.appendUnbarrieredReadOnlyPointer(inlineCallFrame->baselineCodeBlock.get());
+            ASSERT(inlineCallFrame->baselineCodeBlock());
+            inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
         }
     }
 
index 8cd3479..eec5c9e 100644 (file)
@@ -55,7 +55,7 @@ class ThreadData;
 
 struct Plan : public ThreadSafeRefCounted<Plan> {
     Plan(
-        CodeBlock* codeBlockToCompile, CodeBlock* profiledDFGCodeBlock,
+        PassRefPtr<CodeBlock> codeBlockToCompile, CodeBlock* profiledDFGCodeBlock,
         CompilationMode, unsigned osrEntryBytecodeIndex,
         const Operands<JSValue>& mustHandleValues);
     ~Plan();
@@ -71,17 +71,14 @@ struct Plan : public ThreadSafeRefCounted<Plan> {
     
     CompilationKey key();
     
-    void rememberCodeBlocks();
+    void clearCodeBlockMarks();
     void checkLivenessAndVisitChildren(SlotVisitor&);
     bool isKnownToBeLiveDuringGC();
     void cancel();
     
     VM& vm;
-
-    // These can be raw pointers because we visit them during every GC in checkLivenessAndVisitChildren.
-    CodeBlock* codeBlock;
-    CodeBlock* profiledDFGCodeBlock;
-
+    RefPtr<CodeBlock> codeBlock;
+    RefPtr<CodeBlock> profiledDFGCodeBlock;
     CompilationMode mode;
     const unsigned osrEntryBytecodeIndex;
     Operands<JSValue> mustHandleValues;
index a186641..faebdd0 100644 (file)
 
 namespace JSC { namespace DFG {
 
-ToFTLDeferredCompilationCallback::ToFTLDeferredCompilationCallback()
+ToFTLDeferredCompilationCallback::ToFTLDeferredCompilationCallback(
+    PassRefPtr<CodeBlock> dfgCodeBlock)
+    : m_dfgCodeBlock(dfgCodeBlock)
 {
 }
 
 ToFTLDeferredCompilationCallback::~ToFTLDeferredCompilationCallback() { }
 
-Ref<ToFTLDeferredCompilationCallback> ToFTLDeferredCompilationCallback::create()
+Ref<ToFTLDeferredCompilationCallback> ToFTLDeferredCompilationCallback::create(PassRefPtr<CodeBlock> dfgCodeBlock)
 {
-    return adoptRef(*new ToFTLDeferredCompilationCallback());
+    return adoptRef(*new ToFTLDeferredCompilationCallback(dfgCodeBlock));
 }
 
 void ToFTLDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
+    CodeBlock* codeBlock)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
             ") did become ready.\n");
     }
     
-    profiledDFGCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
-        profiledDFGCodeBlock);
+    m_dfgCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
+        m_dfgCodeBlock.get());
 }
 
 void ToFTLDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CompilationResult result)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
             ") result: ", result, "\n");
     }
     
-    if (profiledDFGCodeBlock->replacement() != profiledDFGCodeBlock) {
+    if (m_dfgCodeBlock->replacement() != m_dfgCodeBlock) {
         if (Options::verboseOSR()) {
             dataLog(
                 "Dropping FTL code block ", *codeBlock, " on the floor because the "
-                "DFG code block ", *profiledDFGCodeBlock, " was jettisoned.\n");
+                "DFG code block ", *m_dfgCodeBlock, " was jettisoned.\n");
         }
         return;
     }
@@ -80,10 +82,10 @@ void ToFTLDeferredCompilationCallback::compilationDidComplete(
     if (result == CompilationSuccessful)
         codeBlock->ownerScriptExecutable()->installCode(codeBlock);
     
-    profiledDFGCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
-        profiledDFGCodeBlock, result);
+    m_dfgCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
+        m_dfgCodeBlock.get(), result);
 
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
 }
 
 } } // JSC::DFG
index 2a7931d..3e0ea02 100644 (file)
@@ -40,15 +40,18 @@ namespace DFG {
 
 class ToFTLDeferredCompilationCallback : public DeferredCompilationCallback {
 protected:
-    ToFTLDeferredCompilationCallback();
+    ToFTLDeferredCompilationCallback(PassRefPtr<CodeBlock> dfgCodeBlock);
 
 public:
     virtual ~ToFTLDeferredCompilationCallback();
 
-    static Ref<ToFTLDeferredCompilationCallback> create();
+    static Ref<ToFTLDeferredCompilationCallback> create(PassRefPtr<CodeBlock> dfgCodeBlock);
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock);
-    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*);
+    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
+
+private:
+    RefPtr<CodeBlock> m_dfgCodeBlock;
 };
 
 } } // namespace JSC::DFG
index c9e5c79..70cc825 100644 (file)
@@ -35,7 +35,9 @@
 
 namespace JSC { namespace DFG {
 
-ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback()
+ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback(
+    PassRefPtr<CodeBlock> dfgCodeBlock)
+    : m_dfgCodeBlock(dfgCodeBlock)
 {
 }
 
@@ -43,38 +45,39 @@ ToFTLForOSREntryDeferredCompilationCallback::~ToFTLForOSREntryDeferredCompilatio
 {
 }
 
-Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create()
+Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create(
+    PassRefPtr<CodeBlock> dfgCodeBlock)
 {
-    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback());
+    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback(dfgCodeBlock));
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
+    CodeBlock* codeBlock)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
             ") did become ready.\n");
     }
     
-    profiledDFGCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
-        profiledDFGCodeBlock);
+    m_dfgCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
+        m_dfgCodeBlock.get());
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CompilationResult result)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
             ") result: ", result, "\n");
     }
     
-    JITCode* jitCode = profiledDFGCodeBlock->jitCode()->dfg();
+    JITCode* jitCode = m_dfgCodeBlock->jitCode()->dfg();
         
     switch (result) {
     case CompilationSuccessful:
-        jitCode->setOSREntryBlock(*codeBlock->vm(), profiledDFGCodeBlock, codeBlock);
+        jitCode->osrEntryBlock = codeBlock;
         break;
     case CompilationFailed:
         jitCode->osrEntryRetry = 0;
@@ -87,7 +90,7 @@ void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
         break;
     }
     
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
 }
 
 } } // JSC::DFG
index 580f7d2..c9dcf6d 100644 (file)
@@ -40,15 +40,18 @@ namespace DFG {
 
 class ToFTLForOSREntryDeferredCompilationCallback : public DeferredCompilationCallback {
 protected:
-    ToFTLForOSREntryDeferredCompilationCallback();
+    ToFTLForOSREntryDeferredCompilationCallback(PassRefPtr<CodeBlock> dfgCodeBlock);
 
 public:
     virtual ~ToFTLForOSREntryDeferredCompilationCallback();
 
-    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create();
+    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create(PassRefPtr<CodeBlock> dfgCodeBlock);
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock);
-    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*);
+    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
+
+private:
+    RefPtr<CodeBlock> m_dfgCodeBlock;
 };
 
 } } // namespace JSC::DFG
index ac823c3..b41d803 100644 (file)
@@ -207,14 +207,14 @@ void Worklist::completeAllPlansForVM(VM& vm)
     completeAllReadyPlansForVM(vm);
 }
 
-void Worklist::rememberCodeBlocks(VM& vm)
+void Worklist::clearCodeBlockMarks(VM& vm)
 {
     LockHolder locker(m_lock);
     for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
         Plan* plan = iter->value.get();
         if (&plan->vm != &vm)
             continue;
-        plan->rememberCodeBlocks();
+        plan->clearCodeBlockMarks();
     }
 }
 
@@ -467,11 +467,11 @@ void completeAllPlansForVM(VM& vm)
     }
 }
 
-void rememberCodeBlocks(VM& vm)
+void clearCodeBlockMarks(VM& vm)
 {
     for (unsigned i = DFG::numberOfWorklists(); i--;) {
         if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
-            worklist->rememberCodeBlocks(vm);
+            worklist->clearCodeBlockMarks(vm);
     }
 }
 
index 075f7cc..1740745 100644 (file)
@@ -57,7 +57,7 @@ public:
     // worklist->completeAllReadyPlansForVM(vm);
     void completeAllPlansForVM(VM&);
 
-    void rememberCodeBlocks(VM&);
+    void clearCodeBlockMarks(VM&);
 
     void waitUntilAllPlansForVMAreReady(VM&);
     State completeAllReadyPlansForVM(VM&, CompilationKey = CompilationKey());
@@ -141,7 +141,7 @@ inline Worklist* worklistForIndexOrNull(unsigned index)
 }
 
 void completeAllPlansForVM(VM&);
-void rememberCodeBlocks(VM&);
+void clearCodeBlockMarks(VM&);
 
 } } // namespace JSC::DFG
 
index 0aba6a8..3da4848 100644 (file)
@@ -99,7 +99,7 @@ bool JITFinalizer::finalizeFunction()
         jitCode->initializeExitThunks(
             FINALIZE_DFG_CODE(
                 *exitThunksLinkBuffer,
-                ("FTL exit thunks for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data())));
+                ("FTL exit thunks for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data())));
     } // else this function had no OSR exits, so no exit thunks.
     
     if (sideCodeLinkBuffer) {
@@ -116,7 +116,7 @@ bool JITFinalizer::finalizeFunction()
         jitCode->addHandle(FINALIZE_DFG_CODE(
             *sideCodeLinkBuffer,
             ("FTL side code for %s",
-                toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data()))
+                toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data()))
             .executableMemory());
     }
     
@@ -124,7 +124,7 @@ bool JITFinalizer::finalizeFunction()
         jitCode->addHandle(FINALIZE_DFG_CODE(
             *handleExceptionsLinkBuffer,
             ("FTL exception handler for %s",
-                toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data()))
+                toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data()))
             .executableMemory());
     }
 
@@ -137,7 +137,7 @@ bool JITFinalizer::finalizeFunction()
     jitCode->initializeArityCheckEntrypoint(
         FINALIZE_DFG_CODE(
             *entrypointLinkBuffer,
-            ("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data(), function)));
+            ("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data(), function)));
     
     m_plan.codeBlock->setJITCode(jitCode);
 
index 7c6cee2..ed6ed89 100644 (file)
@@ -41,11 +41,17 @@ CodeBlockSet::CodeBlockSet()
 
 CodeBlockSet::~CodeBlockSet()
 {
+    for (CodeBlock* codeBlock : m_oldCodeBlocks)
+        codeBlock->deref();
+
+    for (CodeBlock* codeBlock : m_newCodeBlocks)
+        codeBlock->deref();
 }
 
-void CodeBlockSet::add(CodeBlock* codeBlock)
+void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
 {
-    bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry;
+    CodeBlock* block = codeBlock.leakRef();
+    bool isNewEntry = m_newCodeBlocks.add(block).isNewEntry;
     ASSERT_UNUSED(isNewEntry, isNewEntry);
 }
 
@@ -58,35 +64,52 @@ void CodeBlockSet::promoteYoungCodeBlocks()
 void CodeBlockSet::clearMarksForFullCollection()
 {
     for (CodeBlock* codeBlock : m_oldCodeBlocks)
-        codeBlock->clearVisitWeaklyHasBeenCalled();
+        codeBlock->clearMarks();
 
     // We promote after we clear marks on the old generation CodeBlocks because
     // none of the young generations CodeBlocks need to be cleared.
     promoteYoungCodeBlocks();
 }
 
-void CodeBlockSet::lastChanceToFinalize()
+void CodeBlockSet::clearMarksForEdenCollection(const Vector<const JSCell*>& rememberedSet)
 {
-    for (CodeBlock* codeBlock : m_newCodeBlocks)
-        codeBlock->classInfo()->methodTable.destroy(codeBlock);
-
-    for (CodeBlock* codeBlock : m_oldCodeBlocks)
-        codeBlock->classInfo()->methodTable.destroy(codeBlock);
+    // This ensures that we will revisit CodeBlocks in remembered Executables even if they were previously marked.
+    for (const JSCell* cell : rememberedSet) {
+        ScriptExecutable* executable = const_cast<ScriptExecutable*>(jsDynamicCast<const ScriptExecutable*>(cell));
+        if (!executable)
+            continue;
+        executable->forEachCodeBlock([this](CodeBlock* codeBlock) {
+            codeBlock->clearMarks();
+            m_remembered.add(codeBlock);
+        });
+    }
 }
 
 void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
 {
     HashSet<CodeBlock*>& set = collectionType == EdenCollection ? m_newCodeBlocks : m_oldCodeBlocks;
-    Vector<CodeBlock*> unmarked;
-    for (CodeBlock* codeBlock : set) {
-        if (Heap::isMarked(codeBlock))
-            continue;
-        unmarked.append(codeBlock);
-    }
 
-    for (CodeBlock* codeBlock : unmarked) {
-        codeBlock->classInfo()->methodTable.destroy(codeBlock);
-        set.remove(codeBlock);
+    // This needs to be a fixpoint because code blocks that are unmarked may
+    // refer to each other. For example, a DFG code block that is owned by
+    // the GC may refer to an FTL for-entry code block that is also owned by
+    // the GC.
+    Vector<CodeBlock*, 16> toRemove;
+    if (verbose)
+        dataLog("Fixpointing over unmarked, set size = ", set.size(), "...\n");
+    for (;;) {
+        for (CodeBlock* codeBlock : set) {
+            if (!codeBlock->hasOneRef())
+                continue;
+            codeBlock->deref();
+            toRemove.append(codeBlock);
+        }
+        if (verbose)
+            dataLog("    Removing ", toRemove.size(), " blocks.\n");
+        if (toRemove.isEmpty())
+            break;
+        for (CodeBlock* codeBlock : toRemove)
+            set.remove(codeBlock);
+        toRemove.resize(0);
     }
 
     // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
@@ -96,6 +119,7 @@ void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
 
 void CodeBlockSet::remove(CodeBlock* codeBlock)
 {
+    codeBlock->deref();
     if (m_oldCodeBlocks.contains(codeBlock)) {
         m_oldCodeBlocks.remove(codeBlock);
         return;
@@ -104,16 +128,35 @@ void CodeBlockSet::remove(CodeBlock* codeBlock)
     m_newCodeBlocks.remove(codeBlock);
 }
 
-void CodeBlockSet::writeBarrierCurrentlyExecutingCodeBlocks(Heap* heap)
+void CodeBlockSet::traceMarked(SlotVisitor& visitor)
+{
+    if (verbose)
+        dataLog("Tracing ", m_currentlyExecuting.size(), " code blocks.\n");
+
+    // We strongly visit the currently executing set because jettisoning code
+    // is not valuable once it's on the stack. We're past the point where
+    // jettisoning would avoid the cost of OSR exit.
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        codeBlock->visitStrongly(visitor);
+
+    // We strongly visit the remembered set because jettisoning old code during
+    // Eden GC is unsound. There might be an old object with a strong reference
+    // to the code.
+    for (const RefPtr<CodeBlock>& codeBlock : m_remembered)
+        codeBlock->visitStrongly(visitor);
+}
+
+void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap)
 {
     if (verbose)
         dataLog("Remembering ", m_currentlyExecuting.size(), " code blocks.\n");
-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        heap->writeBarrier(codeBlock);
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        heap->writeBarrier(codeBlock->ownerExecutable());
 
-    // It's safe to clear this set because we won't delete the CodeBlocks
-    // in it until the next GC, and we'll recompute it at that time.
+    // It's safe to clear these RefPtr sets because we won't delete the CodeBlocks
+    // in them until the next GC, and we'll recompute them at that time.
     m_currentlyExecuting.clear();
+    m_remembered.clear();
 }
 
 void CodeBlockSet::dump(PrintStream& out) const
@@ -128,8 +171,8 @@ void CodeBlockSet::dump(PrintStream& out) const
         out.print(comma, pointerDump(codeBlock));
     out.print("], currentlyExecuting = [");
     comma = CommaPrinter();
-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        out.print(comma, pointerDump(codeBlock));
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        out.print(comma, pointerDump(codeBlock.get()));
     out.print("]}");
 }
 
index ae1441e..18ef5a4 100644 (file)
@@ -51,12 +51,13 @@ class CodeBlockSet {
 public:
     CodeBlockSet();
     ~CodeBlockSet();
-
-    void lastChanceToFinalize();
     
     // Add a CodeBlock. This is only called by CodeBlock constructors.
-    void add(CodeBlock*);
+    void add(PassRefPtr<CodeBlock>);
     
+    // Clear mark bits for certain CodeBlocks depending on the type of collection.
+    void clearMarksForEdenCollection(const Vector<const JSCell*>&);
+
     // Clear all mark bits for all CodeBlocks.
     void clearMarksForFullCollection();
 
@@ -71,9 +72,13 @@ public:
     
     void remove(CodeBlock*);
     
+    // Trace all marked code blocks. The CodeBlock is free to make use of
+    // mayBeExecuting.
+    void traceMarked(SlotVisitor&);
+
     // Add all currently executing CodeBlocks to the remembered set to be 
     // re-scanned during the next collection.
-    void writeBarrierCurrentlyExecutingCodeBlocks(Heap*);
+    void rememberCurrentlyExecutingCodeBlocks(Heap*);
 
     // Visits each CodeBlock in the heap until the visitor function returns true
     // to indicate that it is done iterating, or until every CodeBlock has been
@@ -96,11 +101,16 @@ public:
     void dump(PrintStream&) const;
 
 private:
+    void clearMarksForCodeBlocksInRememberedExecutables(const Vector<const JSCell*>&);
     void promoteYoungCodeBlocks();
 
+    // This is not a set of RefPtr<CodeBlock> because we need to be able to find
+    // arbitrary bogus pointers. I could have written a thingy that had peek types
+    // and all, but that seemed like overkill.
     HashSet<CodeBlock*> m_oldCodeBlocks;
     HashSet<CodeBlock*> m_newCodeBlocks;
-    HashSet<CodeBlock*> m_currentlyExecuting;
+    HashSet<RefPtr<CodeBlock>> m_currentlyExecuting;
+    HashSet<RefPtr<CodeBlock>> m_remembered;
 };
 
 } // namespace JSC
index fa2cf8f..537b40a 100644 (file)
@@ -382,7 +382,6 @@ void Heap::lastChanceToFinalize()
     RELEASE_ASSERT(!m_vm->entryScope);
     RELEASE_ASSERT(m_operationInProgress == NoOperation);
 
-    m_codeBlocks.lastChanceToFinalize();
     m_objectSpace.lastChanceToFinalize();
     releaseDelayedReleasedObjects();
 
@@ -521,6 +520,17 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
     GCPHASE(MarkRoots);
     ASSERT(isValidThreadState(m_vm));
 
+    Vector<const JSCell*> rememberedSet(m_slotVisitor.markStack().size());
+    m_slotVisitor.markStack().fillVector(rememberedSet);
+
+#if ENABLE(DFG_JIT)
+    DFG::clearCodeBlockMarks(*m_vm);
+#endif
+    if (m_operationInProgress == EdenCollection)
+        m_codeBlocks.clearMarksForEdenCollection(rememberedSet);
+    else
+        m_codeBlocks.clearMarksForFullCollection();
+
     // We gather conservative roots before clearing mark bits because conservative
     // gathering uses the mark bits to determine whether a reference is valid.
     ConservativeRoots conservativeRoots(&m_objectSpace.blocks(), &m_storageSpace);
@@ -528,16 +538,10 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
     gatherJSStackRoots(conservativeRoots);
     gatherScratchBufferRoots(conservativeRoots);
 
-#if ENABLE(DFG_JIT)
-    DFG::rememberCodeBlocks(*m_vm);
-#endif
+    clearLivenessData();
 
-    if (m_operationInProgress == FullCollection) {
+    if (m_operationInProgress == FullCollection)
         m_opaqueRoots.clear();
-        m_slotVisitor.clearMarkStack();
-    }
-
-    clearLivenessData();
 
     m_parallelMarkersShouldExit = false;
 
@@ -576,7 +580,6 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
     {
         ParallelModeEnabler enabler(m_slotVisitor);
 
-        m_slotVisitor.donateAndDrain();
         visitExternalRememberedSet();
         visitSmallStrings();
         visitConservativeRoots(conservativeRoots);
@@ -691,9 +694,6 @@ void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
 void Heap::clearLivenessData()
 {
     GCPHASE(ClearLivenessData);
-    if (m_operationInProgress == FullCollection)
-        m_codeBlocks.clearMarksForFullCollection();
-
     m_objectSpace.clearNewlyAllocated();
     m_objectSpace.clearMarks();
 }
@@ -815,6 +815,7 @@ void Heap::visitHandleStack(HeapRootVisitor& visitor)
 void Heap::traceCodeBlocksAndJITStubRoutines()
 {
     GCPHASE(TraceCodeBlocksAndJITStubRoutines);
+    m_codeBlocks.traceMarked(m_slotVisitor);
     m_jitStubRoutines.traceMarkedStubRoutines(m_slotVisitor);
 
     if (Options::logGC() == GCLogging::Verbose)
@@ -948,12 +949,18 @@ void Heap::deleteAllCodeBlocks()
     // If JavaScript is running, it's not safe to delete all JavaScript code, since
     // we'll end up returning to deleted code.
     RELEASE_ASSERT(!m_vm->entryScope);
-    ASSERT(m_operationInProgress == NoOperation);
 
     completeAllDFGPlans();
 
-    for (ExecutableBase* executable : m_executables)
-        executable->clearCode();
+    for (ExecutableBase* current : m_executables) {
+        if (!current->isFunctionExecutable())
+            continue;
+        static_cast<FunctionExecutable*>(current)->clearCode();
+    }
+
+    ASSERT(m_operationInProgress == FullCollection || m_operationInProgress == NoOperation);
+    m_codeBlocks.clearMarksForFullCollection();
+    m_codeBlocks.deleteUnmarkedAndUnreferenced(FullCollection);
 }
 
 void Heap::deleteAllUnlinkedCodeBlocks()
@@ -973,9 +980,9 @@ void Heap::clearUnmarkedExecutables()
         if (isMarked(current))
             continue;
 
-        // Eagerly dereference the Executable's JITCode in order to run watchpoint
-        // destructors. Otherwise, watchpoints might fire for deleted CodeBlocks.
-        current->clearCode();
+        // We do this because executable memory is limited on some platforms and because
+        // CodeBlock requires eager finalization.
+        ExecutableBase::clearCodeVirtual(current);
         std::swap(m_executables[i], m_executables.last());
         m_executables.removeLast();
     }
@@ -1096,7 +1103,7 @@ NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOri
     deleteUnmarkedCompiledCode();
     deleteSourceProviderCaches();
     notifyIncrementalSweeper();
-    writeBarrierCurrentlyExecutingCodeBlocks();
+    rememberCurrentlyExecutingCodeBlocks();
 
     resetAllocators();
     updateAllocationLimits();
@@ -1133,6 +1140,7 @@ void Heap::willStartCollection(HeapOperation collectionType)
     GCPHASE(StartingCollection);
     if (shouldDoFullCollection(collectionType)) {
         m_operationInProgress = FullCollection;
+        m_slotVisitor.clearMarkStack();
         m_shouldDoFullCollection = false;
         if (Options::logGC())
             dataLog("FullCollection, ");
@@ -1249,10 +1257,10 @@ void Heap::notifyIncrementalSweeper()
     m_sweeper->startSweeping();
 }
 
-void Heap::writeBarrierCurrentlyExecutingCodeBlocks()
+void Heap::rememberCurrentlyExecutingCodeBlocks()
 {
-    GCPHASE(WriteBarrierCurrentlyExecutingCodeBlocks);
-    m_codeBlocks.writeBarrierCurrentlyExecutingCodeBlocks(this);
+    GCPHASE(RememberCurrentlyExecutingCodeBlocks);
+    m_codeBlocks.rememberCurrentlyExecutingCodeBlocks(this);
 }
 
 void Heap::resetAllocators()
index 590c911..3411def 100644 (file)
@@ -227,6 +227,8 @@ public:
         template<typename T> void releaseSoon(RetainPtr<T>&&);
 #endif
 
+    void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); }
+
     static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
 
     void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
@@ -312,7 +314,7 @@ private:
     void snapshotMarkedSpace();
     void deleteSourceProviderCaches();
     void notifyIncrementalSweeper();
-    void writeBarrierCurrentlyExecutingCodeBlocks();
+    void rememberCurrentlyExecutingCodeBlocks();
     void resetAllocators();
     void copyBackingStores();
     void harvestWeakReferences();
index 11cbd0c..d3a6085 100644 (file)
@@ -172,7 +172,7 @@ JSValue eval(CallFrame* callFrame)
         ASSERT(!callFrame->vm().exception());
 
         ThisTDZMode thisTDZMode = callerCodeBlock->unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded;
-        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);
+        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerScriptExecutable(), callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);
         if (!eval)
             return jsUndefined();
     }
index 85b0187..e686e49 100644 (file)
@@ -169,7 +169,7 @@ void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin
             m_frame.m_argumentCountIncludingThis = callFrame->r(inlineCallFrame->argumentCountRegister.offset()).unboxedInt32();
         else
             m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
-        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock.get();
+        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
         m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;
 
         JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
index bb675c0..8e3c270 100644 (file)
@@ -38,7 +38,7 @@ ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin)
     if (!codeOrigin.inlineCallFrame)
         return m_codeBlock->ownerExecutable();
     
-    return codeOrigin.inlineCallFrame->baselineCodeBlock->ownerExecutable();
+    return codeOrigin.inlineCallFrame->executable.get();
 }
 
 Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock)
index 9875c85..2afbac3 100644 (file)
@@ -1082,7 +1082,7 @@ public:
     {
         if (!codeOrigin.inlineCallFrame)
             return codeBlock()->isStrictMode();
-        return codeOrigin.inlineCallFrame->isStrictMode();
+        return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
     }
     
     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
index 347b1cc..8763094 100644 (file)
@@ -132,7 +132,7 @@ PassRefPtr<JITStubRoutine> createJITStubRoutine(
 // Helper for the creation of simple stub routines that need no help from the GC. Note
 // that codeBlock gets "executed" more than once.
 #define FINALIZE_CODE_FOR_GC_AWARE_STUB(codeBlock, patchBuffer, makesCalls, cell, dataLogFArguments) \
-    (createJITStubRoutine(FINALIZE_CODE_FOR((codeBlock), (patchBuffer), dataLogFArguments), *(codeBlock)->vm(), (codeBlock), (makesCalls), (cell)))
+    (createJITStubRoutine(FINALIZE_CODE_FOR((codeBlock), (patchBuffer), dataLogFArguments), *(codeBlock)->vm(), (codeBlock)->ownerExecutable(), (makesCalls), (cell)))
 
 } // namespace JSC
 
index 06ae64e..8470ff0 100644 (file)
@@ -122,6 +122,28 @@ public:
         }
     }
 
+    static std::chrono::milliseconds timeToLive(JITType jitType)
+    {
+        switch (jitType) {
+        case InterpreterThunk:
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(5));
+        case BaselineJIT:
+            // Effectively 10 additional seconds, since BaselineJIT and
+            // InterpreterThunk share a CodeBlock.
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(15));
+        case DFGJIT:
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(20));
+        case FTLJIT:
+            return std::chrono::duration_cast<std::chrono::milliseconds>(
+                std::chrono::seconds(60));
+        default:
+            return std::chrono::milliseconds::max();
+        }
+    }
+
     static bool isLowerTier(JITType expectedLower, JITType expectedHigher)
     {
         RELEASE_ASSERT(isExecutableScript(expectedLower));
index 840e262..e176829 100755 (executable)
@@ -666,7 +666,7 @@ void JIT::emit_op_enter(Instruction*)
     for (size_t j = CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters(); j < count; ++j)
         emitInitRegister(virtualRegisterForLocal(j).offset());
 
-    emitWriteBarrier(m_codeBlock);
+    emitWriteBarrier(m_codeBlock->ownerExecutable());
 
     emitEnterOptimizationCheck();
 }
index 8c92e1a..73ffd8d 100644 (file)
@@ -1267,13 +1267,15 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
             mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
         }
 
-        CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
+        RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
         CompilationResult result = DFG::compile(
-            vm, replacementCodeBlock, nullptr, DFG::DFGMode, bytecodeIndex,
+            vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
         
-        if (result != CompilationSuccessful)
+        if (result != CompilationSuccessful) {
+            ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
             return encodeResult(0, 0);
+        }
     }
     
     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
index 876b040..b42464f 100644 (file)
@@ -43,9 +43,8 @@ Ref<JITToDFGDeferredCompilationCallback> JITToDFGDeferredCompilationCallback::cr
 }
 
 void JITToDFGDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
+    CodeBlock* codeBlock)
 {
-    ASSERT_UNUSED(profiledDFGCodeBlock, !profiledDFGCodeBlock);
     ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
     
     if (Options::verboseOSR())
@@ -55,9 +54,8 @@ void JITToDFGDeferredCompilationCallback::compilationDidBecomeReadyAsynchronousl
 }
 
 void JITToDFGDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CompilationResult result)
 {
-    ASSERT(!profiledDFGCodeBlock);
     ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
     
     if (Options::verboseOSR())
@@ -68,7 +66,7 @@ void JITToDFGDeferredCompilationCallback::compilationDidComplete(
     
     codeBlock->alternative()->setOptimizationThresholdBasedOnCompilationResult(result);
 
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
 }
 
 } // JSC
index af2532f..f64b979 100644 (file)
@@ -44,8 +44,8 @@ public:
 
     static Ref<JITToDFGDeferredCompilationCallback> create();
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock) override;
-    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult) override;
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) override;
+    virtual void compilationDidComplete(CodeBlock*, CompilationResult) override;
 };
 
 } // namespace JSC
index 00ffb56..1db251f 100644 (file)
@@ -222,14 +222,15 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
         return GiveUpOnCache;
 
     CodeBlock* codeBlock = exec->codeBlock();
+    ScriptExecutable* owner = codeBlock->ownerScriptExecutable();
     VM& vm = exec->vm();
 
     std::unique_ptr<AccessCase> newCase;
 
     if (isJSArray(baseValue) && propertyName == exec->propertyNames().length)
-        newCase = AccessCase::getLength(vm, codeBlock, AccessCase::ArrayLength);
+        newCase = AccessCase::getLength(vm, owner, AccessCase::ArrayLength);
     else if (isJSString(baseValue) && propertyName == exec->propertyNames().length)
-        newCase = AccessCase::getLength(vm, codeBlock, AccessCase::StringLength);
+        newCase = AccessCase::getLength(vm, owner, AccessCase::StringLength);
     else {
         if (!slot.isCacheable() && !slot.isUnset())
             return GiveUpOnCache;
@@ -274,10 +275,10 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
             
             if (slot.isUnset()) {
                 conditionSet = generateConditionsForPropertyMiss(
-                    vm, codeBlock, exec, structure, propertyName.impl());
+                    vm, codeBlock->ownerExecutable(), exec, structure, propertyName.impl());
             } else {
                 conditionSet = generateConditionsForPrototypePropertyHit(
-                    vm, codeBlock, exec, structure, slot.slotBase(),
+                    vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(),
                     propertyName.impl());
             }
             
@@ -298,7 +299,7 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
             type = AccessCase::CustomGetter;
 
         newCase = AccessCase::get(
-            vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy,
+            vm, owner, type, offset, structure, conditionSet, loadTargetFromProxy,
             slot.watchpointSet(), slot.isCacheableCustom() ? slot.customGetter() : nullptr,
             slot.isCacheableCustom() ? slot.slotBase() : nullptr);
     }
@@ -352,6 +353,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
         return GiveUpOnCache;
     
     CodeBlock* codeBlock = exec->codeBlock();
+    ScriptExecutable* owner = codeBlock->ownerScriptExecutable();
     VM& vm = exec->vm();
 
     if (!baseValue.isCell())
@@ -382,7 +384,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
                 return RetryCacheLater;
             }
 
-            newCase = AccessCase::replace(vm, codeBlock, structure, slot.cachedOffset());
+            newCase = AccessCase::replace(vm, owner, structure, slot.cachedOffset());
         } else {
             ASSERT(slot.type() == PutPropertySlot::NewProperty);
 
@@ -404,12 +406,12 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (putKind == NotDirect) {
                 conditionSet =
                     generateConditionsForPropertySetterMiss(
-                        vm, codeBlock, exec, newStructure, ident.impl());
+                        vm, owner, exec, newStructure, ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
             }
 
-            newCase = AccessCase::transition(vm, codeBlock, structure, newStructure, offset, conditionSet);
+            newCase = AccessCase::transition(vm, owner, structure, newStructure, offset, conditionSet);
         }
     } else if (slot.isCacheableCustom() || slot.isCacheableSetter()) {
         if (slot.isCacheableCustom()) {
@@ -418,13 +420,13 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (slot.base() != baseValue) {
                 conditionSet =
                     generateConditionsForPrototypePropertyHitCustom(
-                        vm, codeBlock, exec, structure, slot.base(), ident.impl());
+                        vm, owner, exec, structure, slot.base(), ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
             }
 
             newCase = AccessCase::setter(
-                vm, codeBlock, AccessCase::CustomSetter, structure, invalidOffset, conditionSet,
+                vm, owner, AccessCase::CustomSetter, structure, invalidOffset, conditionSet,
                 slot.customSetter(), slot.base());
         } else {
             ObjectPropertyConditionSet conditionSet;
@@ -433,7 +435,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (slot.base() != baseValue) {
                 conditionSet =
                     generateConditionsForPrototypePropertyHit(
-                        vm, codeBlock, exec, structure, slot.base(), ident.impl());
+                        vm, owner, exec, structure, slot.base(), ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
                 offset = conditionSet.slotBaseCondition().offset();
@@ -441,7 +443,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
                 offset = slot.cachedOffset();
 
             newCase = AccessCase::setter(
-                vm, codeBlock, AccessCase::Setter, structure, offset, conditionSet);
+                vm, owner, AccessCase::Setter, structure, offset, conditionSet);
         }
     }
 
@@ -483,6 +485,7 @@ static InlineCacheAction tryRepatchIn(
     }
     
     CodeBlock* codeBlock = exec->codeBlock();
+    ScriptExecutable* owner = codeBlock->ownerScriptExecutable();
     VM& vm = exec->vm();
     Structure* structure = base->structure(vm);
     
@@ -490,17 +493,17 @@ static InlineCacheAction tryRepatchIn(
     if (wasFound) {
         if (slot.slotBase() != base) {
             conditionSet = generateConditionsForPrototypePropertyHit(
-                vm, codeBlock, exec, structure, slot.slotBase(), ident.impl());
+                vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(), ident.impl());
         }
     } else {
         conditionSet = generateConditionsForPropertyMiss(
-            vm, codeBlock, exec, structure, ident.impl());
+            vm, codeBlock->ownerExecutable(), exec, structure, ident.impl());
     }
     if (!conditionSet.isValid())
         return GiveUpOnCache;
 
     std::unique_ptr<AccessCase> newCase = AccessCase::in(
-        vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, structure, conditionSet);
+        vm, owner, wasFound ? AccessCase::InHit : AccessCase::InMiss, structure, conditionSet);
 
     MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(codeBlock, ident, WTF::move(newCase));
     if (!codePtr)
@@ -549,8 +552,8 @@ void linkFor(
     VM* vm = callerCodeBlock->vm();
     
     ASSERT(!callLinkInfo.isLinked());
-    callLinkInfo.setCallee(exec->callerFrame()->vm(), callLinkInfo.hotPathBegin(), callerCodeBlock, callee);
-    callLinkInfo.setLastSeenCallee(exec->callerFrame()->vm(), callerCodeBlock, callee);
+    callLinkInfo.setCallee(exec->callerFrame()->vm(), callLinkInfo.hotPathBegin(), callerCodeBlock->ownerExecutable(), callee);
+    callLinkInfo.setLastSeenCallee(exec->callerFrame()->vm(), callerCodeBlock->ownerExecutable(), callee);
     if (shouldShowDisassemblyFor(callerCodeBlock))
         dataLog("Linking call in ", *callerCodeBlock, " at ", callLinkInfo.codeOrigin(), " to ", pointerDump(calleeCodeBlock), ", entrypoint at ", codePtr, "\n");
     MacroAssembler::repatchNearCall(callLinkInfo.hotPathOther(), CodeLocationLabel(codePtr));
@@ -867,7 +870,7 @@ void linkPolymorphicCall(
             ("Polymorphic call stub for %s, return point %p, targets %s",
                 toCString(*callerCodeBlock).data(), callLinkInfo.callReturnLocation().labelAtOffset(0).executableAddress(),
                 toCString(listDump(callCases)).data())),
-        *vm, callerCodeBlock, exec->callerFrame(), callLinkInfo, callCases,
+        *vm, callerCodeBlock->ownerExecutable(), exec->callerFrame(), callLinkInfo, callCases,
         WTF::move(fastCounts)));
     
     MacroAssembler::replaceWithJump(
index e187f61..477ced0 100644 (file)
@@ -576,7 +576,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
         if (!structure->isUncacheableDictionary()
             && !structure->typeInfo().prohibitsPropertyCaching()
             && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
-            vm.heap.writeBarrier(codeBlock);
+            vm.heap.writeBarrier(codeBlock->ownerExecutable());
             
             ConcurrentJITLocker locker(codeBlock->m_lock);
 
@@ -641,7 +641,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
             && !structure->typeInfo().prohibitsPropertyCaching()
             && baseCell == slot.base()) {
 
-            vm.heap.writeBarrier(codeBlock);
+            vm.heap.writeBarrier(codeBlock->ownerExecutable());
             
             if (slot.type() == PutPropertySlot::NewProperty) {
                 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
@@ -658,7 +658,7 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
                             StructureChain* chain = structure->prototypeChain(exec);
                             ASSERT(chain);
                             pc[7].u.structureChain.set(
-                                vm, codeBlock, chain);
+                                vm, codeBlock->ownerExecutable(), chain);
                         }
                         pc[8].u.putByIdFlags = static_cast<PutByIdFlags>(
                             pc[8].u.putByIdFlags |
@@ -1190,8 +1190,8 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code
         
         if (callLinkInfo->isOnList())
             callLinkInfo->remove();
-        callLinkInfo->callee.set(vm, callerCodeBlock, callee);
-        callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock, callee);
+        callLinkInfo->callee.set(vm, callerCodeBlock->ownerExecutable(), callee);
+        callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock->ownerExecutable(), callee);
         callLinkInfo->machineCodeTarget = codePtr;
         if (codeBlock)
             codeBlock->linkIncomingCall(exec, callLinkInfo);
index b8eecdd..5c3242a 100644 (file)
@@ -52,7 +52,7 @@ OriginStack::OriginStack(Database& database, CodeBlock* codeBlock, const CodeOri
     
     for (unsigned i = 1; i < stack.size(); ++i) {
         append(Origin(
-            database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock.get()),
+            database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock()),
             stack[i].bytecodeIndex));
     }
 }
index 1ab78de..e29f13a 100644 (file)
@@ -231,7 +231,7 @@ SLOW_PATH_DECL(slow_path_create_this)
 
     auto& cacheWriteBarrier = pc[4].u.jsCell;
     if (!cacheWriteBarrier)
-        cacheWriteBarrier.set(exec->vm(), exec->codeBlock(), constructor);
+        cacheWriteBarrier.set(exec->vm(), exec->codeBlock()->ownerExecutable(), constructor);
     else if (cacheWriteBarrier.unvalidatedGet() != JSCell::seenMultipleCalleeObjects() && cacheWriteBarrier.get() != constructor)
         cacheWriteBarrier.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
 
@@ -250,7 +250,7 @@ SLOW_PATH_DECL(slow_path_to_this)
         if (myStructure != otherStructure) {
             if (otherStructure)
                 pc[3].u.toThisStatus = ToThisConflicted;
-            pc[2].u.structure.set(vm, exec->codeBlock(), myStructure);
+            pc[2].u.structure.set(vm, exec->codeBlock()->ownerExecutable(), myStructure);
         }
     } else {
         pc[3].u.toThisStatus = ToThisConflicted;
@@ -526,8 +526,8 @@ SLOW_PATH_DECL(slow_path_to_primitive)
 SLOW_PATH_DECL(slow_path_enter)
 {
     BEGIN();
-    CodeBlock* codeBlock = exec->codeBlock();
-    Heap::heap(codeBlock)->writeBarrier(codeBlock);
+    ExecutableBase* ownerExecutable = exec->codeBlock()->ownerExecutable();
+    Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable);
     END();
 }
 
index 444bc9f..05762e5 100644 (file)
@@ -129,7 +129,7 @@ inline void tryCachePutToScopeGlobal(
         scope->structure()->didCachePropertyReplacement(exec->vm(), slot.cachedOffset());
 
         ConcurrentJITLocker locker(codeBlock->m_lock);
-        pc[5].u.structure.set(exec->vm(), codeBlock, scope->structure());
+        pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
         pc[6].u.operand = slot.cachedOffset();
     }
 }
@@ -162,7 +162,7 @@ inline void tryCacheGetFromScopeGlobal(
             Structure* structure = scope->structure(vm);
             {
                 ConcurrentJITLocker locker(codeBlock->m_lock);
-                pc[5].u.structure.set(exec->vm(), codeBlock, structure);
+                pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
                 pc[6].u.operand = slot.cachedOffset();
             }
             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
index 030bcc5..9631c98 100644 (file)
@@ -60,45 +60,6 @@ void ExecutableBase::clearCode()
 #endif
     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
-
-    if (classInfo() == FunctionExecutable::info()) {
-        FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
-        executable->m_codeBlockForCall.clear();
-        executable->m_codeBlockForConstruct.clear();
-        return;
-    }
-
-    if (classInfo() == EvalExecutable::info()) {
-        EvalExecutable* executable = jsCast<EvalExecutable*>(this);
-        executable->m_evalCodeBlock.clear();
-        executable->m_unlinkedEvalCodeBlock.clear();
-        return;
-    }
-    
-    if (classInfo() == ProgramExecutable::info()) {
-        ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
-        executable->m_programCodeBlock.clear();
-        executable->m_unlinkedProgramCodeBlock.clear();
-        return;
-    }
-
-    if (classInfo() == ModuleProgramExecutable::info()) {
-        ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
-        executable->m_moduleProgramCodeBlock.clear();
-        executable->m_unlinkedModuleProgramCodeBlock.clear();
-        executable->m_moduleEnvironmentSymbolTable.clear();
-        return;
-    }
-    
-#if ENABLE(WEBASSEMBLY)
-    if (classInfo() == WebAssemblyExecutable::info()) {
-        WebAssemblyExecutable* executable = jsCast<WebAssemblyExecutable*>(this);
-        executable->m_codeBlockForCall.clear();
-        return;
-    }
-#endif
-
-    ASSERT(classInfo() == NativeExecutable::info());
 }
 
 #if ENABLE(DFG_JIT)
@@ -162,7 +123,7 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 {
     ASSERT(vm.heap.isDeferred());
     
-    CodeBlock* oldCodeBlock = nullptr;
+    RefPtr<CodeBlock> oldCodeBlock;
     
     switch (codeType) {
     case GlobalCode: {
@@ -171,8 +132,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         ASSERT(kind == CodeForCall);
         
-        oldCodeBlock = executable->m_programCodeBlock.get();
-        executable->m_programCodeBlock.setMayBeNull(vm, this, codeBlock);
+        oldCodeBlock = executable->m_programCodeBlock;
+        executable->m_programCodeBlock = codeBlock;
         break;
     }
 
@@ -182,8 +143,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 
         ASSERT(kind == CodeForCall);
 
-        oldCodeBlock = executable->m_moduleProgramCodeBlock.get();
-        executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, codeBlock);
+        oldCodeBlock = executable->m_moduleProgramCodeBlock;
+        executable->m_moduleProgramCodeBlock = codeBlock;
         break;
     }
 
@@ -193,8 +154,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         ASSERT(kind == CodeForCall);
         
-        oldCodeBlock = executable->m_evalCodeBlock.get();
-        executable->m_evalCodeBlock.setMayBeNull(vm, this, codeBlock);
+        oldCodeBlock = executable->m_evalCodeBlock;
+        executable->m_evalCodeBlock = codeBlock;
         break;
     }
         
@@ -204,12 +165,12 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         switch (kind) {
         case CodeForCall:
-            oldCodeBlock = executable->m_codeBlockForCall.get();
-            executable->m_codeBlockForCall.setMayBeNull(vm, this, codeBlock);
+            oldCodeBlock = executable->m_codeBlockForCall;
+            executable->m_codeBlockForCall = codeBlock;
             break;
         case CodeForConstruct:
-            oldCodeBlock = executable->m_codeBlockForConstruct.get();
-            executable->m_codeBlockForConstruct.setMayBeNull(vm, this, codeBlock);
+            oldCodeBlock = executable->m_codeBlockForConstruct;
+            executable->m_codeBlockForConstruct = codeBlock;
             break;
         }
         break;
@@ -249,7 +210,7 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
     vm.heap.writeBarrier(this);
 }
 
-CodeBlock* ScriptExecutable::newCodeBlockFor(
+RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
     CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
 {
     VM* vm = scope->vm();
@@ -263,9 +224,9 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_evalCodeBlock);
         RELEASE_ASSERT(!function);
-        return EvalCodeBlock::create(vm,
+        return adoptRef(new EvalCodeBlock(
             executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
-            executable->source().provider());
+            executable->source().provider()));
     }
     
     if (classInfo() == ProgramExecutable::info()) {
@@ -273,9 +234,9 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_programCodeBlock);
         RELEASE_ASSERT(!function);
-        return ProgramCodeBlock::create(vm,
+        return adoptRef(new ProgramCodeBlock(
             executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
-            executable->source().provider(), executable->source().startColumn());
+            executable->source().provider(), executable->source().startColumn()));
     }
 
     if (classInfo() == ModuleProgramExecutable::info()) {
@@ -283,9 +244,9 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
         RELEASE_ASSERT(!function);
-        return ModuleProgramCodeBlock::create(vm,
+        return adoptRef(new ModuleProgramCodeBlock(
             executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope,
-            executable->source().provider(), executable->source().startColumn());
+            executable->source().provider(), executable->source().startColumn()));
     }
 
     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
@@ -315,11 +276,11 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
     unsigned sourceOffset = executable->source().startOffset();
     unsigned startColumn = executable->source().startColumn();
 
-    return FunctionCodeBlock::create(vm,
-        executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn);
+    return adoptRef(new FunctionCodeBlock(
+        executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
 }
 
-CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
+PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
     CodeSpecializationKind kind)
 {
     if (classInfo() == EvalExecutable::info()) {
@@ -327,9 +288,9 @@ CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
             executable->m_evalCodeBlock->baselineVersion());
-        EvalCodeBlock* result = EvalCodeBlock::create(vm(),
-            CodeBlock::CopyParsedBlock, *baseline);
-        result->setAlternative(*vm(), baseline);
+        RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
+            CodeBlock::CopyParsedBlock, *baseline));
+        result->setAlternative(baseline);
         return result;
     }
     
@@ -338,9 +299,9 @@ CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
             executable->m_programCodeBlock->baselineVersion());
-        ProgramCodeBlock* result = ProgramCodeBlock::create(vm(),
-            CodeBlock::CopyParsedBlock, *baseline);
-        result->setAlternative(*vm(), baseline);
+        RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
+            CodeBlock::CopyParsedBlock, *baseline));
+        result->setAlternative(baseline);
         return result;
     }
 
@@ -349,9 +310,9 @@ CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
         ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>(
             executable->m_moduleProgramCodeBlock->baselineVersion());
-        ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(vm(),
-            CodeBlock::CopyParsedBlock, *baseline);
-        result->setAlternative(*vm(), baseline);
+        RefPtr<ModuleProgramCodeBlock> result = adoptRef(new ModuleProgramCodeBlock(
+            CodeBlock::CopyParsedBlock, *baseline));
+        result->setAlternative(baseline);
         return result;
     }
 
@@ -359,9 +320,9 @@ CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
         executable->codeBlockFor(kind)->baselineVersion());
-    FunctionCodeBlock* result = FunctionCodeBlock::create(vm(),
-        CodeBlock::CopyParsedBlock, *baseline);
-    result->setAlternative(*vm(), baseline);
+    RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
+        CodeBlock::CopyParsedBlock, *baseline));
+    result->setAlternative(baseline);
     return result;
 }
 
@@ -389,7 +350,7 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
     DeferGC deferGC(vm.heap);
     
     JSObject* exception = 0;
-    CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
+    RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
     if (!codeBlock) {
         RELEASE_ASSERT(exception);
         return exception;
@@ -399,11 +360,11 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
         codeBlock->validate();
     
     if (Options::useLLInt())
-        setupLLInt(vm, codeBlock);
+        setupLLInt(vm, codeBlock.get());
     else
-        setupJIT(vm, codeBlock);
+        setupJIT(vm, codeBlock.get());
     
-    installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
+    installCode(*codeBlock->vm(), codeBlock.get(), codeBlock->codeType(), codeBlock->specializationKind());
     return 0;
 }
 
@@ -541,9 +502,16 @@ void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ScriptExecutable::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
     if (thisObject->m_evalCodeBlock)
-        thisObject->m_evalCodeBlock->visitWeakly(visitor);
+        thisObject->m_evalCodeBlock->visitAggregate(visitor);
+    visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
+}
+
+void EvalExecutable::clearCode()
+{
+    m_evalCodeBlock = nullptr;
+    m_unlinkedEvalCodeBlock.clear();
+    Base::clearCode();
 }
 
 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
@@ -650,7 +618,14 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ScriptExecutable::visitChildren(thisObject, visitor);
     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
     if (thisObject->m_programCodeBlock)
-        thisObject->m_programCodeBlock->visitWeakly(visitor);
+        thisObject->m_programCodeBlock->visitAggregate(visitor);
+}
+
+void ProgramExecutable::clearCode()
+{
+    m_programCodeBlock = nullptr;
+    m_unlinkedProgramCodeBlock.clear();
+    Base::clearCode();
 }
 
 void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -661,7 +636,15 @@ void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_unlinkedModuleProgramCodeBlock);
     visitor.append(&thisObject->m_moduleEnvironmentSymbolTable);
     if (thisObject->m_moduleProgramCodeBlock)
-        thisObject->m_moduleProgramCodeBlock->visitWeakly(visitor);
+        thisObject->m_moduleProgramCodeBlock->visitAggregate(visitor);
+}
+
+void ModuleProgramExecutable::clearCode()
+{
+    m_moduleProgramCodeBlock = nullptr;
+    m_unlinkedModuleProgramCodeBlock.clear();
+    m_moduleEnvironmentSymbolTable.clear();
+    Base::clearCode();
 }
 
 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
@@ -684,13 +667,20 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ScriptExecutable::visitChildren(thisObject, visitor);
     if (thisObject->m_codeBlockForCall)
-        thisObject->m_codeBlockForCall->visitWeakly(visitor);
+        thisObject->m_codeBlockForCall->visitAggregate(visitor);
     if (thisObject->m_codeBlockForConstruct)
-        thisObject->m_codeBlockForConstruct->visitWeakly(visitor);
+        thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
     visitor.append(&thisObject->m_unlinkedExecutable);
     visitor.append(&thisObject->m_singletonFunction);
 }
 
+void FunctionExecutable::clearCode()
+{
+    m_codeBlockForCall = nullptr;
+    m_codeBlockForConstruct = nullptr;
+    Base::clearCode();
+}
+
 FunctionExecutable* FunctionExecutable::fromGlobalCode(
     const Identifier& name, ExecState& exec, const SourceCode& source, 
     JSObject*& exception, int overrideLineNumber)
@@ -726,10 +716,16 @@ void WebAssemblyExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ExecutableBase::visitChildren(thisObject, visitor);
     if (thisObject->m_codeBlockForCall)
-        thisObject->m_codeBlockForCall->visitWeakly(visitor);
+        thisObject->m_codeBlockForCall->visitAggregate(visitor);
     visitor.append(&thisObject->m_module);
 }
 
+void WebAssemblyExecutable::clearCode()
+{
+    m_codeBlockForCall = nullptr;
+    Base::clearCode();
+}
+
 void WebAssemblyExecutable::prepareForExecution(ExecState* exec)
 {
     if (hasJITCodeForCall())
@@ -738,16 +734,16 @@ void WebAssemblyExecutable::prepareForExecution(ExecState* exec)
     VM& vm = exec->vm();
     DeferGC deferGC(vm.heap);
 
-    WebAssemblyCodeBlock* codeBlock = WebAssemblyCodeBlock::create(vm,
-        this, exec->lexicalGlobalObject()));
+    RefPtr<WebAssemblyCodeBlock> codeBlock = adoptRef(new WebAssemblyCodeBlock(
+        this, vm, exec->lexicalGlobalObject()));
 
-    WASMFunctionParser::compile(vm, codeBlock, m_module.get(), m_source, m_functionIndex);
+    WASMFunctionParser::compile(vm, codeBlock.get(), m_module.get(), m_source, m_functionIndex);
 
     m_jitCodeForCall = codeBlock->jitCode();
     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
     m_numParametersForCall = codeBlock->numParameters();
 
-    m_codeBlockForCall.set(vm, this, codeBlock);
+    m_codeBlockForCall = codeBlock;
 
     Heap::heap(this)->writeBarrier(this);
 }
index 9fc9be7..155f44b 100644 (file)
@@ -139,6 +139,8 @@ protected:
     int m_numParametersForConstruct;
 
 public:
+    static void clearCodeVirtual(ExecutableBase*);
+
     PassRefPtr<JITCode> generatedJITCodeForCall()
     {
         ASSERT(m_jitCodeForCall);
@@ -304,8 +306,6 @@ protected:
     }
 
 private:
-    friend class ExecutableBase;
-
     NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
         : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
         , m_function(function)
@@ -376,8 +376,8 @@ public:
 
     void installCode(CodeBlock*);
     void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
-    CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
-    CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
+    RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
+    PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
     
     JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
     {
@@ -389,7 +389,6 @@ public:
     template <typename Functor> void forEachCodeBlock(Functor&&);
 
 private:
-    friend class ExecutableBase;
     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
 
 protected:
@@ -448,19 +447,20 @@ public:
         
     DECLARE_INFO;
 
+    void clearCode();
+
     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
 
     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
 
 private:
-    friend class ExecutableBase;
     friend class ScriptExecutable;
     EvalExecutable(ExecState*, const SourceCode&, bool);
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
+    RefPtr<EvalCodeBlock> m_evalCodeBlock;
     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
 };
 
@@ -501,10 +501,11 @@ public:
         
     DECLARE_INFO;
 
+    void clearCode();
+
     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
 
 private:
-    friend class ExecutableBase;
     friend class ScriptExecutable;
 
     ProgramExecutable(ExecState*, const SourceCode&);
@@ -512,7 +513,7 @@ private:
     static void visitChildren(JSCell*, SlotVisitor&);
 
     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
-    WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
+    RefPtr<ProgramCodeBlock> m_programCodeBlock;
 };
 
 class ModuleProgramExecutable final : public ScriptExecutable {
@@ -542,13 +543,14 @@ public:
 
     DECLARE_INFO;
 
+    void clearCode();
+
     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, false); }
     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
 
     SymbolTable* moduleEnvironmentSymbolTable() { return m_moduleEnvironmentSymbolTable.get(); }
 
 private:
-    friend class ExecutableBase;
     friend class ScriptExecutable;
 
     ModuleProgramExecutable(ExecState*, const SourceCode&);
@@ -557,7 +559,7 @@ private:
 
     WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
     WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
-    WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
+    RefPtr<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
 };
 
 class FunctionExecutable final : public ScriptExecutable {
@@ -598,7 +600,7 @@ public:
         
     bool isGeneratedForCall() const
     {
-        return !!m_codeBlockForCall;
+        return m_codeBlockForCall;
     }
 
     FunctionCodeBlock* codeBlockForCall()
@@ -608,7 +610,7 @@ public:
 
     bool isGeneratedForConstruct() const
     {
-        return m_codeBlockForConstruct.get();
+        return m_codeBlockForConstruct;
     }
 
     FunctionCodeBlock* codeBlockForConstruct()
@@ -674,10 +676,11 @@ public:
 
     DECLARE_INFO;
 
+    void clearCode();
+    
     InferredValue* singletonFunction() { return m_singletonFunction.get(); }
 
 private:
-    friend class ExecutableBase;
     FunctionExecutable(
         VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, 
         unsigned lastLine, unsigned startColumn, unsigned endColumn);
@@ -687,8 +690,8 @@ private:
     friend class ScriptExecutable;
     
     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
-    WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
-    WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
+    RefPtr<FunctionCodeBlock> m_codeBlockForCall;
+    RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
     RefPtr<TypeSet> m_returnStatementTypeSet;
     unsigned m_parametersStartOffset;
     WriteBarrier<InferredValue> m_singletonFunction;
@@ -716,6 +719,8 @@ public:
 
     DECLARE_INFO;
 
+    void clearCode();
+
     void prepareForExecution(ExecState*);
 
     WebAssemblyCodeBlock* codeBlockForCall()
@@ -724,7 +729,6 @@ public:
     }
 
 private:
-    friend class ExecutableBase;
     WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
 
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -733,10 +737,30 @@ private:
     WriteBarrier<JSWASMModule> m_module;
     unsigned m_functionIndex;
 
-    WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
+    RefPtr<WebAssemblyCodeBlock> m_codeBlockForCall;
 };
 #endif
 
-} // namespace JSC
+inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
+{
+    switch (executable->type()) {
+    case EvalExecutableType:
+        return jsCast<EvalExecutable*>(executable)->clearCode();
+    case ProgramExecutableType:
+        return jsCast<ProgramExecutable*>(executable)->clearCode();
+    case FunctionExecutableType:
+        return jsCast<FunctionExecutable*>(executable)->clearCode();
+#if ENABLE(WEBASSEMBLY)
+    case WebAssemblyExecutableType:
+        return jsCast<WebAssemblyExecutable*>(executable)->clearCode();
+#endif
+    case ModuleProgramExecutableType:
+        return jsCast<ModuleProgramExecutable*>(executable)->clearCode();
+    default:
+        return jsCast<NativeExecutable*>(executable)->clearCode();
+    }
+}
+
+}
 
-#endif // Executable_h
+#endif
index 695fadc..b2c51dd 100644 (file)
@@ -247,14 +247,6 @@ VM::VM(VMType vmType, HeapType heapType)
     exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
     promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
     internalPromiseDeferredStructure.set(*this, JSInternalPromiseDeferred::createStructure(*this, 0, jsNull()));
-    programCodeBlockStructure.set(*this, ProgramCodeBlock::createStructure(*this, 0, jsNull()));
-    moduleProgramCodeBlockStructure.set(*this, ModuleProgramCodeBlock::createStructure(*this, 0, jsNull()));
-    evalCodeBlockStructure.set(*this, EvalCodeBlock::createStructure(*this, 0, jsNull()));
-    functionCodeBlockStructure.set(*this, FunctionCodeBlock::createStructure(*this, 0, jsNull()));
-#if ENABLE(WEBASSEMBLY)
-    webAssemblyCodeBlockStructure.set(*this, WebAssemblyCodeBlock::createStructure(*this, 0, jsNull()));
-#endif
-
     iterationTerminator.set(*this, JSFinalObject::create(*this, JSFinalObject::createStructure(*this, 0, jsNull(), 1)));
     nativeStdFunctionCellStructure.set(*this, NativeStdFunctionCell::createStructure(*this, 0, jsNull()));
     smallStrings.initializeCommonStrings(*this);
index 87d1662..a49b94e 100644 (file)
@@ -309,12 +309,6 @@ public:
     Strong<Structure> promiseDeferredStructure;
     Strong<Structure> internalPromiseDeferredStructure;
     Strong<Structure> nativeStdFunctionCellStructure;
-    Strong<Structure> programCodeBlockStructure;
-    Strong<Structure> moduleProgramCodeBlockStructure;
-    Strong<Structure> evalCodeBlockStructure;
-    Strong<Structure> functionCodeBlockStructure;
-    Strong<Structure> webAssemblyCodeBlockStructure;
-
     Strong<JSCell> iterationTerminator;
     Strong<JSCell> emptyPropertyNameEnumerator;