Unreviewed, rolling back in r190450
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Oct 2015 21:16:20 +0000 (21:16 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Oct 2015 21:16:20 +0000 (21:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149727

The cause of the crash was a CodeBlock, after surviving a call to
deleteAllCode by virtue of being in the remembered set, trying to mark
its inlined CodeBlocks via pointers from its inlined executables.
Since deleteAllCode clears those pointers, the CodeBlock would ASSERT.
(Any other choice to retain a CodeBlock after deleteAllCode -- for
example, conservative marking -- could trigger the same bug.)

The fix is for InlineCallFrame to point directly to its inlined CodeBlock
instead of pointing indirectly via an executable. This guarantees that
CodeBlocks are GC safe regardless of whether we've called deleteAllCode.

Restored changesets:

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

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

56 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/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 30da5a5..93bd84e 100644 (file)
@@ -1,3 +1,25 @@
+2015-10-01  Geoffrey Garen  <ggaren@apple.com>
+
+        Unreviewed, rolling back in r190450
+        https://bugs.webkit.org/show_bug.cgi?id=149727
+
+        The cause of the crash was a CodeBlock, after surviving a call to
+        deleteAllCode by virtue of being in the remembered set, trying to mark
+        its inlined CodeBlocks via pointers from its inlined executables.
+        Since deleteAllCode clears those pointers, the CodeBlock would ASSERT.
+        (Any other choice to retain a CodeBlock after deleteAllCode -- for
+        example, conservative marking -- could trigger the same bug.)
+
+        The fix is for InlineCallFrame to point directly to its inlined CodeBlock
+        instead of pointing indirectly via an executable. This guarantees that
+        CodeBlocks are GC safe regardless of whether we've called deleteAllCode.
+
+        Restored changesets:
+
+        "CodeBlock should be a GC object"
+        https://bugs.webkit.org/show_bug.cgi?id=149727
+        http://trac.webkit.org/changeset/190450
+
 2015-10-02  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Include Garbage Collection Event in Timeline
index bf6d19d..3f93640 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()) {
@@ -153,7 +217,7 @@ void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType)
     out.print(inferredName(), "#", hashAsStringIfPossible());
     out.print(":[", RawPointer(this), "->");
     if (!!m_alternative)
-        out.print(RawPointer(m_alternative.get()), "->");
+        out.print(RawPointer(alternative()), "->");
     out.print(RawPointer(ownerExecutable()), ", ", jitType, codeType());
 
     if (codeType() == FunctionCode)
@@ -1585,8 +1649,9 @@ private:
 
 } // anonymous namespace
 
-CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
-    : m_globalObject(other.m_globalObject)
+CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock& other)
+    : JSCell(*vm, structure)
+    , m_globalObject(other.m_globalObject)
     , m_heap(other.m_heap)
     , m_numCalleeRegisters(other.m_numCalleeRegisters)
     , m_numVars(other.m_numVars)
@@ -1594,11 +1659,11 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_hasBeenCompiledWithFTL(false)
-    , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
+    , m_unlinkedCode(*other.m_vm, this, other.m_unlinkedCode.get())
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
+    , m_ownerExecutable(*other.m_vm, this, other.m_ownerExecutable.get())
     , m_vm(other.m_vm)
     , m_instructions(other.m_instructions)
     , m_thisRegister(other.m_thisRegister)
@@ -1623,13 +1688,18 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
-    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
-    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitWeaklyHasBeenCalled.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();
 
@@ -1643,11 +1713,12 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     }
     
     m_heap->m_codeBlocks.add(this);
-    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
 }
 
-CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
-    : m_globalObject(scope->globalObject()->vm(), ownerExecutable, scope->globalObject())
+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())
     , m_heap(&m_globalObject->vm().heap)
     , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
     , m_numVars(unlinkedCodeBlock->m_numVars)
@@ -1655,11 +1726,11 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_hasBeenCompiledWithFTL(false)
-    , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
+    , m_unlinkedCode(m_globalObject->vm(), this, unlinkedCodeBlock)
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
+    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
     , m_vm(unlinkedCodeBlock->vm())
     , m_thisRegister(unlinkedCodeBlock->thisRegister())
     , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
@@ -1678,26 +1749,31 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
 {
-    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
-    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
 
     ASSERT(m_heap->isDeferred());
     ASSERT(m_scopeRegister.isLocal());
 
     ASSERT(m_source);
     setNumParameters(unlinkedCodeBlock->numParameters());
+}
 
-    if (vm()->typeProfiler() || vm()->controlFlowProfiler())
-        vm()->functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
+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());
 
     setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
     if (unlinkedCodeBlock->usesGlobalObject())
-        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
+        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, 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, ownerExecutable, m_globalObject->jsCellForLinkTimeConstant(type));
+            m_constantRegisters[registerIndex].set(*m_vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
     }
 
     HashSet<int, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> clonedConstantSymbolTables;
@@ -1712,7 +1788,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                     ConcurrentJITLocker locker(symbolTable->m_lock);
                     symbolTable->prepareForTypeProfiling(locker);
                 }
-                m_constantRegisters[i].set(*m_vm, ownerExecutable, symbolTable->cloneScopePart(*m_vm));
+                m_constantRegisters[i].set(*m_vm, this, symbolTable->cloneScopePart(*m_vm));
                 clonedConstantSymbolTables.add(i + FirstConstantRegisterIndex);
             }
         }
@@ -1732,17 +1808,17 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     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, ownerExecutable, 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, this, 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, ownerExecutable, 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, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
     }
 
     if (unlinkedCodeBlock->hasRareData()) {
@@ -1821,7 +1897,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
 
         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;
@@ -1880,7 +1956,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             int inferredInlineCapacity = pc[opLength - 2].u.operand;
 
             instructions[i + opLength - 1] = objectAllocationProfile;
-            objectAllocationProfile->initialize(*vm(),
+            objectAllocationProfile->initialize(vm,
                 ownerExecutable, m_globalObject->objectPrototype(), inferredInlineCapacity);
             break;
         }
@@ -1929,11 +2005,11 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                     // 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(), ownerExecutable, op.lexicalEnvironment);
+                    instructions[i + 6].u.jsCell.set(vm, this, op.lexicalEnvironment);
                 } else
-                    instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable());
+                    instructions[i + 6].u.symbolTable.set(vm, this, op.lexicalEnvironment->symbolTable());
             } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this))
-                instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, constantScope);
+                instructions[i + 6].u.jsCell.set(vm, this, constantScope);
             else
                 instructions[i + 6].u.pointer = nullptr;
             break;
@@ -1966,7 +2042,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             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(), ownerExecutable, op.structure);
+                instructions[i + 5].u.structure.set(vm, this, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
             break;
         }
@@ -2003,14 +2079,14 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                 if (op.watchpointSet)
                     op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
             } else if (op.structure)
-                instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
+                instructions[i + 5].u.structure.set(vm, this, 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;
@@ -2040,8 +2116,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                     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;
 
@@ -2054,8 +2130,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                 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;
             }
@@ -2081,8 +2157,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             }
             }
 
-            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;
 
@@ -2090,7 +2166,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
                 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();
 
             if (shouldAnalyze && isNewLocation)
-                vm()->typeProfiler()->insertNewLocation(location);
+                vm.typeProfiler()->insertNewLocation(location);
 
             instructions[i + 2].u.location = location;
             break;
@@ -2108,7 +2184,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
         i += opLength;
     }
 
-    if (vm()->controlFlowProfiler())
+    if (vm.controlFlowProfiler())
         insertBasicBlockBoundariesForControlFlowProfiler(instructions);
 
     m_instructions = WTF::RefCountedArray<Instruction>(instructions);
@@ -2128,12 +2204,13 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
         dumpBytecode();
     
     m_heap->m_codeBlocks.add(this);
-    m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
+    m_heap->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
 }
 
 #if ENABLE(WEBASSEMBLY)
-CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
-    : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
+CodeBlock::CodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
+    : JSCell(vm, structure)
+    , m_globalObject(globalObject->vm(), this, globalObject)
     , m_heap(&m_globalObject->vm().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
@@ -2144,7 +2221,7 @@ CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObj
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
+    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
     , m_vm(&vm)
     , m_isStrictMode(false)
     , m_needsActivation(false)
@@ -2158,9 +2235,13 @@ CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObj
 #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
 
@@ -2172,29 +2253,30 @@ 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.
-    while (m_incomingCalls.begin() != m_incomingCalls.end())
-        m_incomingCalls.begin()->remove();
-    while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
-        m_incomingPolymorphicCalls.begin()->remove();
+    unlinkIncomingCalls();
     
     // 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)
         (*iter)->deref();
 #endif // ENABLE(JIT)
 }
 
+void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
+{
+    m_alternative.set(vm, this, alternative);
+}
+
 void CodeBlock::setNumParameters(int newValue)
 {
     m_numParameters = newValue;
@@ -2215,73 +2297,43 @@ CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
     if (jitType() != JITCode::DFGJIT)
         return 0;
     DFG::JITCode* jitCode = m_jitCode->dfg();
-    return jitCode->osrEntryBlock.get();
+    return jitCode->osrEntryBlock();
 #else // ENABLE(FTL_JIT)
     return 0;
 #endif // ENABLE(FTL_JIT)
 }
 
-void CodeBlock::visitStrongly(SlotVisitor& visitor)
+void CodeBlock::visitWeakly(SlotVisitor& visitor)
 {
-    bool setByMe = m_visitStronglyHasBeenCalled.compareExchangeStrong(false, true);
+    bool setByMe = m_visitWeaklyHasBeenCalled.compareExchangeStrong(false, true);
     if (!setByMe)
         return;
 
-    visitAggregate(visitor);
-
-    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)
+    if (Heap::isMarked(this))
         return;
-    
-    if (!!m_alternative)
-        m_alternative->visitAggregate(visitor);
-    
-    if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
-        otherBlock->visitAggregate(visitor);
 
-    visitor.reportExtraMemoryVisited(ownerExecutable(), sizeof(CodeBlock));
-    if (m_jitCode)
-        visitor.reportExtraMemoryVisited(ownerExecutable(), 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(ownerExecutable(), m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
+    if (shouldVisitStrongly()) {
+        visitor.appendUnbarrieredReadOnlyPointer(this);
+        return;
     }
 
-    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(this);
-    
-    m_allTransitionsHaveBeenMarked = false;
-    
-    if (shouldVisitStrongly()) {
-        visitStrongly(visitor);
-        return;
-    }
-    
+    visitor.addUnconditionalFinalizer(&m_unconditionalFinalizer);
+
     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(this);
+    visitor.addWeakReferenceHarvester(&m_weakReferenceHarvester);
 
 #if ENABLE(DFG_JIT)
     // We get here if we're live in the sense that our owner executable is live,
@@ -2292,14 +2344,48 @@ void CodeBlock::visitAggregate(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_jitCode->dfgCommon()->livenessHasBeenProved = false;
-    
+
+    m_allTransitionsHaveBeenMarked = false;
     propagateTransitions(visitor);
+
+    m_jitCode->dfgCommon()->livenessHasBeenProved = false;
     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(this, m_jitCode->size());
+    if (m_instructions.size())
+        visitor.reportExtraMemoryVisited(this, 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())
@@ -2327,17 +2413,7 @@ bool CodeBlock::isKnownToBeLiveDuringGC()
     //   because livenessHasBeenProved would have survived as true.
     // - Code blocks that don't have any dead weak references.
 
-    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;
+    return Heap::isMarked(this);
 }
 
 bool CodeBlock::shouldJettisonDueToWeakReference()
@@ -2347,12 +2423,34 @@ 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 (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
+    if (Heap::isMarked(this))
         return false;
 
-    if (timeSinceCreation() < JITCode::timeToLive(jitType()))
+    if (timeSinceCreation() < timeToLive(jitType()))
         return false;
 
     return true;
@@ -2505,14 +2603,18 @@ 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;
-    stronglyVisitStrongReferences(visitor);
+    visitor.appendUnbarrieredReadOnlyPointer(this);
 #endif // ENABLE(DFG_JIT)
 }
 
-void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
+void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)
 {
-    propagateTransitions(visitor);
-    determineLiveness(visitor);
+    CodeBlock* codeBlock =
+        bitwise_cast<CodeBlock*>(
+            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_weakReferenceHarvester));
+
+    codeBlock->propagateTransitions(visitor);
+    codeBlock->determineLiveness(visitor);
 }
 
 void CodeBlock::finalizeLLIntInlineCaches()
@@ -2632,26 +2734,29 @@ void CodeBlock::finalizeBaselineJITInlineCaches()
 #endif
 }
 
-void CodeBlock::finalizeUnconditionally()
+void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
 {
+    CodeBlock* codeBlock = bitwise_cast<CodeBlock*>(
+        bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_unconditionalFinalizer));
+
 #if ENABLE(DFG_JIT)
-    if (shouldJettisonDueToWeakReference()) {
-        jettison(Profiler::JettisonDueToWeakReference);
+    if (codeBlock->shouldJettisonDueToWeakReference()) {
+        codeBlock->jettison(Profiler::JettisonDueToWeakReference);
         return;
     }
 #endif // ENABLE(DFG_JIT)
 
-    if (shouldJettisonDueToOldAge()) {
-        jettison(Profiler::JettisonDueToOldAge);
+    if (codeBlock->shouldJettisonDueToOldAge()) {
+        codeBlock->jettison(Profiler::JettisonDueToOldAge);
         return;
     }
 
-    if (JITCode::couldBeInterpreted(jitType()))
-        finalizeLLIntInlineCaches();
+    if (JITCode::couldBeInterpreted(codeBlock->jitType()))
+        codeBlock->finalizeLLIntInlineCaches();
 
 #if ENABLE(JIT)
-    if (!!jitCode())
-        finalizeBaselineJITInlineCaches();
+    if (!!codeBlock->jitCode())
+        codeBlock->finalizeBaselineJITInlineCaches();
 #endif
 }
 
@@ -2746,14 +2851,14 @@ void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor)
     // guaranteeing that it matches the details of the CodeBlock we compiled
     // the OSR exit against.
 
-    alternative()->visitStrongly(visitor);
+    visitor.append(&m_alternative);
 
 #if ENABLE(DFG_JIT)
     DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
     if (dfgCommon->inlineCallFrames) {
         for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
-            ASSERT(inlineCallFrame->baselineCodeBlock());
-            inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
+            ASSERT(inlineCallFrame->baselineCodeBlock);
+            visitor.append(&inlineCallFrame->baselineCodeBlock);
         }
     }
 #endif
@@ -2962,8 +3067,6 @@ 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())
@@ -2977,66 +3080,66 @@ void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* inco
     m_incomingLLIntCalls.push(incoming);
 }
 
-PassRefPtr<CodeBlock> CodeBlock::newReplacement()
+CodeBlock* CodeBlock::newReplacement()
 {
     return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
 }
 
 #if ENABLE(JIT)
-CodeBlock* ProgramCodeBlock::replacement()
+CodeBlock* CodeBlock::replacement()
 {
-    return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
-}
+    const ClassInfo* classInfo = this->classInfo();
 
-CodeBlock* ModuleProgramCodeBlock::replacement()
-{
-    return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
-}
+    if (classInfo == FunctionCodeBlock::info())
+        return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
 
-CodeBlock* EvalCodeBlock::replacement()
-{
-    return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
-}
+    if (classInfo == EvalCodeBlock::info())
+        return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
 
-CodeBlock* FunctionCodeBlock::replacement()
-{
-    return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
-}
+    if (classInfo == ProgramCodeBlock::info())
+        return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
 
-DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
-{
-    return DFG::programCapabilityLevel(this);
-}
+    if (classInfo == ModuleProgramCodeBlock::info())
+        return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
 
-DFG::CapabilityLevel ModuleProgramCodeBlock::capabilityLevelInternal()
-{
-    return DFG::programCapabilityLevel(this);
-}
+#if ENABLE(WEBASSEMBLY)
+    if (classInfo == WebAssemblyCodeBlock::info())
+        return nullptr
+#endif
 
-DFG::CapabilityLevel EvalCodeBlock::capabilityLevelInternal()
-{
-    return DFG::evalCapabilityLevel(this);
+    RELEASE_ASSERT_NOT_REACHED();
+    return nullptr;
 }
 
-DFG::CapabilityLevel FunctionCodeBlock::capabilityLevelInternal()
+DFG::CapabilityLevel CodeBlock::computeCapabilityLevel()
 {
-    if (m_isConstructor)
-        return DFG::functionForConstructCapabilityLevel(this);
-    return DFG::functionForCallCapabilityLevel(this);
-}
+    const ClassInfo* classInfo = this->classInfo();
+
+    if (classInfo == FunctionCodeBlock::info()) {
+        if (m_isConstructor)
+            return DFG::functionForConstructCapabilityLevel(this);
+        return DFG::functionForCallCapabilityLevel(this);
+    }
+
+    if (classInfo == EvalCodeBlock::info())
+        return DFG::evalCapabilityLevel(this);
+
+    if (classInfo == ProgramCodeBlock::info())
+        return DFG::programCapabilityLevel(this);
+
+    if (classInfo == ModuleProgramCodeBlock::info())
+        return DFG::programCapabilityLevel(this);
 
 #if ENABLE(WEBASSEMBLY)
-CodeBlock* WebAssemblyCodeBlock::replacement()
-{
-    return nullptr;
-}
+    if (classInfo == WebAssemblyCodeBlock::info())
+        return DFG::CannotCompile;
+#endif
 
-DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()
-{
+    RELEASE_ASSERT_NOT_REACHED();
     return DFG::CannotCompile;
 }
-#endif
-#endif
+
+#endif // ENABLE(JIT)
 
 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
 {
@@ -3140,7 +3243,7 @@ JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
 {
     if (!codeOrigin.inlineCallFrame)
         return globalObject();
-    return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->eitherCodeBlock()->globalObject();
+    return codeOrigin.inlineCallFrame->baselineCodeBlock->globalObject();
 }
 
 class RecursionCheckFunctor {
@@ -3980,7 +4083,7 @@ unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
 #if ENABLE(JIT)
 DFG::CapabilityLevel CodeBlock::capabilityLevel()
 {
-    DFG::CapabilityLevel result = capabilityLevelInternal();
+    DFG::CapabilityLevel result = computeCapabilityLevel();
     m_capabilityLevelState = result;
     return result;
 }
index 5c2b10c..1e4e3ec 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"
@@ -85,26 +86,45 @@ class JSModuleEnvironment;
 
 enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };
 
-class CodeBlock : public ThreadSafeRefCounted<CodeBlock>, public UnconditionalFinalizer, public WeakReferenceHarvester {
-    WTF_MAKE_FAST_ALLOCATED;
+class CodeBlock : public JSCell {
+    typedef JSCell Base;
     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(CopyParsedBlockTag, CodeBlock& other);
-        
-    CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
+    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*);
 #if ENABLE(WEBASSEMBLY)
-    CodeBlock(WebAssemblyExecutable* ownerExecutable, VM&, JSGlobalObject*);
+    void finishCreation(VM&, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);
 #endif
 
     WriteBarrier<JSGlobalObject> m_globalObject;
     Heap* m_heap;
 
 public:
-    JS_EXPORT_PRIVATE virtual ~CodeBlock();
+    JS_EXPORT_PRIVATE ~CodeBlock();
 
     UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }
 
@@ -124,8 +144,8 @@ public:
     int* addressOfNumParameters() { return &m_numParameters; }
     static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
 
-    CodeBlock* alternative() { return m_alternative.get(); }
-    void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
+    CodeBlock* alternative() const { return static_cast<CodeBlock*>(m_alternative.get()); }
+    void setAlternative(VM&, CodeBlock*);
 
     template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)
     {
@@ -148,16 +168,18 @@ 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();
 
-    void clearMarks();
-    void visitAggregate(SlotVisitor&);
-    void visitStrongly(SlotVisitor&);
+    static void visitChildren(JSCell*, SlotVisitor&);
+    void visitChildren(SlotVisitor&);
+    void visitWeakly(SlotVisitor&);
+    void clearVisitWeaklyHasBeenCalled();
 
     void dumpSource();
     void dumpSource(PrintStream&);
@@ -265,7 +287,7 @@ public:
     unsigned instructionCount() const { return m_instructions.size(); }
 
     // Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())
-    PassRefPtr<CodeBlock> newReplacement();
+    CodeBlock* newReplacement();
     
     void setJITCode(PassRefPtr<JITCode> code)
     {
@@ -291,9 +313,9 @@ public:
     }
     
 #if ENABLE(JIT)
-    virtual CodeBlock* replacement() = 0;
+    CodeBlock* replacement();
 
-    virtual DFG::CapabilityLevel capabilityLevelInternal() = 0;
+    DFG::CapabilityLevel computeCapabilityLevel();
     DFG::CapabilityLevel capabilityLevel();
     DFG::CapabilityLevel capabilityLevelState() { return m_capabilityLevelState; }
 
@@ -543,7 +565,7 @@ public:
     {
         unsigned result = m_constantRegisters.size();
         m_constantRegisters.append(WriteBarrier<Unknown>());
-        m_constantRegisters.last().set(m_globalObject->vm(), m_ownerExecutable.get(), v);
+        m_constantRegisters.last().set(m_globalObject->vm(), this, v);
         m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
         return result;
     }
@@ -895,8 +917,6 @@ public:
     }
 
 protected:
-    virtual void visitWeakReferences(SlotVisitor&) override;
-    virtual void finalizeUnconditionally() override;
     void finalizeLLIntInlineCaches();
     void finalizeBaselineJITInlineCaches();
 
@@ -923,14 +943,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, ownerExecutable(), constants[i].get());
+            m_constantRegisters[i].set(*m_vm, this, 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(), m_ownerExecutable.get(), value);
+        m_constantRegisters[index - FirstConstantRegisterIndex].set(m_globalObject->vm(), this, value);
     }
 
     void dumpBytecode(
@@ -1002,8 +1022,7 @@ private:
     bool m_isStrictMode;
     bool m_needsActivation;
 
-    Atomic<bool> m_visitAggregateHasBeenCalled;
-    Atomic<bool> m_visitStronglyHasBeenCalled;
+    Atomic<bool> m_visitWeaklyHasBeenCalled;
 
     RefPtr<SourceProvider> m_source;
     unsigned m_sourceOffset;
@@ -1045,7 +1064,7 @@ private:
     Vector<WriteBarrier<FunctionExecutable>> m_functionDecls;
     Vector<WriteBarrier<FunctionExecutable>> m_functionExprs;
 
-    RefPtr<CodeBlock> m_alternative;
+    WriteBarrier<CodeBlock> m_alternative;
     
     BaselineExecutionCounter m_llintExecuteCounter;
 
@@ -1065,124 +1084,242 @@ 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(CopyParsedBlockTag, GlobalCodeBlock& other)
-    : CodeBlock(CopyParsedBlock, other)
+    GlobalCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, GlobalCodeBlock& other)
+        : CodeBlock(vm, structure, CopyParsedBlock, other)
     {
     }
-        
-    GlobalCodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
-        : CodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
+
+    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)
     {
     }
 };
 
 class ProgramCodeBlock : public GlobalCodeBlock {
 public:
-    ProgramCodeBlock(CopyParsedBlockTag, ProgramCodeBlock& other)
-    : GlobalCodeBlock(CopyParsedBlock, other)
+    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;
     }
 
-    ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
-        : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
+    static ProgramCodeBlock* create(VM* vm, ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock,
+        JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
     {
+        ProgramCodeBlock* instance = new (NotNull, allocateCell<ProgramCodeBlock>(vm->heap))
+            ProgramCodeBlock(vm, vm->programCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, firstLineColumnOffset);
+        instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+        return instance;
     }
 
-#if ENABLE(JIT)
-protected:
-    virtual CodeBlock* replacement() override;
-    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
-#endif
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+    }
+
+private:
+    ProgramCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, ProgramCodeBlock& other)
+        : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)
+    {
+    }
+
+    ProgramCodeBlock(VM* vm, Structure* structure, ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock,
+        JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
+        : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
+    {
+    }
+
+    static void destroy(JSCell*);
 };
 
 class ModuleProgramCodeBlock : public GlobalCodeBlock {
 public:
-    ModuleProgramCodeBlock(CopyParsedBlockTag, ModuleProgramCodeBlock& other)
-        : GlobalCodeBlock(CopyParsedBlock, other)
+    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;
     }
 
-    ModuleProgramCodeBlock(ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
-        : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
+    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;
     }
 
-#if ENABLE(JIT)
-protected:
-    virtual CodeBlock* replacement() override;
-    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
-#endif
+    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(VM* vm, Structure* structure, ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock,
+        JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
+        : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)
+    {
+    }
+
+    static void destroy(JSCell*);
 };
 
 class EvalCodeBlock : public GlobalCodeBlock {
 public:
-    EvalCodeBlock(CopyParsedBlockTag, EvalCodeBlock& other)
-        : GlobalCodeBlock(CopyParsedBlock, other)
+    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;
     }
-        
-    EvalCodeBlock(EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)
-        : GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, 1)
+
+    static EvalCodeBlock* create(VM* vm, EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock,
+        JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)
     {
+        EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))
+            EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider);
+        instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+        return instance;
     }
-    
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+    }
+
     const Identifier& variable(unsigned index) { return unlinkedEvalCodeBlock()->variable(index); }
     unsigned numVariables() { return unlinkedEvalCodeBlock()->numVariables(); }
     
-#if ENABLE(JIT)
-protected:
-    virtual CodeBlock* replacement() override;
-    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
-#endif
+private:
+    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)
+    {
+    }
     
+    static void destroy(JSCell*);
+
 private:
     UnlinkedEvalCodeBlock* unlinkedEvalCodeBlock() const { return jsCast<UnlinkedEvalCodeBlock*>(unlinkedCodeBlock()); }
 };
 
 class FunctionCodeBlock : public CodeBlock {
 public:
-    FunctionCodeBlock(CopyParsedBlockTag, FunctionCodeBlock& other)
-        : CodeBlock(CopyParsedBlock, other)
+    typedef CodeBlock Base;
+    DECLARE_INFO;
+
+    static FunctionCodeBlock* create(VM* vm, CopyParsedBlockTag, FunctionCodeBlock& other)
+    {
+        FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))
+            FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), CopyParsedBlock, other);
+        instance->finishCreation(*vm, CopyParsedBlock, other);
+        return instance;
+    }
+
+    static FunctionCodeBlock* create(VM* vm, FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope,
+        PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
     {
+        FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))
+            FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset);
+        instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
+        return instance;
     }
 
-    FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
-        : CodeBlock(ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)
+    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)
     {
     }
     
-#if ENABLE(JIT)
-protected:
-    virtual CodeBlock* replacement() override;
-    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
-#endif
+    static void destroy(JSCell*);
 };
 
 #if ENABLE(WEBASSEMBLY)
 class WebAssemblyCodeBlock : public CodeBlock {
 public:
-    WebAssemblyCodeBlock(CopyParsedBlockTag, WebAssemblyCodeBlock& other)
-        : CodeBlock(CopyParsedBlock, other)
+    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;
     }
 
-    WebAssemblyCodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
-        : CodeBlock(ownerExecutable, vm, globalObject)
+    static WebAssemblyCodeBlock* create(VM* vm, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
     {
+        WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))
+            WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), ownerExecutable, globalObject);
+        instance->finishCreation(*vm);
+        return instance;
     }
 
-#if ENABLE(JIT)
-protected:
-    virtual CodeBlock* replacement() override;
-    virtual DFG::CapabilityLevel capabilityLevelInternal() override;
-#endif
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        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*);
 };
 #endif
 
@@ -1210,10 +1347,9 @@ inline Register& ExecState::uncheckedR(VirtualRegister reg)
     return uncheckedR(reg.offset());
 }
 
-inline void CodeBlock::clearMarks()
+inline void CodeBlock::clearVisitWeaklyHasBeenCalled()
 {
-    m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
-    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
+    m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
 }
 
 inline void CodeBlockSet::mark(void* candidateCodeBlock)
@@ -1238,12 +1374,11 @@ inline void CodeBlockSet::mark(CodeBlock* codeBlock)
 {
     if (!codeBlock)
         return;
-    
-    // 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();
+
+    // Try to recover gracefully if we forget to execute a barrier for a
+    // CodeBlock that does value profiling. This is probably overkill, but we
+    // have always done it.
+    Heap::heap(codeBlock)->writeBarrier(codeBlock);
 
     m_currentlyExecuting.add(codeBlock);
 }
@@ -1252,13 +1387,13 @@ template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Funct
 {
     switch (type()) {
     case ProgramExecutableType: {
-        if (CodeBlock* codeBlock = jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get())
+        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get()))
             codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
         break;
     }
 
     case EvalExecutableType: {
-        if (CodeBlock* codeBlock = jsCast<EvalExecutable*>(this)->m_evalCodeBlock.get())
+        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<EvalExecutable*>(this)->m_evalCodeBlock.get()))
             codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
         break;
     }
@@ -1266,15 +1401,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 = executable->m_codeBlockForCall.get())
+        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForCall.get()))
             codeBlock->forEachRelatedCodeBlock(f);
-        if (CodeBlock* codeBlock = executable->m_codeBlockForConstruct.get())
+        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForConstruct.get()))
             codeBlock->forEachRelatedCodeBlock(f);
         break;
     }
 
     case ModuleProgramExecutableType: {
-        if (CodeBlock* codeBlock = jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get())
+        if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get()))
             codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));
         break;
     }
index 5646a53..d516950 100644 (file)
@@ -75,7 +75,7 @@ bool CodeOrigin::isApproximatelyEqualTo(const CodeOrigin& other) const
         if (!a.inlineCallFrame)
             return true;
         
-        if (a.inlineCallFrame->executable.get() != b.inlineCallFrame->executable.get())
+        if (a.inlineCallFrame->baselineCodeBlock.get() != b.inlineCallFrame->baselineCodeBlock.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->executable.get());
+        result += WTF::PtrHash<JSCell*>::hash(codeOrigin.inlineCallFrame->baselineCodeBlock.get());
         
         codeOrigin = codeOrigin.inlineCallFrame->directCaller;
     }
@@ -115,11 +115,11 @@ Vector<CodeOrigin> CodeOrigin::inlineStack() const
     return result;
 }
 
-ScriptExecutable* CodeOrigin::codeOriginOwner() const
+CodeBlock* CodeOrigin::codeOriginOwner() const
 {
     if (!inlineCallFrame)
         return 0;
-    return inlineCallFrame->executable.get();
+    return inlineCallFrame->baselineCodeBlock.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->executable.get()), "> ");
+            out.print(frame->briefFunctionInformation(), ":<", RawPointer(frame->baselineCodeBlock.get()), "> ");
             if (frame->isClosureCall)
                 out.print("(closure) ");
         }
index a522ba9..c944e81 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.
-    ScriptExecutable* codeOriginOwner() const;
+    CodeBlock* codeOriginOwner() const;
     
     int stackOffset() const;
     
index 761e95b..eb9d419 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
 DeferredCompilationCallback::DeferredCompilationCallback() { }
 DeferredCompilationCallback::~DeferredCompilationCallback() { }
 
-void DeferredCompilationCallback::compilationDidComplete(CodeBlock* codeBlock, CompilationResult result)
+void DeferredCompilationCallback::compilationDidComplete(CodeBlock* codeBlock, CodeBlock*, CompilationResult result)
 {
     dumpCompiledSourcesIfNeeded();
 
index 37568d2..adecb82 100644 (file)
@@ -42,8 +42,8 @@ protected:
 public:
     virtual ~DeferredCompilationCallback();
 
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) = 0;
-    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock) = 0;
+    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
 
     Vector<DeferredSourceDump>& ensureDeferredSourceDump();
 
index 7a89898..62521fc 100644 (file)
@@ -51,7 +51,7 @@ namespace JSC {
             return 0;
         }
         
-        EvalExecutable* getSlow(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, ThisTDZMode thisTDZMode, const String& evalSource, JSScope* scope)
+        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, const String& evalSource, JSScope* scope)
         {
             VariableEnvironment variablesUnderTDZ;
             JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ);
index 7a3d8af..447bc7e 100644 (file)
@@ -47,24 +47,17 @@ JSFunction* InlineCallFrame::calleeForCallFrame(ExecState* exec) const
 
 CodeBlockHash InlineCallFrame::hash() const
 {
-    return jsCast<FunctionExecutable*>(executable.get())->codeBlockFor(
-        specializationKind())->hash();
+    return baselineCodeBlock->hash();
 }
 
 CString InlineCallFrame::hashAsStringIfPossible() const
 {
-    return jsCast<FunctionExecutable*>(executable.get())->codeBlockFor(
-        specializationKind())->hashAsStringIfPossible();
+    return baselineCodeBlock->hashAsStringIfPossible();
 }
 
 CString InlineCallFrame::inferredName() const
 {
-    return jsCast<FunctionExecutable*>(executable.get())->inferredName().utf8();
-}
-
-CodeBlock* InlineCallFrame::baselineCodeBlock() const
-{
-    return jsCast<FunctionExecutable*>(executable.get())->baselineCodeBlockFor(specializationKind());
+    return jsCast<FunctionExecutable*>(baselineCodeBlock->ownerExecutable())->inferredName().utf8();
 }
 
 void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const
@@ -74,8 +67,8 @@ void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const
 
 void InlineCallFrame::dumpInContext(PrintStream& out, DumpContext* context) const
 {
-    out.print(briefFunctionInformation(), ":<", RawPointer(executable.get()));
-    if (executable->isStrictMode())
+    out.print(briefFunctionInformation(), ":<", RawPointer(baselineCodeBlock.get()));
+    if (isStrictMode())
         out.print(" (StrictMode)");
     out.print(", bc#", directCaller.bytecodeIndex, ", ", static_cast<Kind>(kind));
     if (isClosureCall)
index 62f25fc..9eb7fb3 100644 (file)
@@ -29,7 +29,6 @@
 #include "CodeBlock.h"
 #include "CodeBlockHash.h"
 #include "CodeOrigin.h"
-#include "Executable.h"
 #include "ValueRecovery.h"
 #include "WriteBarrier.h"
 #include <wtf/BitVector.h>
@@ -42,7 +41,6 @@ namespace JSC {
 
 struct InlineCallFrame;
 class ExecState;
-class ScriptExecutable;
 class JSFunction;
 
 struct InlineCallFrame {
@@ -174,7 +172,7 @@ struct InlineCallFrame {
     }
     
     Vector<ValueRecovery> arguments; // Includes 'this'.
-    WriteBarrier<ScriptExecutable> executable;
+    WriteBarrier<CodeBlock> baselineCodeBlock;
     ValueRecovery calleeRecovery;
     CodeOrigin directCaller;
 
@@ -209,8 +207,6 @@ struct InlineCallFrame {
     CodeBlockHash hash() const;
     CString hashAsStringIfPossible() const;
     
-    CodeBlock* baselineCodeBlock() const;
-    
     void setStackOffset(signed offset)
     {
         stackOffset = offset;
@@ -220,6 +216,8 @@ 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;
@@ -231,9 +229,7 @@ struct InlineCallFrame {
 inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
 {
     RELEASE_ASSERT(inlineCallFrame);
-    ScriptExecutable* executable = inlineCallFrame->executable.get();
-    RELEASE_ASSERT(executable->structure()->classInfo() == FunctionExecutable::info());
-    return static_cast<FunctionExecutable*>(executable)->baselineCodeBlockFor(inlineCallFrame->specializationKind());
+    return inlineCallFrame->baselineCodeBlock.get();
 }
 
 inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
index 61f5176..9b0560f 100644 (file)
@@ -411,7 +411,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->ownerExecutable(), structure));
+        state.weakReferences.append(WriteBarrier<JSCell>(vm, codeBlock, structure));
         
         jit.move(CCallHelpers::TrustedImmPtr(condition.object()), scratchGPR);
         state.failAndRepatch.append(
@@ -1170,7 +1170,7 @@ MacroAssemblerCodePtr PolymorphicAccess::regenerate(
     for (auto& entry : cases)
         doesCalls |= entry->doesCalls();
     
-    m_stubRoutine = createJITStubRoutine(code, vm, codeBlock->ownerExecutable(), doesCalls);
+    m_stubRoutine = createJITStubRoutine(code, vm, codeBlock, doesCalls);
     m_watchpoints = WTF::move(state.watchpoints);
     if (!state.weakReferences.isEmpty())
         m_weakReferences = std::make_unique<Vector<WriteBarrier<JSCell>>>(WTF::move(state.weakReferences));
index c8f3f44..cfe6d34 100644 (file)
@@ -62,7 +62,7 @@ MacroAssemblerCodePtr StructureStubInfo::addAccessCase(
     Vector<std::unique_ptr<AccessCase>> accessCases;
     
     std::unique_ptr<AccessCase> previousCase =
-        AccessCase::fromStructureStubInfo(vm, codeBlock->ownerExecutable(), *this);
+        AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
     if (previousCase)
         accessCases.append(WTF::move(previousCase));
 
index d4fc1a8..635751e 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->ownerExecutable());
+        byteCodeParser->m_graph.freeze(codeBlock->baselineVersion());
         // The owner is the machine code block, and we already have a barrier on that when the
         // plan finishes.
-        m_inlineCallFrame->executable.setWithoutWriteBarrier(codeBlock->ownerScriptExecutable());
+        m_inlineCallFrame->baselineCodeBlock.setWithoutWriteBarrier(codeBlock->baselineVersion());
         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.get();
+    m_dfgCodeBlock = m_graph.m_plan.profiledDFGCodeBlock;
     if (isFTL(m_graph.m_plan.mode) && m_dfgCodeBlock
         && Options::enablePolyvariantDevirtualization()) {
         if (Options::enablePolyvariantCallInlining())
index 47881e2..741bc16 100644 (file)
@@ -89,8 +89,8 @@ void CommonData::validateReferences(const TrackedReferences& trackedReferences)
                     trackedReferences.check(recovery.constant());
             }
             
-            if (ScriptExecutable* executable = inlineCallFrame->executable.get())
-                trackedReferences.check(executable);
+            if (CodeBlock* baselineCodeBlock = inlineCallFrame->baselineCodeBlock.get())
+                trackedReferences.check(baselineCodeBlock);
             
             if (inlineCallFrame->calleeRecovery.isConstant())
                 trackedReferences.check(inlineCallFrame->calleeRecovery.constant());
index 91134cc..e273ae8 100644 (file)
@@ -34,7 +34,7 @@
 
 namespace JSC { namespace DFG {
 
-DesiredTransition::DesiredTransition(CodeBlock* codeBlock, ScriptExecutable* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
+DesiredTransition::DesiredTransition(CodeBlock* codeBlock, CodeBlock* 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->ownerExecutable(),
+            vm, m_codeBlock,
             m_codeOriginOwner,
             m_oldStructure, m_newStructure));
 }
@@ -66,7 +66,7 @@ DesiredTransitions::~DesiredTransitions()
 {
 }
 
-void DesiredTransitions::addLazily(CodeBlock* codeBlock, ScriptExecutable* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
+void DesiredTransitions::addLazily(CodeBlock* codeBlock, CodeBlock* codeOriginOwner, Structure* oldStructure, Structure* newStructure)
 {
     m_transitions.append(DesiredTransition(codeBlock, codeOriginOwner, oldStructure, newStructure));
 }
index addaf3e..9ea6ada 100644 (file)
@@ -44,7 +44,7 @@ class CommonData;
 
 class DesiredTransition {
 public:
-    DesiredTransition(CodeBlock*, ScriptExecutable*, Structure*, Structure*);
+    DesiredTransition(CodeBlock*, CodeBlock* codeOriginOwner, Structure*, Structure*);
 
     void reallyAdd(VM&, CommonData*);
     
@@ -52,7 +52,7 @@ public:
 
 private:
     CodeBlock* m_codeBlock;
-    ScriptExecutable* m_codeOriginOwner;
+    CodeBlock* m_codeOriginOwner;
     Structure* m_oldStructure;
     Structure* m_newStructure;
 };
@@ -62,7 +62,7 @@ public:
     DesiredTransitions();
     ~DesiredTransitions();
 
-    void addLazily(CodeBlock*, ScriptExecutable*, Structure*, Structure*);
+    void addLazily(CodeBlock*, CodeBlock* codeOriginOwner, Structure*, Structure*);
     void reallyAdd(VM&, CommonData*);
     void visitChildren(SlotVisitor&);
 
index 0df9606..1af13ef 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->ownerExecutable(), structure));
+                WriteBarrier<Structure>(vm, m_codeBlock, structure));
         } else {
             common->weakReferences.append(
-                WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target));
+                WriteBarrier<JSCell>(vm, m_codeBlock, target));
         }
     }
 }
index fe407aa..aca733a 100644 (file)
@@ -121,7 +121,7 @@ CompilationResult compile(
         vm, codeBlock, profiledDFGCodeBlock, mode, osrEntryBytecodeIndex, mustHandleValues,
         callback);
     if (result != CompilationDeferred)
-        callback->compilationDidComplete(codeBlock, result);
+        callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
     return result;
 }
 
index 72bf31f..f2807e4 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.get())
+    , m_codeBlock(m_plan.codeBlock)
     , m_profiledBlock(m_codeBlock->alternative())
     , m_allocator(longLivedState.m_allocator)
     , m_nextMachineLocal(0)
index 8343341..054ff07 100644 (file)
@@ -348,7 +348,7 @@ public:
         if (!inlineCallFrame)
             return m_codeBlock->ownerScriptExecutable();
         
-        return inlineCallFrame->executable.get();
+        return inlineCallFrame->baselineCodeBlock->ownerScriptExecutable();
     }
     
     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
@@ -372,7 +372,7 @@ public:
     {
         if (!codeOrigin.inlineCallFrame)
             return m_codeBlock->isStrictMode();
-        return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
+        return codeOrigin.inlineCallFrame->isStrictMode();
     }
     
     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
index 266a7ce..ff6c866 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "CodeBlock.h"
 #include "CompilationResult.h"
 #include "DFGCommonData.h"
 #include "DFGMinifiedGraph.h"
@@ -114,6 +115,12 @@ public:
     void validateReferences(const TrackedReferences&) override;
     
     void shrinkToFit();
+
+#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().
@@ -128,7 +135,7 @@ public:
 #if ENABLE(FTL_JIT)
     uint8_t nestedTriggerIsSet { 0 };
     UpperTierExecutionCounter tierUpCounter;
-    RefPtr<CodeBlock> osrEntryBlock;
+    WriteBarrier<CodeBlock> m_osrEntryBlock;
     unsigned osrEntryRetry;
     bool abandonOSREntry;
 #endif // ENABLE(FTL_JIT)
index 836c0e0..2d131c3 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.get(), JITCode::DFGJIT)).data())),
+        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, 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.get(), JITCode::DFGJIT)).data())),
+        FINALIZE_DFG_CODE(*m_linkBuffer, ("DFG JIT code for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, 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.get());
+    m_jitCode->optimizeAfterWarmUp(m_plan.codeBlock);
 #endif // ENABLE(FTL_JIT)
     
     if (m_plan.compilation)
index 12648bc..9a60560 100644 (file)
@@ -69,7 +69,7 @@ void handleExitCounts(CCallHelpers& jit, const OSRExitBase& exit)
             jit.branchTest8(
                 AssemblyHelpers::NonZero,
                 AssemblyHelpers::AbsoluteAddress(
-                    inlineCallFrame->executable->addressOfDidTryToEnterInLoop())));
+                    inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->addressOfDidTryToEnterInLoop())));
     }
     
     jit.move(
@@ -268,13 +268,14 @@ static void osrWriteBarrier(CCallHelpers& jit, GPRReg owner, GPRReg scratch)
 
 void adjustAndJumpToTarget(CCallHelpers& jit, const OSRExitBase& exit, bool isExitingToOpCatch)
 {
-    jit.move(AssemblyHelpers::TrustedImmPtr(jit.codeBlock()->ownerExecutable()), GPRInfo::argumentGPR1);
+    CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin);
+    jit.move(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), GPRInfo::argumentGPR1);
     osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
     InlineCallFrameSet* inlineCallFrames = jit.codeBlock()->jitCode()->dfgCommon()->inlineCallFrames.get();
     if (inlineCallFrames) {
         for (InlineCallFrame* inlineCallFrame : *inlineCallFrames) {
-            ScriptExecutable* ownerExecutable = inlineCallFrame->executable.get();
-            jit.move(AssemblyHelpers::TrustedImmPtr(ownerExecutable), GPRInfo::argumentGPR1);
+            CodeBlock* baselineCodeBlock = inlineCallFrame->baselineCodeBlock.get();
+            jit.move(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), GPRInfo::argumentGPR1);
             osrWriteBarrier(jit, GPRInfo::argumentGPR1, GPRInfo::nonArgGPR0);
         }
     }
@@ -282,7 +283,6 @@ 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 48e9f05..ba2a0da 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();
+        CodeBlock* codeBlock = codeOrigin.inlineCallFrame->baselineCodeBlock.get();
         if (codeBlock->jitType() == JSC::JITCode::BaselineJIT)
             continue;
 
index 7e0f07d..d6c4740 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->executable->didTryToEnterInLoop()) {
+        if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->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().get(), codeBlock, FTLMode, UINT_MAX,
-        Operands<JSValue>(), ToFTLDeferredCompilationCallback::create(codeBlock));
+        *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
+        Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
 }
 
 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.get()) {
+    if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
         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->osrEntryBlock = nullptr;
+        jitCode->clearOSREntryBlock();
         jitCode->osrEntryRetry = 0;
         return 0;
     }
@@ -1494,21 +1494,19 @@ char* JIT_OPERATION triggerOSREntryNow(
     Operands<JSValue> mustHandleValues;
     jitCode->reconstruct(
         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
-    RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
+    CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
     CompilationResult forEntryResult = compile(
-        *vm, replacementCodeBlock.get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,
-        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock));
+        *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
+        mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create());
     
-    if (forEntryResult != CompilationSuccessful) {
-        ASSERT(forEntryResult == CompilationDeferred || replacementCodeBlock->hasOneRef());
+    if (forEntryResult != CompilationSuccessful)
         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.get(), bytecodeIndex, streamIndex);
+        exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
     return static_cast<char*>(address);
 }
 #endif // ENABLE(FTL_JIT)
index a98cd45..53e106c 100644 (file)
@@ -131,7 +131,7 @@ Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode)
 
 } // anonymous namespace
 
-Plan::Plan(PassRefPtr<CodeBlock> passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
+Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
     CompilationMode mode, unsigned osrEntryBytecodeIndex,
     const Operands<JSValue>& mustHandleValues)
     : vm(*passedCodeBlock->vm())
@@ -140,10 +140,10 @@ Plan::Plan(PassRefPtr<CodeBlock> passedCodeBlock, CodeBlock* profiledDFGCodeBloc
     , mode(mode)
     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
     , mustHandleValues(mustHandleValues)
-    , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), profilerCompilationKindForMode(mode))) : 0)
+    , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0)
     , inlineCallFrames(adoptRef(new InlineCallFrameSet()))
-    , identifiers(codeBlock.get())
-    , weakReferences(codeBlock.get())
+    , identifiers(codeBlock)
+    , weakReferences(codeBlock)
     , willTryToTierUp(false)
     , stage(Preparing)
 {
@@ -535,7 +535,7 @@ bool Plan::isStillValid()
 
 void Plan::reallyAdd(CommonData* commonData)
 {
-    watchpoints.reallyAdd(codeBlock.get(), *commonData);
+    watchpoints.reallyAdd(codeBlock, *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.get());
+    callback->compilationDidBecomeReadyAsynchronously(codeBlock, profiledDFGCodeBlock);
     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->ownerExecutable());
+    vm.heap.writeBarrier(codeBlock);
     
     if (!isStillValid())
         return CompilationInvalidated;
@@ -596,7 +596,7 @@ CompilationResult Plan::finalizeWithoutNotifyingCallback()
 
 void Plan::finalizeAndNotifyCallback()
 {
-    callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
+    callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, finalizeWithoutNotifyingCallback());
 }
 
 CompilationKey Plan::key()
@@ -604,16 +604,15 @@ CompilationKey Plan::key()
     return CompilationKey(codeBlock->alternative(), mode);
 }
 
-void Plan::clearCodeBlockMarks()
+void Plan::rememberCodeBlocks()
 {
     // 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.
 
-    codeBlock->clearMarks();
-    codeBlock->alternative()->clearMarks();
+    Heap::heap(codeBlock)->writeBarrier(codeBlock);
     if (profiledDFGCodeBlock)
-        profiledDFGCodeBlock->clearMarks();
+        Heap::heap(profiledDFGCodeBlock)->writeBarrier(profiledDFGCodeBlock);
 }
 
 void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
@@ -624,15 +623,13 @@ void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
     for (unsigned i = mustHandleValues.size(); i--;)
         visitor.appendUnbarrieredValue(&mustHandleValues[i]);
 
-    codeBlock->visitStrongly(visitor);
-    codeBlock->alternative()->visitStrongly(visitor);
-    if (profiledDFGCodeBlock)
-        profiledDFGCodeBlock->visitStrongly(visitor);
+    visitor.appendUnbarrieredReadOnlyPointer(codeBlock);
+    visitor.appendUnbarrieredReadOnlyPointer(profiledDFGCodeBlock);
 
     if (inlineCallFrames) {
         for (auto* inlineCallFrame : *inlineCallFrames) {
-            ASSERT(inlineCallFrame->baselineCodeBlock());
-            inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
+            ASSERT(inlineCallFrame->baselineCodeBlock.get());
+            visitor.appendUnbarrieredReadOnlyPointer(inlineCallFrame->baselineCodeBlock.get());
         }
     }
 
index eec5c9e..8cd3479 100644 (file)
@@ -55,7 +55,7 @@ class ThreadData;
 
 struct Plan : public ThreadSafeRefCounted<Plan> {
     Plan(
-        PassRefPtr<CodeBlock> codeBlockToCompile, CodeBlock* profiledDFGCodeBlock,
+        CodeBlock* codeBlockToCompile, CodeBlock* profiledDFGCodeBlock,
         CompilationMode, unsigned osrEntryBytecodeIndex,
         const Operands<JSValue>& mustHandleValues);
     ~Plan();
@@ -71,14 +71,17 @@ struct Plan : public ThreadSafeRefCounted<Plan> {
     
     CompilationKey key();
     
-    void clearCodeBlockMarks();
+    void rememberCodeBlocks();
     void checkLivenessAndVisitChildren(SlotVisitor&);
     bool isKnownToBeLiveDuringGC();
     void cancel();
     
     VM& vm;
-    RefPtr<CodeBlock> codeBlock;
-    RefPtr<CodeBlock> profiledDFGCodeBlock;
+
+    // These can be raw pointers because we visit them during every GC in checkLivenessAndVisitChildren.
+    CodeBlock* codeBlock;
+    CodeBlock* profiledDFGCodeBlock;
+
     CompilationMode mode;
     const unsigned osrEntryBytecodeIndex;
     Operands<JSValue> mustHandleValues;
index faebdd0..a186641 100644 (file)
 
 namespace JSC { namespace DFG {
 
-ToFTLDeferredCompilationCallback::ToFTLDeferredCompilationCallback(
-    PassRefPtr<CodeBlock> dfgCodeBlock)
-    : m_dfgCodeBlock(dfgCodeBlock)
+ToFTLDeferredCompilationCallback::ToFTLDeferredCompilationCallback()
 {
 }
 
 ToFTLDeferredCompilationCallback::~ToFTLDeferredCompilationCallback() { }
 
-Ref<ToFTLDeferredCompilationCallback> ToFTLDeferredCompilationCallback::create(PassRefPtr<CodeBlock> dfgCodeBlock)
+Ref<ToFTLDeferredCompilationCallback> ToFTLDeferredCompilationCallback::create()
 {
-    return adoptRef(*new ToFTLDeferredCompilationCallback(dfgCodeBlock));
+    return adoptRef(*new ToFTLDeferredCompilationCallback());
 }
 
 void ToFTLDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
             ") did become ready.\n");
     }
     
-    m_dfgCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
-        m_dfgCodeBlock.get());
+    profiledDFGCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
+        profiledDFGCodeBlock);
 }
 
 void ToFTLDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
             ") result: ", result, "\n");
     }
     
-    if (m_dfgCodeBlock->replacement() != m_dfgCodeBlock) {
+    if (profiledDFGCodeBlock->replacement() != profiledDFGCodeBlock) {
         if (Options::verboseOSR()) {
             dataLog(
                 "Dropping FTL code block ", *codeBlock, " on the floor because the "
-                "DFG code block ", *m_dfgCodeBlock, " was jettisoned.\n");
+                "DFG code block ", *profiledDFGCodeBlock, " was jettisoned.\n");
         }
         return;
     }
@@ -82,10 +80,10 @@ void ToFTLDeferredCompilationCallback::compilationDidComplete(
     if (result == CompilationSuccessful)
         codeBlock->ownerScriptExecutable()->installCode(codeBlock);
     
-    m_dfgCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
-        m_dfgCodeBlock.get(), result);
+    profiledDFGCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult(
+        profiledDFGCodeBlock, result);
 
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
 }
 
 } } // JSC::DFG
index 3e0ea02..2a7931d 100644 (file)
@@ -40,18 +40,15 @@ namespace DFG {
 
 class ToFTLDeferredCompilationCallback : public DeferredCompilationCallback {
 protected:
-    ToFTLDeferredCompilationCallback(PassRefPtr<CodeBlock> dfgCodeBlock);
+    ToFTLDeferredCompilationCallback();
 
 public:
     virtual ~ToFTLDeferredCompilationCallback();
 
-    static Ref<ToFTLDeferredCompilationCallback> create(PassRefPtr<CodeBlock> dfgCodeBlock);
+    static Ref<ToFTLDeferredCompilationCallback> create();
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*);
-    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
-
-private:
-    RefPtr<CodeBlock> m_dfgCodeBlock;
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock);
+    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
 };
 
 } } // namespace JSC::DFG
index 70cc825..c9e5c79 100644 (file)
@@ -35,9 +35,7 @@
 
 namespace JSC { namespace DFG {
 
-ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback(
-    PassRefPtr<CodeBlock> dfgCodeBlock)
-    : m_dfgCodeBlock(dfgCodeBlock)
+ToFTLForOSREntryDeferredCompilationCallback::ToFTLForOSREntryDeferredCompilationCallback()
 {
 }
 
@@ -45,39 +43,38 @@ ToFTLForOSREntryDeferredCompilationCallback::~ToFTLForOSREntryDeferredCompilatio
 {
 }
 
-Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create(
-    PassRefPtr<CodeBlock> dfgCodeBlock)
+Ref<ToFTLForOSREntryDeferredCompilationCallback>ToFTLForOSREntryDeferredCompilationCallback::create()
 {
-    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback(dfgCodeBlock));
+    return adoptRef(*new ToFTLForOSREntryDeferredCompilationCallback());
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
             ") did become ready.\n");
     }
     
-    m_dfgCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
-        m_dfgCodeBlock.get());
+    profiledDFGCodeBlock->jitCode()->dfg()->forceOptimizationSlowPathConcurrently(
+        profiledDFGCodeBlock);
 }
 
 void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
 {
     if (Options::verboseOSR()) {
         dataLog(
-            "Optimizing compilation of ", *codeBlock, " (for ", *m_dfgCodeBlock,
+            "Optimizing compilation of ", *codeBlock, " (for ", *profiledDFGCodeBlock,
             ") result: ", result, "\n");
     }
     
-    JITCode* jitCode = m_dfgCodeBlock->jitCode()->dfg();
+    JITCode* jitCode = profiledDFGCodeBlock->jitCode()->dfg();
         
     switch (result) {
     case CompilationSuccessful:
-        jitCode->osrEntryBlock = codeBlock;
+        jitCode->setOSREntryBlock(*codeBlock->vm(), profiledDFGCodeBlock, codeBlock);
         break;
     case CompilationFailed:
         jitCode->osrEntryRetry = 0;
@@ -90,7 +87,7 @@ void ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete(
         break;
     }
     
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
 }
 
 } } // JSC::DFG
index c9dcf6d..580f7d2 100644 (file)
@@ -40,18 +40,15 @@ namespace DFG {
 
 class ToFTLForOSREntryDeferredCompilationCallback : public DeferredCompilationCallback {
 protected:
-    ToFTLForOSREntryDeferredCompilationCallback(PassRefPtr<CodeBlock> dfgCodeBlock);
+    ToFTLForOSREntryDeferredCompilationCallback();
 
 public:
     virtual ~ToFTLForOSREntryDeferredCompilationCallback();
 
-    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create(PassRefPtr<CodeBlock> dfgCodeBlock);
+    static Ref<ToFTLForOSREntryDeferredCompilationCallback> create();
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*);
-    virtual void compilationDidComplete(CodeBlock*, CompilationResult);
-
-private:
-    RefPtr<CodeBlock> m_dfgCodeBlock;
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock);
+    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult);
 };
 
 } } // namespace JSC::DFG
index b41d803..ac823c3 100644 (file)
@@ -207,14 +207,14 @@ void Worklist::completeAllPlansForVM(VM& vm)
     completeAllReadyPlansForVM(vm);
 }
 
-void Worklist::clearCodeBlockMarks(VM& vm)
+void Worklist::rememberCodeBlocks(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->clearCodeBlockMarks();
+        plan->rememberCodeBlocks();
     }
 }
 
@@ -467,11 +467,11 @@ void completeAllPlansForVM(VM& vm)
     }
 }
 
-void clearCodeBlockMarks(VM& vm)
+void rememberCodeBlocks(VM& vm)
 {
     for (unsigned i = DFG::numberOfWorklists(); i--;) {
         if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
-            worklist->clearCodeBlockMarks(vm);
+            worklist->rememberCodeBlocks(vm);
     }
 }
 
index 1740745..075f7cc 100644 (file)
@@ -57,7 +57,7 @@ public:
     // worklist->completeAllReadyPlansForVM(vm);
     void completeAllPlansForVM(VM&);
 
-    void clearCodeBlockMarks(VM&);
+    void rememberCodeBlocks(VM&);
 
     void waitUntilAllPlansForVMAreReady(VM&);
     State completeAllReadyPlansForVM(VM&, CompilationKey = CompilationKey());
@@ -141,7 +141,7 @@ inline Worklist* worklistForIndexOrNull(unsigned index)
 }
 
 void completeAllPlansForVM(VM&);
-void clearCodeBlockMarks(VM&);
+void rememberCodeBlocks(VM&);
 
 } } // namespace JSC::DFG
 
index 3da4848..0aba6a8 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.get(), JITCode::FTLJIT)).data())));
+                ("FTL exit thunks for %s", toCString(CodeBlockWithJITType(m_plan.codeBlock, 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.get(), JITCode::FTLJIT)).data()))
+                toCString(CodeBlockWithJITType(m_plan.codeBlock, 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.get(), JITCode::FTLJIT)).data()))
+                toCString(CodeBlockWithJITType(m_plan.codeBlock, 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.get(), JITCode::FTLJIT)).data(), function)));
+            ("FTL entrypoint thunk for %s with LLVM generated code at %p", toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data(), function)));
     
     m_plan.codeBlock->setJITCode(jitCode);
 
index 3eda521..cfeb81f 100644 (file)
@@ -41,17 +41,11 @@ CodeBlockSet::CodeBlockSet()
 
 CodeBlockSet::~CodeBlockSet()
 {
-    for (CodeBlock* codeBlock : m_oldCodeBlocks)
-        codeBlock->deref();
-
-    for (CodeBlock* codeBlock : m_newCodeBlocks)
-        codeBlock->deref();
 }
 
-void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
+void CodeBlockSet::add(CodeBlock* codeBlock)
 {
-    CodeBlock* block = codeBlock.leakRef();
-    bool isNewEntry = m_newCodeBlocks.add(block).isNewEntry;
+    bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry;
     ASSERT_UNUSED(isNewEntry, isNewEntry);
 }
 
@@ -64,52 +58,26 @@ void CodeBlockSet::promoteYoungCodeBlocks()
 void CodeBlockSet::clearMarksForFullCollection()
 {
     for (CodeBlock* codeBlock : m_oldCodeBlocks)
-        codeBlock->clearMarks();
+        codeBlock->clearVisitWeaklyHasBeenCalled();
 
     // 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::clearMarksForEdenCollection(const Vector<const JSCell*>& rememberedSet)
-{
-    // 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);
+    }
 
-    // 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);
+    for (CodeBlock* codeBlock : unmarked) {
+        codeBlock->classInfo()->methodTable.destroy(codeBlock);
+        set.remove(codeBlock);
     }
 
     // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
@@ -119,7 +87,6 @@ void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
 
 void CodeBlockSet::remove(CodeBlock* codeBlock)
 {
-    codeBlock->deref();
     if (m_oldCodeBlocks.contains(codeBlock)) {
         m_oldCodeBlocks.remove(codeBlock);
         return;
@@ -128,35 +95,13 @@ void CodeBlockSet::remove(CodeBlock* codeBlock)
     m_newCodeBlocks.remove(codeBlock);
 }
 
-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 (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
-        heap->addToRememberedSet(codeBlock->ownerExecutable());
-
-    // 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.
+    for (CodeBlock* codeBlock : m_currentlyExecuting)
+        heap->addToRememberedSet(codeBlock);
     m_currentlyExecuting.clear();
-    m_remembered.clear();
 }
 
 void CodeBlockSet::dump(PrintStream& out) const
@@ -171,8 +116,8 @@ void CodeBlockSet::dump(PrintStream& out) const
         out.print(comma, pointerDump(codeBlock));
     out.print("], currentlyExecuting = [");
     comma = CommaPrinter();
-    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
-        out.print(comma, pointerDump(codeBlock.get()));
+    for (CodeBlock* codeBlock : m_currentlyExecuting)
+        out.print(comma, pointerDump(codeBlock));
     out.print("]}");
 }
 
index 18ef5a4..1c92583 100644 (file)
@@ -53,11 +53,8 @@ public:
     ~CodeBlockSet();
     
     // Add a CodeBlock. This is only called by CodeBlock constructors.
-    void add(PassRefPtr<CodeBlock>);
+    void add(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();
 
@@ -72,10 +69,6 @@ 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 rememberCurrentlyExecutingCodeBlocks(Heap*);
@@ -104,13 +97,9 @@ 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<RefPtr<CodeBlock>> m_currentlyExecuting;
-    HashSet<RefPtr<CodeBlock>> m_remembered;
+    HashSet<CodeBlock*> m_currentlyExecuting;
 };
 
 } // namespace JSC
index a30a826..904d8fa 100644 (file)
@@ -519,17 +519,6 @@ 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);
@@ -537,10 +526,20 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
     gatherJSStackRoots(conservativeRoots);
     gatherScratchBufferRoots(conservativeRoots);
 
-    clearLivenessData();
+#if ENABLE(DFG_JIT)
+    DFG::rememberCodeBlocks(*m_vm);
+#endif
 
-    if (m_operationInProgress == FullCollection)
+    if (m_operationInProgress == FullCollection) {
         m_opaqueRoots.clear();
+        m_slotVisitor.clearMarkStack();
+    }
+
+    Vector<const JSCell*> rememberedSet(m_slotVisitor.markStack().size());
+    m_slotVisitor.markStack().fillVector(rememberedSet);
+
+    clearLivenessData();
+
 
     m_shouldHashCons = m_vm->haveEnoughNewStringsToHashCons();
 
@@ -581,6 +580,7 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, Mach
     {
         ParallelModeEnabler enabler(m_slotVisitor);
 
+        m_slotVisitor.donateAndDrain();
         visitExternalRememberedSet();
         visitSmallStrings();
         visitConservativeRoots(conservativeRoots);
@@ -696,6 +696,9 @@ void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
 void Heap::clearLivenessData()
 {
     GCPHASE(ClearLivenessData);
+    if (m_operationInProgress == FullCollection)
+        m_codeBlocks.clearMarksForFullCollection();
+
     m_objectSpace.clearNewlyAllocated();
     m_objectSpace.clearMarks();
 }
@@ -817,7 +820,6 @@ 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)
@@ -962,18 +964,12 @@ 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* 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);
+    for (ExecutableBase* executable : m_executables)
+        executable->clearCode();
 }
 
 void Heap::deleteAllUnlinkedCodeBlocks()
@@ -993,9 +989,9 @@ void Heap::clearUnmarkedExecutables()
         if (isMarked(current))
             continue;
 
-        // We do this because executable memory is limited on some platforms and because
-        // CodeBlock requires eager finalization.
-        ExecutableBase::clearCodeVirtual(current);
+        // Eagerly dereference the Executable's JITCode in order to run watchpoint
+        // destructors. Otherwise, watchpoints might fire for deleted CodeBlocks.
+        current->clearCode();
         std::swap(m_executables[i], m_executables.last());
         m_executables.removeLast();
     }
@@ -1149,7 +1145,6 @@ void Heap::willStartCollection(HeapOperation collectionType)
     GCPHASE(StartingCollection);
     if (shouldDoFullCollection(collectionType)) {
         m_operationInProgress = FullCollection;
-        m_slotVisitor.clearMarkStack();
         m_shouldDoFullCollection = false;
         if (Options::logGC())
             dataLog("FullCollection, ");
index 04be8c8..c241989 100644 (file)
@@ -173,7 +173,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->ownerScriptExecutable(), callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);
+        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);
         if (!eval)
             return jsUndefined();
     }
index 3730721..84383c8 100644 (file)
@@ -170,7 +170,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();
+        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock.get();
         m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;
 
         JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
index 8e3c270..bb675c0 100644 (file)
@@ -38,7 +38,7 @@ ExecutableBase* AssemblyHelpers::executableFor(const CodeOrigin& codeOrigin)
     if (!codeOrigin.inlineCallFrame)
         return m_codeBlock->ownerExecutable();
     
-    return codeOrigin.inlineCallFrame->executable.get();
+    return codeOrigin.inlineCallFrame->baselineCodeBlock->ownerExecutable();
 }
 
 Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock)
index fea3c43..f6fd606 100644 (file)
@@ -1074,7 +1074,7 @@ public:
     {
         if (!codeOrigin.inlineCallFrame)
             return codeBlock()->isStrictMode();
-        return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
+        return codeOrigin.inlineCallFrame->isStrictMode();
     }
     
     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
index 0adc63b..59cbb24 100644 (file)
@@ -115,7 +115,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)->ownerExecutable(), (makesCalls), (cell)))
+    (createJITStubRoutine(FINALIZE_CODE_FOR((codeBlock), (patchBuffer), dataLogFArguments), *(codeBlock)->vm(), (codeBlock), (makesCalls), (cell)))
 
 } // namespace JSC
 
index fef5bc9..382f7ab 100644 (file)
@@ -121,28 +121,6 @@ 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 e176829..840e262 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->ownerExecutable());
+    emitWriteBarrier(m_codeBlock);
 
     emitEnterOptimizationCheck();
 }
index 8e7ea65..442a792 100644 (file)
@@ -1273,15 +1273,13 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
             mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
         }
 
-        RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
+        CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
         CompilationResult result = DFG::compile(
-            vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
+            vm, replacementCodeBlock, nullptr, DFG::DFGMode, bytecodeIndex,
             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
         
-        if (result != CompilationSuccessful) {
-            ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
+        if (result != CompilationSuccessful)
             return encodeResult(0, 0);
-        }
     }
     
     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
index b42464f..876b040 100644 (file)
@@ -43,8 +43,9 @@ Ref<JITToDFGDeferredCompilationCallback> JITToDFGDeferredCompilationCallback::cr
 }
 
 void JITToDFGDeferredCompilationCallback::compilationDidBecomeReadyAsynchronously(
-    CodeBlock* codeBlock)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock)
 {
+    ASSERT_UNUSED(profiledDFGCodeBlock, !profiledDFGCodeBlock);
     ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
     
     if (Options::verboseOSR())
@@ -54,8 +55,9 @@ void JITToDFGDeferredCompilationCallback::compilationDidBecomeReadyAsynchronousl
 }
 
 void JITToDFGDeferredCompilationCallback::compilationDidComplete(
-    CodeBlock* codeBlock, CompilationResult result)
+    CodeBlock* codeBlock, CodeBlock* profiledDFGCodeBlock, CompilationResult result)
 {
+    ASSERT(!profiledDFGCodeBlock);
     ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
     
     if (Options::verboseOSR())
@@ -66,7 +68,7 @@ void JITToDFGDeferredCompilationCallback::compilationDidComplete(
     
     codeBlock->alternative()->setOptimizationThresholdBasedOnCompilationResult(result);
 
-    DeferredCompilationCallback::compilationDidComplete(codeBlock, result);
+    DeferredCompilationCallback::compilationDidComplete(codeBlock, profiledDFGCodeBlock, result);
 }
 
 } // JSC
index f64b979..af2532f 100644 (file)
@@ -44,8 +44,8 @@ public:
 
     static Ref<JITToDFGDeferredCompilationCallback> create();
     
-    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) override;
-    virtual void compilationDidComplete(CodeBlock*, CompilationResult) override;
+    virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*, CodeBlock* profiledDFGCodeBlock) override;
+    virtual void compilationDidComplete(CodeBlock*, CodeBlock* profiledDFGCodeBlock, CompilationResult) override;
 };
 
 } // namespace JSC
index b119f59..655d918 100644 (file)
@@ -227,15 +227,14 @@ 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, owner, AccessCase::ArrayLength);
+        newCase = AccessCase::getLength(vm, codeBlock, AccessCase::ArrayLength);
     else if (isJSString(baseValue) && propertyName == exec->propertyNames().length)
-        newCase = AccessCase::getLength(vm, owner, AccessCase::StringLength);
+        newCase = AccessCase::getLength(vm, codeBlock, AccessCase::StringLength);
     else {
         if (!slot.isCacheable() && !slot.isUnset())
             return GiveUpOnCache;
@@ -266,7 +265,7 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
             && !loadTargetFromProxy) {
             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
             repatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdOptimize, true);
-            stubInfo.initGetByIdSelf(vm, codeBlock->ownerExecutable(), structure, slot.cachedOffset());
+            stubInfo.initGetByIdSelf(vm, codeBlock, structure, slot.cachedOffset());
             return RetryCacheLater;
         }
 
@@ -279,10 +278,10 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
             
             if (slot.isUnset()) {
                 conditionSet = generateConditionsForPropertyMiss(
-                    vm, codeBlock->ownerExecutable(), exec, structure, propertyName.impl());
+                    vm, codeBlock, exec, structure, propertyName.impl());
             } else {
                 conditionSet = generateConditionsForPrototypePropertyHit(
-                    vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(),
+                    vm, codeBlock, exec, structure, slot.slotBase(),
                     propertyName.impl());
             }
             
@@ -303,7 +302,7 @@ static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, con
             type = AccessCase::CustomGetter;
 
         newCase = AccessCase::get(
-            vm, owner, type, offset, structure, conditionSet, loadTargetFromProxy,
+            vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy,
             slot.watchpointSet(), slot.isCacheableCustom() ? slot.customGetter() : nullptr,
             slot.isCacheableCustom() ? slot.slotBase() : nullptr);
     }
@@ -357,7 +356,6 @@ 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())
@@ -385,11 +383,11 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
                     codeBlock, stubInfo, structure, slot.cachedOffset(),
                     appropriateOptimizingPutByIdFunction(slot, putKind), false);
                 stubInfo.initPutByIdReplace(
-                    vm, codeBlock->ownerExecutable(), structure, slot.cachedOffset());
+                    vm, codeBlock, structure, slot.cachedOffset());
                 return RetryCacheLater;
             }
 
-            newCase = AccessCase::replace(vm, owner, structure, slot.cachedOffset());
+            newCase = AccessCase::replace(vm, codeBlock, structure, slot.cachedOffset());
         } else {
             ASSERT(slot.type() == PutPropertySlot::NewProperty);
 
@@ -411,12 +409,12 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (putKind == NotDirect) {
                 conditionSet =
                     generateConditionsForPropertySetterMiss(
-                        vm, owner, exec, newStructure, ident.impl());
+                        vm, codeBlock, exec, newStructure, ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
             }
 
-            newCase = AccessCase::transition(vm, owner, structure, newStructure, offset, conditionSet);
+            newCase = AccessCase::transition(vm, codeBlock, structure, newStructure, offset, conditionSet);
         }
     } else if (slot.isCacheableCustom() || slot.isCacheableSetter()) {
         if (slot.isCacheableCustom()) {
@@ -425,13 +423,13 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (slot.base() != baseValue) {
                 conditionSet =
                     generateConditionsForPrototypePropertyHitCustom(
-                        vm, owner, exec, structure, slot.base(), ident.impl());
+                        vm, codeBlock, exec, structure, slot.base(), ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
             }
 
             newCase = AccessCase::setter(
-                vm, owner, AccessCase::CustomSetter, structure, invalidOffset, conditionSet,
+                vm, codeBlock, AccessCase::CustomSetter, structure, invalidOffset, conditionSet,
                 slot.customSetter(), slot.base());
         } else {
             ObjectPropertyConditionSet conditionSet;
@@ -440,7 +438,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
             if (slot.base() != baseValue) {
                 conditionSet =
                     generateConditionsForPrototypePropertyHit(
-                        vm, owner, exec, structure, slot.base(), ident.impl());
+                        vm, codeBlock, exec, structure, slot.base(), ident.impl());
                 if (!conditionSet.isValid())
                     return GiveUpOnCache;
                 offset = conditionSet.slotBaseCondition().offset();
@@ -448,7 +446,7 @@ static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Str
                 offset = slot.cachedOffset();
 
             newCase = AccessCase::setter(
-                vm, owner, AccessCase::Setter, structure, offset, conditionSet);
+                vm, codeBlock, AccessCase::Setter, structure, offset, conditionSet);
         }
     }
 
@@ -491,7 +489,6 @@ static InlineCacheAction tryRepatchIn(
     }
     
     CodeBlock* codeBlock = exec->codeBlock();
-    ScriptExecutable* owner = codeBlock->ownerScriptExecutable();
     VM& vm = exec->vm();
     Structure* structure = base->structure(vm);
     
@@ -499,17 +496,17 @@ static InlineCacheAction tryRepatchIn(
     if (wasFound) {
         if (slot.slotBase() != base) {
             conditionSet = generateConditionsForPrototypePropertyHit(
-                vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(), ident.impl());
+                vm, codeBlock, exec, structure, slot.slotBase(), ident.impl());
         }
     } else {
         conditionSet = generateConditionsForPropertyMiss(
-            vm, codeBlock->ownerExecutable(), exec, structure, ident.impl());
+            vm, codeBlock, exec, structure, ident.impl());
     }
     if (!conditionSet.isValid())
         return GiveUpOnCache;
 
     std::unique_ptr<AccessCase> newCase = AccessCase::in(
-        vm, owner, wasFound ? AccessCase::InHit : AccessCase::InMiss, structure, conditionSet);
+        vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, structure, conditionSet);
 
     MacroAssemblerCodePtr codePtr = stubInfo.addAccessCase(vm, codeBlock, ident, WTF::move(newCase));
     if (!codePtr)
@@ -558,8 +555,8 @@ void linkFor(
     VM* vm = callerCodeBlock->vm();
     
     ASSERT(!callLinkInfo.isLinked());
-    callLinkInfo.setCallee(exec->callerFrame()->vm(), callLinkInfo.hotPathBegin(), callerCodeBlock->ownerExecutable(), callee);
-    callLinkInfo.setLastSeenCallee(exec->callerFrame()->vm(), callerCodeBlock->ownerExecutable(), callee);
+    callLinkInfo.setCallee(exec->callerFrame()->vm(), callLinkInfo.hotPathBegin(), callerCodeBlock, callee);
+    callLinkInfo.setLastSeenCallee(exec->callerFrame()->vm(), callerCodeBlock, 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));
@@ -876,7 +873,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->ownerExecutable(), exec->callerFrame(), callLinkInfo, callCases,
+        *vm, callerCodeBlock, exec->callerFrame(), callLinkInfo, callCases,
         WTF::move(fastCounts)));
     
     MacroAssembler::replaceWithJump(
index 477ced0..e187f61 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->ownerExecutable());
+            vm.heap.writeBarrier(codeBlock);
             
             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->ownerExecutable());
+            vm.heap.writeBarrier(codeBlock);
             
             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->ownerExecutable(), chain);
+                                vm, codeBlock, 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->ownerExecutable(), callee);
-        callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock->ownerExecutable(), callee);
+        callLinkInfo->callee.set(vm, callerCodeBlock, callee);
+        callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock, callee);
         callLinkInfo->machineCodeTarget = codePtr;
         if (codeBlock)
             codeBlock->linkIncomingCall(exec, callLinkInfo);
index 5c3242a..b8eecdd 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()),
+            database.ensureBytecodesFor(stack[i].inlineCallFrame->baselineCodeBlock.get()),
             stack[i].bytecodeIndex));
     }
 }
index e29f13a..1ab78de 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()->ownerExecutable(), constructor);
+        cacheWriteBarrier.set(exec->vm(), exec->codeBlock(), 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()->ownerExecutable(), myStructure);
+            pc[2].u.structure.set(vm, exec->codeBlock(), 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();
-    ExecutableBase* ownerExecutable = exec->codeBlock()->ownerExecutable();
-    Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable);
+    CodeBlock* codeBlock = exec->codeBlock();
+    Heap::heap(codeBlock)->writeBarrier(codeBlock);
     END();
 }
 
index 05762e5..444bc9f 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->ownerExecutable(), scope->structure());
+        pc[5].u.structure.set(exec->vm(), codeBlock, 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->ownerExecutable(), structure);
+                pc[5].u.structure.set(exec->vm(), codeBlock, structure);
                 pc[6].u.operand = slot.cachedOffset();
             }
             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
index 9631c98..030bcc5 100644 (file)
@@ -60,6 +60,45 @@ 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)
@@ -123,7 +162,7 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 {
     ASSERT(vm.heap.isDeferred());
     
-    RefPtr<CodeBlock> oldCodeBlock;
+    CodeBlock* oldCodeBlock = nullptr;
     
     switch (codeType) {
     case GlobalCode: {
@@ -132,8 +171,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         ASSERT(kind == CodeForCall);
         
-        oldCodeBlock = executable->m_programCodeBlock;
-        executable->m_programCodeBlock = codeBlock;
+        oldCodeBlock = executable->m_programCodeBlock.get();
+        executable->m_programCodeBlock.setMayBeNull(vm, this, codeBlock);
         break;
     }
 
@@ -143,8 +182,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
 
         ASSERT(kind == CodeForCall);
 
-        oldCodeBlock = executable->m_moduleProgramCodeBlock;
-        executable->m_moduleProgramCodeBlock = codeBlock;
+        oldCodeBlock = executable->m_moduleProgramCodeBlock.get();
+        executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, codeBlock);
         break;
     }
 
@@ -154,8 +193,8 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         ASSERT(kind == CodeForCall);
         
-        oldCodeBlock = executable->m_evalCodeBlock;
-        executable->m_evalCodeBlock = codeBlock;
+        oldCodeBlock = executable->m_evalCodeBlock.get();
+        executable->m_evalCodeBlock.setMayBeNull(vm, this, codeBlock);
         break;
     }
         
@@ -165,12 +204,12 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
         
         switch (kind) {
         case CodeForCall:
-            oldCodeBlock = executable->m_codeBlockForCall;
-            executable->m_codeBlockForCall = codeBlock;
+            oldCodeBlock = executable->m_codeBlockForCall.get();
+            executable->m_codeBlockForCall.setMayBeNull(vm, this, codeBlock);
             break;
         case CodeForConstruct:
-            oldCodeBlock = executable->m_codeBlockForConstruct;
-            executable->m_codeBlockForConstruct = codeBlock;
+            oldCodeBlock = executable->m_codeBlockForConstruct.get();
+            executable->m_codeBlockForConstruct.setMayBeNull(vm, this, codeBlock);
             break;
         }
         break;
@@ -210,7 +249,7 @@ void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType
     vm.heap.writeBarrier(this);
 }
 
-RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
+CodeBlock* ScriptExecutable::newCodeBlockFor(
     CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)
 {
     VM* vm = scope->vm();
@@ -224,9 +263,9 @@ RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_evalCodeBlock);
         RELEASE_ASSERT(!function);
-        return adoptRef(new EvalCodeBlock(
+        return EvalCodeBlock::create(vm,
             executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
-            executable->source().provider()));
+            executable->source().provider());
     }
     
     if (classInfo() == ProgramExecutable::info()) {
@@ -234,9 +273,9 @@ RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_programCodeBlock);
         RELEASE_ASSERT(!function);
-        return adoptRef(new ProgramCodeBlock(
+        return ProgramCodeBlock::create(vm,
             executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
-            executable->source().provider(), executable->source().startColumn()));
+            executable->source().provider(), executable->source().startColumn());
     }
 
     if (classInfo() == ModuleProgramExecutable::info()) {
@@ -244,9 +283,9 @@ RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
         RELEASE_ASSERT(kind == CodeForCall);
         RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);
         RELEASE_ASSERT(!function);
-        return adoptRef(new ModuleProgramCodeBlock(
+        return ModuleProgramCodeBlock::create(vm,
             executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope,
-            executable->source().provider(), executable->source().startColumn()));
+            executable->source().provider(), executable->source().startColumn());
     }
 
     RELEASE_ASSERT(classInfo() == FunctionExecutable::info());
@@ -276,11 +315,11 @@ RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
     unsigned sourceOffset = executable->source().startOffset();
     unsigned startColumn = executable->source().startColumn();
 
-    return adoptRef(new FunctionCodeBlock(
-        executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
+    return FunctionCodeBlock::create(vm,
+        executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn);
 }
 
-PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
+CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(
     CodeSpecializationKind kind)
 {
     if (classInfo() == EvalExecutable::info()) {
@@ -288,9 +327,9 @@ PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
         EvalExecutable* executable = jsCast<EvalExecutable*>(this);
         EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(
             executable->m_evalCodeBlock->baselineVersion());
-        RefPtr<EvalCodeBlock> result = adoptRef(new EvalCodeBlock(
-            CodeBlock::CopyParsedBlock, *baseline));
-        result->setAlternative(baseline);
+        EvalCodeBlock* result = EvalCodeBlock::create(vm(),
+            CodeBlock::CopyParsedBlock, *baseline);
+        result->setAlternative(*vm(), baseline);
         return result;
     }
     
@@ -299,9 +338,9 @@ PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
         ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);
         ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(
             executable->m_programCodeBlock->baselineVersion());
-        RefPtr<ProgramCodeBlock> result = adoptRef(new ProgramCodeBlock(
-            CodeBlock::CopyParsedBlock, *baseline));
-        result->setAlternative(baseline);
+        ProgramCodeBlock* result = ProgramCodeBlock::create(vm(),
+            CodeBlock::CopyParsedBlock, *baseline);
+        result->setAlternative(*vm(), baseline);
         return result;
     }
 
@@ -310,9 +349,9 @@ PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
         ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);
         ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>(
             executable->m_moduleProgramCodeBlock->baselineVersion());
-        RefPtr<ModuleProgramCodeBlock> result = adoptRef(new ModuleProgramCodeBlock(
-            CodeBlock::CopyParsedBlock, *baseline));
-        result->setAlternative(baseline);
+        ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(vm(),
+            CodeBlock::CopyParsedBlock, *baseline);
+        result->setAlternative(*vm(), baseline);
         return result;
     }
 
@@ -320,9 +359,9 @@ PassRefPtr<CodeBlock> ScriptExecutable::newReplacementCodeBlockFor(
     FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);
     FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(
         executable->codeBlockFor(kind)->baselineVersion());
-    RefPtr<FunctionCodeBlock> result = adoptRef(new FunctionCodeBlock(
-        CodeBlock::CopyParsedBlock, *baseline));
-    result->setAlternative(baseline);
+    FunctionCodeBlock* result = FunctionCodeBlock::create(vm(),
+        CodeBlock::CopyParsedBlock, *baseline);
+    result->setAlternative(*vm(), baseline);
     return result;
 }
 
@@ -350,7 +389,7 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
     DeferGC deferGC(vm.heap);
     
     JSObject* exception = 0;
-    RefPtr<CodeBlock> codeBlock = newCodeBlockFor(kind, function, scope, exception);
+    CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
     if (!codeBlock) {
         RELEASE_ASSERT(exception);
         return exception;
@@ -360,11 +399,11 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
         codeBlock->validate();
     
     if (Options::useLLInt())
-        setupLLInt(vm, codeBlock.get());
+        setupLLInt(vm, codeBlock);
     else
-        setupJIT(vm, codeBlock.get());
+        setupJIT(vm, codeBlock);
     
-    installCode(*codeBlock->vm(), codeBlock.get(), codeBlock->codeType(), codeBlock->specializationKind());
+    installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());
     return 0;
 }
 
@@ -502,16 +541,9 @@ void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ScriptExecutable::visitChildren(thisObject, visitor);
-    if (thisObject->m_evalCodeBlock)
-        thisObject->m_evalCodeBlock->visitAggregate(visitor);
     visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
-}
-
-void EvalExecutable::clearCode()
-{
-    m_evalCodeBlock = nullptr;
-    m_unlinkedEvalCodeBlock.clear();
-    Base::clearCode();
+    if (thisObject->m_evalCodeBlock)
+        thisObject->m_evalCodeBlock->visitWeakly(visitor);
 }
 
 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
@@ -618,14 +650,7 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ScriptExecutable::visitChildren(thisObject, visitor);
     visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
     if (thisObject->m_programCodeBlock)
-        thisObject->m_programCodeBlock->visitAggregate(visitor);
-}
-
-void ProgramExecutable::clearCode()
-{
-    m_programCodeBlock = nullptr;
-    m_unlinkedProgramCodeBlock.clear();
-    Base::clearCode();
+        thisObject->m_programCodeBlock->visitWeakly(visitor);
 }
 
 void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -636,15 +661,7 @@ void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_unlinkedModuleProgramCodeBlock);
     visitor.append(&thisObject->m_moduleEnvironmentSymbolTable);
     if (thisObject->m_moduleProgramCodeBlock)
-        thisObject->m_moduleProgramCodeBlock->visitAggregate(visitor);
-}
-
-void ModuleProgramExecutable::clearCode()
-{
-    m_moduleProgramCodeBlock = nullptr;
-    m_unlinkedModuleProgramCodeBlock.clear();
-    m_moduleEnvironmentSymbolTable.clear();
-    Base::clearCode();
+        thisObject->m_moduleProgramCodeBlock->visitWeakly(visitor);
 }
 
 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
@@ -667,20 +684,13 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ScriptExecutable::visitChildren(thisObject, visitor);
     if (thisObject->m_codeBlockForCall)
-        thisObject->m_codeBlockForCall->visitAggregate(visitor);
+        thisObject->m_codeBlockForCall->visitWeakly(visitor);
     if (thisObject->m_codeBlockForConstruct)
-        thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
+        thisObject->m_codeBlockForConstruct->visitWeakly(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)
@@ -716,16 +726,10 @@ void WebAssemblyExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     ExecutableBase::visitChildren(thisObject, visitor);
     if (thisObject->m_codeBlockForCall)
-        thisObject->m_codeBlockForCall->visitAggregate(visitor);
+        thisObject->m_codeBlockForCall->visitWeakly(visitor);
     visitor.append(&thisObject->m_module);
 }
 
-void WebAssemblyExecutable::clearCode()
-{
-    m_codeBlockForCall = nullptr;
-    Base::clearCode();
-}
-
 void WebAssemblyExecutable::prepareForExecution(ExecState* exec)
 {
     if (hasJITCodeForCall())
@@ -734,16 +738,16 @@ void WebAssemblyExecutable::prepareForExecution(ExecState* exec)
     VM& vm = exec->vm();
     DeferGC deferGC(vm.heap);
 
-    RefPtr<WebAssemblyCodeBlock> codeBlock = adoptRef(new WebAssemblyCodeBlock(
-        this, vm, exec->lexicalGlobalObject()));
+    WebAssemblyCodeBlock* codeBlock = WebAssemblyCodeBlock::create(vm,
+        this, exec->lexicalGlobalObject()));
 
-    WASMFunctionParser::compile(vm, codeBlock.get(), m_module.get(), m_source, m_functionIndex);
+    WASMFunctionParser::compile(vm, codeBlock, m_module.get(), m_source, m_functionIndex);
 
     m_jitCodeForCall = codeBlock->jitCode();
     m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
     m_numParametersForCall = codeBlock->numParameters();
 
-    m_codeBlockForCall = codeBlock;
+    m_codeBlockForCall.set(vm, this, codeBlock);
 
     Heap::heap(this)->writeBarrier(this);
 }
index 155f44b..9fc9be7 100644 (file)
@@ -139,8 +139,6 @@ protected:
     int m_numParametersForConstruct;
 
 public:
-    static void clearCodeVirtual(ExecutableBase*);
-
     PassRefPtr<JITCode> generatedJITCodeForCall()
     {
         ASSERT(m_jitCodeForCall);
@@ -306,6 +304,8 @@ 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);
-    RefPtr<CodeBlock> newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
-    PassRefPtr<CodeBlock> newReplacementCodeBlockFor(CodeSpecializationKind);
+    CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, JSObject*& exception);
+    CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
     
     JSObject* prepareForExecution(ExecState* exec, JSFunction* function, JSScope* scope, CodeSpecializationKind kind)
     {
@@ -389,6 +389,7 @@ public:
     template <typename Functor> void forEachCodeBlock(Functor&&);
 
 private:
+    friend class ExecutableBase;
     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
 
 protected:
@@ -447,20 +448,19 @@ 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&);
 
-    RefPtr<EvalCodeBlock> m_evalCodeBlock;
+    WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
     WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
 };
 
@@ -501,11 +501,10 @@ 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&);
@@ -513,7 +512,7 @@ private:
     static void visitChildren(JSCell*, SlotVisitor&);
 
     WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
-    RefPtr<ProgramCodeBlock> m_programCodeBlock;
+    WriteBarrier<ProgramCodeBlock> m_programCodeBlock;
 };
 
 class ModuleProgramExecutable final : public ScriptExecutable {
@@ -543,14 +542,13 @@ 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&);
@@ -559,7 +557,7 @@ private:
 
     WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock;
     WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable;
-    RefPtr<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
+    WriteBarrier<ModuleProgramCodeBlock> m_moduleProgramCodeBlock;
 };
 
 class FunctionExecutable final : public ScriptExecutable {
@@ -600,7 +598,7 @@ public:
         
     bool isGeneratedForCall() const
     {
-        return m_codeBlockForCall;
+        return !!m_codeBlockForCall;
     }
 
     FunctionCodeBlock* codeBlockForCall()
@@ -610,7 +608,7 @@ public:
 
     bool isGeneratedForConstruct() const
     {
-        return m_codeBlockForConstruct;
+        return m_codeBlockForConstruct.get();
     }
 
     FunctionCodeBlock* codeBlockForConstruct()
@@ -676,11 +674,10 @@ 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);
@@ -690,8 +687,8 @@ private:
     friend class ScriptExecutable;
     
     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
-    RefPtr<FunctionCodeBlock> m_codeBlockForCall;
-    RefPtr<FunctionCodeBlock> m_codeBlockForConstruct;
+    WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
+    WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
     RefPtr<TypeSet> m_returnStatementTypeSet;
     unsigned m_parametersStartOffset;
     WriteBarrier<InferredValue> m_singletonFunction;
@@ -719,8 +716,6 @@ public:
 
     DECLARE_INFO;
 
-    void clearCode();
-
     void prepareForExecution(ExecState*);
 
     WebAssemblyCodeBlock* codeBlockForCall()
@@ -729,6 +724,7 @@ public:
     }
 
 private:
+    friend class ExecutableBase;
     WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);
 
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -737,30 +733,10 @@ private:
     WriteBarrier<JSWASMModule> m_module;
     unsigned m_functionIndex;
 
-    RefPtr<WebAssemblyCodeBlock> m_codeBlockForCall;
+    WriteBarrier<WebAssemblyCodeBlock> m_codeBlockForCall;
 };
 #endif
 
-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();
-    }
-}
-
-}
+} // namespace JSC
 
-#endif
+#endif // Executable_h
index 1c7fc62..123a489 100644 (file)
@@ -248,6 +248,14 @@ 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 8123404..0e247e9 100644 (file)
@@ -309,6 +309,12 @@ 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;