We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / bytecode / CodeBlock.cpp
index 1aa4249..d051ab3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2010, 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "ArithProfile.h"
 #include "BasicBlockLocation.h"
+#include "BytecodeDumper.h"
 #include "BytecodeGenerator.h"
 #include "BytecodeLivenessAnalysis.h"
+#include "BytecodeStructs.h"
 #include "BytecodeUseDef.h"
 #include "CallLinkStatus.h"
 #include "CodeBlockSet.h"
 #include "DFGWorklist.h"
 #include "Debugger.h"
 #include "EvalCodeBlock.h"
+#include "FullCodeOrigin.h"
 #include "FunctionCodeBlock.h"
 #include "FunctionExecutableDump.h"
 #include "GetPutInfo.h"
 #include "InlineCallFrame.h"
-#include "Interpreter.h"
+#include "InterpreterInlines.h"
+#include "IsoCellSetInlines.h"
 #include "JIT.h"
 #include "JITMathIC.h"
+#include "JSBigInt.h"
 #include "JSCInlines.h"
 #include "JSCJSValue.h"
 #include "JSFunction.h"
 #include "JSLexicalEnvironment.h"
 #include "JSModuleEnvironment.h"
+#include "JSSet.h"
+#include "JSString.h"
+#include "JSTemplateObjectDescriptor.h"
 #include "LLIntData.h"
 #include "LLIntEntrypoint.h"
 #include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
 #include "LowLevelInterpreter.h"
 #include "ModuleProgramCodeBlock.h"
+#include "ObjectAllocationProfileInlines.h"
 #include "PCToCodeOriginMap.h"
 #include "PolymorphicAccess.h"
 #include "ProfilerDatabase.h"
@@ -77,7 +86,6 @@
 #include <wtf/BagToHashMap.h>
 #include <wtf/CommaPrinter.h>
 #include <wtf/SimpleStats.h>
-#include <wtf/StringExtras.h>
 #include <wtf/StringPrintStream.h>
 #include <wtf/text/UniquedStringImpl.h>
 
 namespace JSC {
 
 const ClassInfo CodeBlock::s_info = {
-    "CodeBlock", 0, 0,
+    "CodeBlock", nullptr, nullptr, nullptr,
     CREATE_METHOD_TABLE(CodeBlock)
 };
 
@@ -203,324 +211,6 @@ void CodeBlock::dump(PrintStream& out) const
     dumpAssumingJITType(out, jitType());
 }
 
-static CString idName(int id0, const Identifier& ident)
-{
-    return toCString(ident.impl(), "(@id", id0, ")");
-}
-
-CString CodeBlock::registerName(int r) const
-{
-    if (isConstantRegisterIndex(r))
-        return constantName(r);
-
-    return toCString(VirtualRegister(r));
-}
-
-CString CodeBlock::constantName(int index) const
-{
-    JSValue value = getConstant(index);
-    return toCString(value, "(", VirtualRegister(index), ")");
-}
-
-static CString regexpToSourceString(RegExp* regExp)
-{
-    char postfix[5] = { '/', 0, 0, 0, 0 };
-    int index = 1;
-    if (regExp->global())
-        postfix[index++] = 'g';
-    if (regExp->ignoreCase())
-        postfix[index++] = 'i';
-    if (regExp->multiline())
-        postfix[index] = 'm';
-    if (regExp->sticky())
-        postfix[index++] = 'y';
-    if (regExp->unicode())
-        postfix[index++] = 'u';
-
-    return toCString("/", regExp->pattern().impl(), postfix);
-}
-
-static CString regexpName(int re, RegExp* regexp)
-{
-    return toCString(regexpToSourceString(regexp), "(@re", re, ")");
-}
-
-NEVER_INLINE static const char* debugHookName(int debugHookType)
-{
-    switch (static_cast<DebugHookType>(debugHookType)) {
-        case DidEnterCallFrame:
-            return "didEnterCallFrame";
-        case WillLeaveCallFrame:
-            return "willLeaveCallFrame";
-        case WillExecuteStatement:
-            return "willExecuteStatement";
-        case WillExecuteExpression:
-            return "willExecuteExpression";
-        case WillExecuteProgram:
-            return "willExecuteProgram";
-        case DidExecuteProgram:
-            return "didExecuteProgram";
-        case DidReachBreakpoint:
-            return "didReachBreakpoint";
-    }
-
-    RELEASE_ASSERT_NOT_REACHED();
-    return "";
-}
-
-void CodeBlock::printUnaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
-{
-    int r0 = (++it)->u.operand;
-    int r1 = (++it)->u.operand;
-
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-}
-
-void CodeBlock::printBinaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
-{
-    int r0 = (++it)->u.operand;
-    int r1 = (++it)->u.operand;
-    int r2 = (++it)->u.operand;
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-}
-
-void CodeBlock::printConditionalJump(PrintStream& out, ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op)
-{
-    int r0 = (++it)->u.operand;
-    int offset = (++it)->u.operand;
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s, %d(->%d)", registerName(r0).data(), offset, location + offset);
-}
-
-void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it)
-{
-    const char* op;
-    switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
-    case op_get_by_id:
-        op = "get_by_id";
-        break;
-    case op_get_by_id_proto_load:
-        op = "get_by_id_proto_load";
-        break;
-    case op_get_by_id_unset:
-        op = "get_by_id_unset";
-        break;
-    case op_get_array_length:
-        op = "array_length";
-        break;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
-        op = 0;
-#endif
-    }
-    int r0 = (++it)->u.operand;
-    int r1 = (++it)->u.operand;
-    int id0 = (++it)->u.operand;
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
-    it += 4; // Increment up to the value profiler.
-}
-
-static void dumpStructure(PrintStream& out, const char* name, Structure* structure, const Identifier& ident)
-{
-    if (!structure)
-        return;
-    
-    out.printf("%s = %p", name, structure);
-    
-    PropertyOffset offset = structure->getConcurrently(ident.impl());
-    if (offset != invalidOffset)
-        out.printf(" (offset = %d)", offset);
-}
-
-static void dumpChain(PrintStream& out, StructureChain* chain, const Identifier& ident)
-{
-    out.printf("chain = %p: [", chain);
-    bool first = true;
-    for (WriteBarrier<Structure>* currentStructure = chain->head();
-         *currentStructure;
-         ++currentStructure) {
-        if (first)
-            first = false;
-        else
-            out.printf(", ");
-        dumpStructure(out, "struct", currentStructure->get(), ident);
-    }
-    out.printf("]");
-}
-
-void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
-{
-    Instruction* instruction = instructions().begin() + location;
-
-    const Identifier& ident = identifier(instruction[3].u.operand);
-    
-    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
-    
-    if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
-        out.printf(" llint(array_length)");
-    else if (StructureID structureID = instruction[4].u.structureID) {
-        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
-        out.printf(" llint(");
-        dumpStructure(out, "struct", structure, ident);
-        out.printf(")");
-        if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_by_id_proto_load)
-            out.printf(" proto(%p)", instruction[6].u.pointer);
-    }
-
-#if ENABLE(JIT)
-    if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
-        StructureStubInfo& stubInfo = *stubPtr;
-        if (stubInfo.resetByGC)
-            out.print(" (Reset By GC)");
-        
-        out.printf(" jit(");
-            
-        Structure* baseStructure = nullptr;
-        PolymorphicAccess* stub = nullptr;
-            
-        switch (stubInfo.cacheType) {
-        case CacheType::GetByIdSelf:
-            out.printf("self");
-            baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
-            break;
-        case CacheType::Stub:
-            out.printf("stub");
-            stub = stubInfo.u.stub;
-            break;
-        case CacheType::Unset:
-            out.printf("unset");
-            break;
-        case CacheType::ArrayLength:
-            out.printf("ArrayLength");
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-            
-        if (baseStructure) {
-            out.printf(", ");
-            dumpStructure(out, "struct", baseStructure, ident);
-        }
-
-        if (stub)
-            out.print(", ", *stub);
-
-        out.printf(")");
-    }
-#else
-    UNUSED_PARAM(map);
-#endif
-}
-
-void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
-{
-    Instruction* instruction = instructions().begin() + location;
-
-    const Identifier& ident = identifier(instruction[2].u.operand);
-    
-    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
-
-    out.print(", ", instruction[8].u.putByIdFlags);
-    
-    if (StructureID structureID = instruction[4].u.structureID) {
-        Structure* structure = m_vm->heap.structureIDTable().get(structureID);
-        out.print(" llint(");
-        if (StructureID newStructureID = instruction[6].u.structureID) {
-            Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID);
-            dumpStructure(out, "prev", structure, ident);
-            out.print(", ");
-            dumpStructure(out, "next", newStructure, ident);
-            if (StructureChain* chain = instruction[7].u.structureChain.get()) {
-                out.print(", ");
-                dumpChain(out, chain, ident);
-            }
-        } else
-            dumpStructure(out, "struct", structure, ident);
-        out.print(")");
-    }
-
-#if ENABLE(JIT)
-    if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
-        StructureStubInfo& stubInfo = *stubPtr;
-        if (stubInfo.resetByGC)
-            out.print(" (Reset By GC)");
-        
-        out.printf(" jit(");
-        
-        switch (stubInfo.cacheType) {
-        case CacheType::PutByIdReplace:
-            out.print("replace, ");
-            dumpStructure(out, "struct", stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
-            break;
-        case CacheType::Stub: {
-            out.print("stub, ", *stubInfo.u.stub);
-            break;
-        }
-        case CacheType::Unset:
-            out.printf("unset");
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-        out.printf(")");
-    }
-#else
-    UNUSED_PARAM(map);
-#endif
-}
-
-void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map)
-{
-    int dst = (++it)->u.operand;
-    int func = (++it)->u.operand;
-    int argCount = (++it)->u.operand;
-    int registerOffset = (++it)->u.operand;
-    printLocationAndOp(out, exec, location, it, op);
-    out.print(registerName(dst), ", ", registerName(func), ", ", argCount, ", ", registerOffset);
-    out.print(" (this at ", virtualRegisterForArgument(0, -registerOffset), ")");
-    if (cacheDumpMode == DumpCaches) {
-        LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
-        if (callLinkInfo->lastSeenCallee) {
-            out.printf(
-                " llint(%p, exec %p)",
-                callLinkInfo->lastSeenCallee.get(),
-                callLinkInfo->lastSeenCallee->executable());
-        }
-#if ENABLE(JIT)
-        if (CallLinkInfo* info = map.get(CodeOrigin(location))) {
-            JSFunction* target = info->lastSeenCallee();
-            if (target)
-                out.printf(" jit(%p, exec %p)", target, target->executable());
-        }
-        
-        if (jitType() != JITCode::FTLJIT)
-            out.print(" status(", CallLinkStatus::computeFor(this, location, map), ")");
-#else
-        UNUSED_PARAM(map);
-#endif
-    }
-    ++it;
-    ++it;
-    dumpArrayProfiling(out, it, hasPrintedProfiling);
-    dumpValueProfiling(out, it, hasPrintedProfiling);
-}
-
-void CodeBlock::printPutByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
-{
-    int r0 = (++it)->u.operand;
-    int id0 = (++it)->u.operand;
-    int r1 = (++it)->u.operand;
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data());
-    it += 5;
-}
-
 void CodeBlock::dumpSource()
 {
     dumpSource(WTF::dataFile());
@@ -530,1262 +220,38 @@ void CodeBlock::dumpSource(PrintStream& out)
 {
     ScriptExecutable* executable = ownerScriptExecutable();
     if (executable->isFunctionExecutable()) {
-        FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
-        StringView source = functionExecutable->source().provider()->getRange(
-            functionExecutable->parametersStartOffset(),
-            functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
-        
-        out.print("function ", inferredName(), source);
-        return;
-    }
-    out.print(executable->source().view());
-}
-
-void CodeBlock::dumpBytecode()
-{
-    dumpBytecode(WTF::dataFile());
-}
-
-void CodeBlock::dumpBytecode(PrintStream& out)
-{
-    // We only use the ExecState* for things that don't actually lead to JS execution,
-    // like converting a JSString to a String. Hence the globalExec is appropriate.
-    ExecState* exec = m_globalObject->globalExec();
-    
-    size_t instructionCount = 0;
-
-    for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
-        ++instructionCount;
-
-    out.print(*this);
-    out.printf(
-        ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)",
-        static_cast<unsigned long>(instructions().size()),
-        static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
-        m_numParameters, m_numCalleeLocals, m_numVars);
-    out.print("; scope at ", scopeRegister());
-    out.printf("\n");
-    
-    StubInfoMap stubInfos;
-    CallLinkInfoMap callLinkInfos;
-    getStubInfoMap(stubInfos);
-    getCallLinkInfoMap(callLinkInfos);
-    
-    const Instruction* begin = instructions().begin();
-    const Instruction* end = instructions().end();
-    for (const Instruction* it = begin; it != end; ++it)
-        dumpBytecode(out, exec, begin, it, stubInfos, callLinkInfos);
-    
-    if (numberOfIdentifiers()) {
-        out.printf("\nIdentifiers:\n");
-        size_t i = 0;
-        do {
-            out.printf("  id%u = %s\n", static_cast<unsigned>(i), identifier(i).string().utf8().data());
-            ++i;
-        } while (i != numberOfIdentifiers());
-    }
-
-    if (!m_constantRegisters.isEmpty()) {
-        out.printf("\nConstants:\n");
-        size_t i = 0;
-        do {
-            const char* sourceCodeRepresentationDescription = nullptr;
-            switch (m_constantsSourceCodeRepresentation[i]) {
-            case SourceCodeRepresentation::Double:
-                sourceCodeRepresentationDescription = ": in source as double";
-                break;
-            case SourceCodeRepresentation::Integer:
-                sourceCodeRepresentationDescription = ": in source as integer";
-                break;
-            case SourceCodeRepresentation::Other:
-                sourceCodeRepresentationDescription = "";
-                break;
-            }
-            out.printf("   k%u = %s%s\n", static_cast<unsigned>(i), toCString(m_constantRegisters[i].get()).data(), sourceCodeRepresentationDescription);
-            ++i;
-        } while (i < m_constantRegisters.size());
-    }
-
-    if (size_t count = m_unlinkedCode->numberOfRegExps()) {
-        out.printf("\nm_regexps:\n");
-        size_t i = 0;
-        do {
-            out.printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).data());
-            ++i;
-        } while (i < count);
-    }
-
-    dumpExceptionHandlers(out);
-    
-    if (m_rareData && !m_rareData->m_switchJumpTables.isEmpty()) {
-        out.printf("Switch Jump Tables:\n");
-        unsigned i = 0;
-        do {
-            out.printf("  %1d = {\n", i);
-            int entry = 0;
-            Vector<int32_t>::const_iterator end = m_rareData->m_switchJumpTables[i].branchOffsets.end();
-            for (Vector<int32_t>::const_iterator iter = m_rareData->m_switchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
-                if (!*iter)
-                    continue;
-                out.printf("\t\t%4d => %04d\n", entry + m_rareData->m_switchJumpTables[i].min, *iter);
-            }
-            out.printf("      }\n");
-            ++i;
-        } while (i < m_rareData->m_switchJumpTables.size());
-    }
-    
-    if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
-        out.printf("\nString Switch Jump Tables:\n");
-        unsigned i = 0;
-        do {
-            out.printf("  %1d = {\n", i);
-            StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
-            for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
-                out.printf("\t\t\"%s\" => %04d\n", iter->key->utf8().data(), iter->value.branchOffset);
-            out.printf("      }\n");
-            ++i;
-        } while (i < m_rareData->m_stringSwitchJumpTables.size());
-    }
-
-    out.printf("\n");
-}
-
-void CodeBlock::dumpExceptionHandlers(PrintStream& out)
-{
-    if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
-        out.printf("\nException Handlers:\n");
-        unsigned i = 0;
-        do {
-            HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
-            out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] } %s\n",
-                i + 1, handler.start, handler.end, handler.target, handler.typeName());
-            ++i;
-        } while (i < m_rareData->m_exceptionHandlers.size());
-    }
-}
-
-void CodeBlock::beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling)
-{
-    if (hasPrintedProfiling) {
-        out.print("; ");
-        return;
-    }
-    
-    out.print("    ");
-    hasPrintedProfiling = true;
-}
-
-void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
-{
-    ConcurrentJSLocker locker(m_lock);
-    
-    ++it;
-    CString description = it->u.profile->briefDescription(locker);
-    if (!description.length())
-        return;
-    beginDumpProfiling(out, hasPrintedProfiling);
-    out.print(description);
-}
-
-void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
-{
-    ConcurrentJSLocker locker(m_lock);
-    
-    ++it;
-    if (!it->u.arrayProfile)
-        return;
-    CString description = it->u.arrayProfile->briefDescription(locker, this);
-    if (!description.length())
-        return;
-    beginDumpProfiling(out, hasPrintedProfiling);
-    out.print(description);
-}
-
-void CodeBlock::dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling)
-{
-    if (!profile || !profile->m_counter)
-        return;
-
-    beginDumpProfiling(out, hasPrintedProfiling);
-    out.print(name, profile->m_counter);
-}
-
-void CodeBlock::dumpArithProfile(PrintStream& out, ArithProfile* profile, bool& hasPrintedProfiling)
-{
-    if (!profile)
-        return;
-    
-    beginDumpProfiling(out, hasPrintedProfiling);
-    out.print("results: ", *profile);
-}
-
-void CodeBlock::printLocationAndOp(PrintStream& out, ExecState*, int location, const Instruction*&, const char* op)
-{
-    out.printf("[%4d] %-17s ", location, op);
-}
-
-void CodeBlock::printLocationOpAndRegisterOperand(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, int operand)
-{
-    printLocationAndOp(out, exec, location, it, op);
-    out.printf("%s", registerName(operand).data());
-}
-
-void CodeBlock::dumpBytecode(
-    PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it,
-    const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
-{
-    int location = it - begin;
-    bool hasPrintedProfiling = false;
-    OpcodeID opcode = exec->interpreter()->getOpcodeID(it->u.opcode);
-    switch (opcode) {
-        case op_enter: {
-            printLocationAndOp(out, exec, location, it, "enter");
-            break;
-        }
-        case op_get_scope: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "get_scope", r0);
-            break;
-        }
-        case op_create_direct_arguments: {
-            int r0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "create_direct_arguments");
-            out.printf("%s", registerName(r0).data());
-            break;
-        }
-        case op_create_scoped_arguments: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "create_scoped_arguments");
-            out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-            break;
-        }
-        case op_create_cloned_arguments: {
-            int r0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "create_cloned_arguments");
-            out.printf("%s", registerName(r0).data());
-            break;
-        }
-        case op_argument_count: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "argument_count", r0);
-            break;
-        }
-        case op_get_argument: {
-            int r0 = (++it)->u.operand;
-            int index = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "argument", r0);
-            out.printf(", %d", index);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_create_rest: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            unsigned argumentOffset = (++it)->u.unsignedValue;
-            printLocationAndOp(out, exec, location, it, "create_rest");
-            out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
-            out.printf("ArgumentsOffset: %u", argumentOffset);
-            break;
-        }
-        case op_get_rest_length: {
-            int r0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_rest_length");
-            out.printf("%s, ", registerName(r0).data());
-            unsigned argumentOffset = (++it)->u.unsignedValue;
-            out.printf("ArgumentsOffset: %u", argumentOffset);
-            break;
-        }
-        case op_create_this: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            unsigned inferredInlineCapacity = (++it)->u.operand;
-            unsigned cachedFunction = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "create_this");
-            out.printf("%s, %s, %u, %u", registerName(r0).data(), registerName(r1).data(), inferredInlineCapacity, cachedFunction);
-            break;
-        }
-        case op_to_this: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "to_this", r0);
-            Structure* structure = (++it)->u.structure.get();
-            if (structure)
-                out.print(", cache(struct = ", RawPointer(structure), ")");
-            out.print(", ", (++it)->u.toThisStatus);
-            break;
-        }
-        case op_check_tdz: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "op_check_tdz", r0);
-            break;
-        }
-        case op_new_object: {
-            int r0 = (++it)->u.operand;
-            unsigned inferredInlineCapacity = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_object");
-            out.printf("%s, %u", registerName(r0).data(), inferredInlineCapacity);
-            ++it; // Skip object allocation profile.
-            break;
-        }
-        case op_new_array: {
-            int dst = (++it)->u.operand;
-            int argv = (++it)->u.operand;
-            int argc = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_array");
-            out.printf("%s, %s, %d", registerName(dst).data(), registerName(argv).data(), argc);
-            ++it; // Skip array allocation profile.
-            break;
-        }
-        case op_new_array_with_spread: {
-            int dst = (++it)->u.operand;
-            int argv = (++it)->u.operand;
-            int argc = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_array_with_spread");
-            out.printf("%s, %s, %d, ", registerName(dst).data(), registerName(argv).data(), argc);
-            unsigned bitVectorIndex = (++it)->u.unsignedValue;
-            const BitVector& bitVector = m_unlinkedCode->bitVector(bitVectorIndex);
-            out.print("BitVector:", bitVectorIndex, ":");
-            for (unsigned i = 0; i < static_cast<unsigned>(argc); i++) {
-                if (bitVector.get(i))
-                    out.print("1");
-                else
-                    out.print("0");
-            }
-            break;
-        }
-        case op_spread: {
-            int dst = (++it)->u.operand;
-            int arg = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "spread");
-            out.printf("%s, %s", registerName(dst).data(), registerName(arg).data());
-            break;
-        }
-        case op_new_array_with_size: {
-            int dst = (++it)->u.operand;
-            int length = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_array_with_size");
-            out.printf("%s, %s", registerName(dst).data(), registerName(length).data());
-            ++it; // Skip array allocation profile.
-            break;
-        }
-        case op_new_array_buffer: {
-            int dst = (++it)->u.operand;
-            int argv = (++it)->u.operand;
-            int argc = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_array_buffer");
-            out.printf("%s, %d, %d", registerName(dst).data(), argv, argc);
-            ++it; // Skip array allocation profile.
-            break;
-        }
-        case op_new_regexp: {
-            int r0 = (++it)->u.operand;
-            int re0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_regexp");
-            out.printf("%s, ", registerName(r0).data());
-            if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps())
-                out.printf("%s", regexpName(re0, regexp(re0)).data());
-            else
-                out.printf("bad_regexp(%d)", re0);
-            break;
-        }
-        case op_mov: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "mov");
-            out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-            break;
-        }
-        case op_profile_type: {
-            int r0 = (++it)->u.operand;
-            ++it;
-            ++it;
-            ++it;
-            ++it;
-            printLocationAndOp(out, exec, location, it, "op_profile_type");
-            out.printf("%s", registerName(r0).data());
-            break;
-        }
-        case op_profile_control_flow: {
-            BasicBlockLocation* basicBlockLocation = (++it)->u.basicBlockLocation;
-            printLocationAndOp(out, exec, location, it, "profile_control_flow");
-            out.printf("[%d, %d]", basicBlockLocation->startOffset(), basicBlockLocation->endOffset());
-            break;
-        }
-        case op_not: {
-            printUnaryOp(out, exec, location, it, "not");
-            break;
-        }
-        case op_eq: {
-            printBinaryOp(out, exec, location, it, "eq");
-            break;
-        }
-        case op_eq_null: {
-            printUnaryOp(out, exec, location, it, "eq_null");
-            break;
-        }
-        case op_neq: {
-            printBinaryOp(out, exec, location, it, "neq");
-            break;
-        }
-        case op_neq_null: {
-            printUnaryOp(out, exec, location, it, "neq_null");
-            break;
-        }
-        case op_stricteq: {
-            printBinaryOp(out, exec, location, it, "stricteq");
-            break;
-        }
-        case op_nstricteq: {
-            printBinaryOp(out, exec, location, it, "nstricteq");
-            break;
-        }
-        case op_less: {
-            printBinaryOp(out, exec, location, it, "less");
-            break;
-        }
-        case op_lesseq: {
-            printBinaryOp(out, exec, location, it, "lesseq");
-            break;
-        }
-        case op_greater: {
-            printBinaryOp(out, exec, location, it, "greater");
-            break;
-        }
-        case op_greatereq: {
-            printBinaryOp(out, exec, location, it, "greatereq");
-            break;
-        }
-        case op_inc: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "inc", r0);
-            break;
-        }
-        case op_dec: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "dec", r0);
-            break;
-        }
-        case op_to_number: {
-            printUnaryOp(out, exec, location, it, "to_number");
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_to_string: {
-            printUnaryOp(out, exec, location, it, "to_string");
-            break;
-        }
-        case op_negate: {
-            printUnaryOp(out, exec, location, it, "negate");
-            ++it; // op_negate has an extra operand for the ArithProfile.
-            break;
-        }
-        case op_add: {
-            printBinaryOp(out, exec, location, it, "add");
-            ++it;
-            break;
-        }
-        case op_mul: {
-            printBinaryOp(out, exec, location, it, "mul");
-            ++it;
-            break;
-        }
-        case op_div: {
-            printBinaryOp(out, exec, location, it, "div");
-            ++it;
-            break;
-        }
-        case op_mod: {
-            printBinaryOp(out, exec, location, it, "mod");
-            break;
-        }
-        case op_pow: {
-            printBinaryOp(out, exec, location, it, "pow");
-            break;
-        }
-        case op_sub: {
-            printBinaryOp(out, exec, location, it, "sub");
-            ++it;
-            break;
-        }
-        case op_lshift: {
-            printBinaryOp(out, exec, location, it, "lshift");
-            break;            
-        }
-        case op_rshift: {
-            printBinaryOp(out, exec, location, it, "rshift");
-            break;
-        }
-        case op_urshift: {
-            printBinaryOp(out, exec, location, it, "urshift");
-            break;
-        }
-        case op_bitand: {
-            printBinaryOp(out, exec, location, it, "bitand");
-            ++it;
-            break;
-        }
-        case op_bitxor: {
-            printBinaryOp(out, exec, location, it, "bitxor");
-            ++it;
-            break;
-        }
-        case op_bitor: {
-            printBinaryOp(out, exec, location, it, "bitor");
-            ++it;
-            break;
-        }
-        case op_overrides_has_instance: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "overrides_has_instance");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            break;
-        }
-        case op_instanceof: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "instanceof");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            break;
-        }
-        case op_instanceof_custom: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "instanceof_custom");
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
-            break;
-        }
-        case op_unsigned: {
-            printUnaryOp(out, exec, location, it, "unsigned");
-            break;
-        }
-        case op_typeof: {
-            printUnaryOp(out, exec, location, it, "typeof");
-            break;
-        }
-        case op_is_empty: {
-            printUnaryOp(out, exec, location, it, "is_empty");
-            break;
-        }
-        case op_is_undefined: {
-            printUnaryOp(out, exec, location, it, "is_undefined");
-            break;
-        }
-        case op_is_boolean: {
-            printUnaryOp(out, exec, location, it, "is_boolean");
-            break;
-        }
-        case op_is_number: {
-            printUnaryOp(out, exec, location, it, "is_number");
-            break;
-        }
-        case op_is_cell_with_type: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int type = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "is_cell_with_type");
-            out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), type);
-            break;
-        }
-        case op_is_object: {
-            printUnaryOp(out, exec, location, it, "is_object");
-            break;
-        }
-        case op_is_object_or_null: {
-            printUnaryOp(out, exec, location, it, "is_object_or_null");
-            break;
-        }
-        case op_is_function: {
-            printUnaryOp(out, exec, location, it, "is_function");
-            break;
-        }
-        case op_in: {
-            printBinaryOp(out, exec, location, it, "in");
-            dumpArrayProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_try_get_by_id: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "try_get_by_id");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_get_by_id:
-        case op_get_by_id_proto_load:
-        case op_get_by_id_unset:
-        case op_get_array_length: {
-            printGetByIdOp(out, exec, location, it);
-            printGetByIdCacheStatus(out, exec, location, stubInfos);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_get_by_id_with_this: {
-            printLocationAndOp(out, exec, location, it, "get_by_id_with_this");
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), idName(id0, identifier(id0)).data());
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_get_by_val_with_this: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_by_val_with_this");
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_put_by_id: {
-            printPutByIdOp(out, exec, location, it, "put_by_id");
-            printPutByIdCacheStatus(out, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_with_this: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_by_id_with_this");
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data(), registerName(r2).data());
-            break;
-        }
-        case op_put_by_val_with_this: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_by_val_with_this");
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
-            break;
-        }
-        case op_put_getter_by_id: {
-            int r0 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int n0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_getter_by_id");
-            out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
-            break;
-        }
-        case op_put_setter_by_id: {
-            int r0 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int n0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_setter_by_id");
-            out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
-            break;
-        }
-        case op_put_getter_setter_by_id: {
-            int r0 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int n0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_getter_setter_by_id");
-            out.printf("%s, %s, %d, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data(), registerName(r2).data());
-            break;
-        }
-        case op_put_getter_by_val: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int n0 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_getter_by_val");
-            out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
-            break;
-        }
-        case op_put_setter_by_val: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int n0 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_setter_by_val");
-            out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
-            break;
-        }
-        case op_define_data_property: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "define_data_property");
-            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
-            break;
-        }
-        case op_define_accessor_property: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            int r4 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "define_accessor_property");
-            out.printf("%s, %s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), registerName(r4).data());
-            break;
-        }
-        case op_del_by_id: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "del_by_id");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
-            break;
-        }
-        case op_get_by_val: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_by_val");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            dumpArrayProfiling(out, it, hasPrintedProfiling);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_put_by_val: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_by_val");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            dumpArrayProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_put_by_val_direct: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_by_val_direct");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            dumpArrayProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_del_by_val: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "del_by_val");
-            out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
-            break;
-        }
-        case op_put_by_index: {
-            int r0 = (++it)->u.operand;
-            unsigned n0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_by_index");
-            out.printf("%s, %u, %s", registerName(r0).data(), n0, registerName(r1).data());
-            break;
-        }
-        case op_jmp: {
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jmp");
-            out.printf("%d(->%d)", offset, location + offset);
-            break;
-        }
-        case op_jtrue: {
-            printConditionalJump(out, exec, begin, it, location, "jtrue");
-            break;
-        }
-        case op_jfalse: {
-            printConditionalJump(out, exec, begin, it, location, "jfalse");
-            break;
-        }
-        case op_jeq_null: {
-            printConditionalJump(out, exec, begin, it, location, "jeq_null");
-            break;
-        }
-        case op_jneq_null: {
-            printConditionalJump(out, exec, begin, it, location, "jneq_null");
-            break;
-        }
-        case op_jneq_ptr: {
-            int r0 = (++it)->u.operand;
-            Special::Pointer pointer = (++it)->u.specialPointer;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jneq_ptr");
-            out.printf("%s, %d (%p), %d(->%d)", registerName(r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset);
-            ++it;
-            break;
-        }
-        case op_jless: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jless");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jlesseq: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jlesseq");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jgreater: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jgreater");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jgreatereq: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jgreatereq");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jnless: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jnless");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jnlesseq: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jnlesseq");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jngreater: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jngreater");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_jngreatereq: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "jngreatereq");
-            out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
-            break;
-        }
-        case op_loop_hint: {
-            printLocationAndOp(out, exec, location, it, "loop_hint");
-            break;
-        }
-        case op_watchdog: {
-            printLocationAndOp(out, exec, location, it, "watchdog");
-            break;
-        }
-        case op_log_shadow_chicken_prologue: {
-            int r0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "log_shadow_chicken_prologue");
-            out.printf("%s", registerName(r0).data());
-            break;
-        }
-        case op_log_shadow_chicken_tail: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "log_shadow_chicken_tail");
-            out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-            break;
-        }
-        case op_switch_imm: {
-            int tableIndex = (++it)->u.operand;
-            int defaultTarget = (++it)->u.operand;
-            int scrutineeRegister = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "switch_imm");
-            out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
-            break;
-        }
-        case op_switch_char: {
-            int tableIndex = (++it)->u.operand;
-            int defaultTarget = (++it)->u.operand;
-            int scrutineeRegister = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "switch_char");
-            out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
-            break;
-        }
-        case op_switch_string: {
-            int tableIndex = (++it)->u.operand;
-            int defaultTarget = (++it)->u.operand;
-            int scrutineeRegister = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "switch_string");
-            out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
-            break;
-        }
-        case op_new_func: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_func");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_new_generator_func: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_generator_func");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_new_async_func: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_async_func");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_new_func_exp: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_func_exp");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_new_generator_func_exp: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_generator_func_exp");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_new_async_func_exp: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int f0 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "new_async_func_exp");
-            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
-            break;
-        }
-        case op_set_function_name: {
-            int funcReg = (++it)->u.operand;
-            int nameReg = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "set_function_name");
-            out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data());
-            break;
-        }
-        case op_call: {
-            printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
-            break;
-        }
-        case op_tail_call: {
-            printCallOp(out, exec, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
-            break;
-        }
-        case op_call_eval: {
-            printCallOp(out, exec, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
-            break;
-        }
-            
-        case op_construct_varargs:
-        case op_call_varargs:
-        case op_tail_call_varargs:
-        case op_tail_call_forward_arguments: {
-            int result = (++it)->u.operand;
-            int callee = (++it)->u.operand;
-            int thisValue = (++it)->u.operand;
-            int arguments = (++it)->u.operand;
-            int firstFreeRegister = (++it)->u.operand;
-            int varArgOffset = (++it)->u.operand;
-            ++it;
-            const char* opName;
-            if (opcode == op_call_varargs)
-                opName = "call_varargs";
-            else if (opcode == op_construct_varargs)
-                opName = "construct_varargs";
-            else if (opcode == op_tail_call_varargs)
-                opName = "tail_call_varargs";
-            else if (opcode == op_tail_call_forward_arguments)
-                opName = "tail_call_forward_arguments";
-            else
-                RELEASE_ASSERT_NOT_REACHED();
-
-            printLocationAndOp(out, exec, location, it, opName);
-            out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-
-        case op_ret: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "ret", r0);
-            break;
-        }
-        case op_construct: {
-            printCallOp(out, exec, location, it, "construct", DumpCaches, hasPrintedProfiling, callLinkInfos);
-            break;
-        }
-        case op_strcat: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int count = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "strcat");
-            out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), count);
-            break;
-        }
-        case op_to_primitive: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "to_primitive");
-            out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-            break;
-        }
-        case op_get_enumerable_length: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_get_enumerable_length");
-            out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
-            it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
-            break;
-        }
-        case op_has_indexed_property: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            int propertyName = it[3].u.operand;
-            ArrayProfile* arrayProfile = it[4].u.arrayProfile;
-            printLocationAndOp(out, exec, location, it, "op_has_indexed_property");
-            out.printf("%s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), arrayProfile);
-            it += OPCODE_LENGTH(op_has_indexed_property) - 1;
-            break;
-        }
-        case op_has_structure_property: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            int propertyName = it[3].u.operand;
-            int enumerator = it[4].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_has_structure_property");
-            out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
-            it += OPCODE_LENGTH(op_has_structure_property) - 1;
-            break;
-        }
-        case op_has_generic_property: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            int propertyName = it[3].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_has_generic_property");
-            out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
-            it += OPCODE_LENGTH(op_has_generic_property) - 1;
-            break;
-        }
-        case op_get_direct_pname: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            int propertyName = it[3].u.operand;
-            int index = it[4].u.operand;
-            int enumerator = it[5].u.operand;
-            ValueProfile* profile = it[6].u.profile;
-            printLocationAndOp(out, exec, location, it, "op_get_direct_pname");
-            out.printf("%s, %s, %s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data(), profile);
-            it += OPCODE_LENGTH(op_get_direct_pname) - 1;
-            break;
-
-        }
-        case op_get_property_enumerator: {
-            int dst = it[1].u.operand;
-            int base = it[2].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_get_property_enumerator");
-            out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
-            it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
-            break;
-        }
-        case op_enumerator_structure_pname: {
-            int dst = it[1].u.operand;
-            int enumerator = it[2].u.operand;
-            int index = it[3].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_enumerator_structure_pname");
-            out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
-            it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
-            break;
-        }
-        case op_enumerator_generic_pname: {
-            int dst = it[1].u.operand;
-            int enumerator = it[2].u.operand;
-            int index = it[3].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_enumerator_generic_pname");
-            out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
-            it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
-            break;
-        }
-        case op_to_index_string: {
-            int dst = it[1].u.operand;
-            int index = it[2].u.operand;
-            printLocationAndOp(out, exec, location, it, "op_to_index_string");
-            out.printf("%s, %s", registerName(dst).data(), registerName(index).data());
-            it += OPCODE_LENGTH(op_to_index_string) - 1;
-            break;
-        }
-        case op_push_with_scope: {
-            int dst = (++it)->u.operand;
-            int newScope = (++it)->u.operand;
-            int currentScope = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "push_with_scope");
-            out.printf("%s, %s, %s", registerName(dst).data(), registerName(newScope).data(), registerName(currentScope).data());
-            break;
-        }
-        case op_get_parent_scope: {
-            int dst = (++it)->u.operand;
-            int parentScope = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_parent_scope");
-            out.printf("%s, %s", registerName(dst).data(), registerName(parentScope).data());
-            break;
-        }
-        case op_create_lexical_environment: {
-            int dst = (++it)->u.operand;
-            int scope = (++it)->u.operand;
-            int symbolTable = (++it)->u.operand;
-            int initialValue = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "create_lexical_environment");
-            out.printf("%s, %s, %s, %s", 
-                registerName(dst).data(), registerName(scope).data(), registerName(symbolTable).data(), registerName(initialValue).data());
-            break;
-        }
-        case op_catch: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "catch");
-            out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
-            break;
-        }
-        case op_throw: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "throw", r0);
-            break;
-        }
-        case op_throw_static_error: {
-            int k0 = (++it)->u.operand;
-            ErrorType k1 = static_cast<ErrorType>((++it)->u.unsignedValue);
-            printLocationAndOp(out, exec, location, it, "throw_static_error");
-            out.printf("%s, ", constantName(k0).data());
-            out.print(k1);
-            break;
-        }
-        case op_debug: {
-            int debugHookType = (++it)->u.operand;
-            int hasBreakpointFlag = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "debug");
-            out.printf("%s, %d", debugHookName(debugHookType), hasBreakpointFlag);
-            break;
-        }
-        case op_assert: {
-            int condition = (++it)->u.operand;
-            int line = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "assert");
-            out.printf("%s, %d", registerName(condition).data(), line);
-            break;
-        }
-        case op_end: {
-            int r0 = (++it)->u.operand;
-            printLocationOpAndRegisterOperand(out, exec, location, it, "end", r0);
-            break;
-        }
-        case op_resolve_scope: {
-            int r0 = (++it)->u.operand;
-            int scope = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            ResolveType resolveType = static_cast<ResolveType>((++it)->u.operand);
-            int depth = (++it)->u.operand;
-            void* pointer = (++it)->u.pointer;
-            printLocationAndOp(out, exec, location, it, "resolve_scope");
-            out.printf("%s, %s, %s, <%s>, %d, %p", registerName(r0).data(), registerName(scope).data(), idName(id0, identifier(id0)).data(), resolveTypeName(resolveType), depth, pointer);
-            break;
-        }
-        case op_get_from_scope: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
-            ++it; // Structure
-            int operand = (++it)->u.operand; // Operand
-            printLocationAndOp(out, exec, location, it, "get_from_scope");
-            out.print(registerName(r0), ", ", registerName(r1));
-            if (static_cast<unsigned>(id0) == UINT_MAX)
-                out.print(", anonymous");
-            else
-                out.print(", ", idName(id0, identifier(id0)));
-            out.print(", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, ", operand);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_put_to_scope: {
-            int r0 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
-            ++it; // Structure
-            int operand = (++it)->u.operand; // Operand
-            printLocationAndOp(out, exec, location, it, "put_to_scope");
-            out.print(registerName(r0));
-            if (static_cast<unsigned>(id0) == UINT_MAX)
-                out.print(", anonymous");
-            else
-                out.print(", ", idName(id0, identifier(id0)));
-            out.print(", ", registerName(r1), ", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, <structure>, ", operand);
-            break;
-        }
-        case op_get_from_arguments: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_from_arguments");
-            out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), offset);
-            dumpValueProfiling(out, it, hasPrintedProfiling);
-            break;
-        }
-        case op_put_to_arguments: {
-            int r0 = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "put_to_arguments");
-            out.printf("%s, %d, %s", registerName(r0).data(), offset, registerName(r1).data());
-            break;
-        }
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
+        FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
+        StringView source = functionExecutable->source().provider()->getRange(
+            functionExecutable->parametersStartOffset(),
+            functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
+        
+        out.print("function ", inferredName(), source);
+        return;
     }
+    out.print(executable->source().view());
+}
 
-    dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
-    {
-        dumpArithProfile(out, arithProfileForBytecodeOffset(location), hasPrintedProfiling);
-    }
-    
-#if ENABLE(DFG_JIT)
-    Vector<DFG::FrequentExitSite> exitSites = exitProfile().exitSitesFor(location);
-    if (!exitSites.isEmpty()) {
-        out.print(" !! frequent exits: ");
-        CommaPrinter comma;
-        for (auto& exitSite : exitSites)
-            out.print(comma, exitSite.kind(), " ", exitSite.jitType());
-    }
-#else // ENABLE(DFG_JIT)
-    UNUSED_PARAM(location);
-#endif // ENABLE(DFG_JIT)
-    out.print("\n");
+void CodeBlock::dumpBytecode()
+{
+    dumpBytecode(WTF::dataFile());
+}
+
+void CodeBlock::dumpBytecode(PrintStream& out)
+{
+    ICStatusMap statusMap;
+    getICStatusMap(statusMap);
+    BytecodeDumper<CodeBlock>::dumpBlock(this, instructions(), out, statusMap);
+}
+
+void CodeBlock::dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const ICStatusMap& statusMap)
+{
+    BytecodeDumper<CodeBlock>::dumpBytecode(this, out, begin, it, statusMap);
 }
 
-void CodeBlock::dumpBytecode(
-    PrintStream& out, unsigned bytecodeOffset,
-    const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
+void CodeBlock::dumpBytecode(PrintStream& out, unsigned bytecodeOffset, const ICStatusMap& statusMap)
 {
-    ExecState* exec = m_globalObject->globalExec();
-    const Instruction* it = instructions().begin() + bytecodeOffset;
-    dumpBytecode(out, exec, instructions().begin(), it, stubInfos, callLinkInfos);
+    const Instruction* it = &instructions()[bytecodeOffset];
+    dumpBytecode(out, instructions().begin(), it, statusMap);
 }
 
 #define FOR_EACH_MEMBER_VECTOR(macro) \
@@ -1827,8 +293,6 @@ private:
 CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock& other)
     : JSCell(*vm, structure)
     , m_globalObject(other.m_globalObject)
-    , m_numCalleeLocals(other.m_numCalleeLocals)
-    , m_numVars(other.m_numVars)
     , m_shouldAlwaysBeInlined(true)
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
@@ -1839,12 +303,15 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock
     , m_isConstructor(other.m_isConstructor)
     , m_isStrictMode(other.m_isStrictMode)
     , m_codeType(other.m_codeType)
-    , m_unlinkedCode(*other.m_vm, this, other.m_unlinkedCode.get())
+    , m_numCalleeLocals(other.m_numCalleeLocals)
+    , m_numVars(other.m_numVars)
+    , m_numberOfArgumentsToSkip(other.m_numberOfArgumentsToSkip)
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(*other.m_vm, this, other.m_ownerExecutable.get())
-    , m_vm(other.m_vm)
+    , m_unlinkedCode(*other.vm(), this, other.m_unlinkedCode.get())
+    , m_ownerExecutable(*other.vm(), this, other.m_ownerExecutable.get())
+    , m_poisonedVM(other.m_poisonedVM)
     , m_instructions(other.m_instructions)
     , m_thisRegister(other.m_thisRegister)
     , m_scopeRegister(other.m_scopeRegister)
@@ -1859,19 +326,20 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
-    , m_creationTime(std::chrono::steady_clock::now())
+    , m_creationTime(MonotonicTime::now())
 {
-    m_visitWeaklyHasBeenCalled = false;
-
     ASSERT(heap()->isDeferred());
     ASSERT(m_scopeRegister.isLocal());
 
     setNumParameters(other.numParameters());
+    
+    vm->heap.codeBlockSet().add(this);
 }
 
 void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
 {
     Base::finishCreation(vm);
+    finishCreationCommon(vm);
 
     optimizeAfterWarmUp();
     jitAfterWarmUp();
@@ -1880,20 +348,15 @@ void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
         createRareDataIfNecessary();
         
         m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
-        m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
         m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables;
         m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
     }
-    
-    heap()->m_codeBlocks->add(this);
 }
 
 CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
     JSScope* scope, RefPtr<SourceProvider>&& sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
     : JSCell(*vm, structure)
-    , m_globalObject(scope->globalObject()->vm(), this, scope->globalObject())
-    , m_numCalleeLocals(unlinkedCodeBlock->m_numCalleeLocals)
-    , m_numVars(unlinkedCodeBlock->m_numVars)
+    , m_globalObject(*vm, this, scope->globalObject(*vm))
     , m_shouldAlwaysBeInlined(true)
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
@@ -1904,12 +367,14 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecut
     , m_isConstructor(unlinkedCodeBlock->isConstructor())
     , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
     , m_codeType(unlinkedCodeBlock->codeType())
-    , m_unlinkedCode(m_globalObject->vm(), this, unlinkedCodeBlock)
+    , m_numCalleeLocals(unlinkedCodeBlock->numCalleeLocals())
+    , m_numVars(unlinkedCodeBlock->numVars())
     , m_hasDebuggerStatement(false)
     , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
-    , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
-    , m_vm(unlinkedCodeBlock->vm())
+    , m_unlinkedCode(*vm, this, unlinkedCodeBlock)
+    , m_ownerExecutable(*vm, this, ownerExecutable)
+    , m_poisonedVM(vm)
     , m_thisRegister(unlinkedCodeBlock->thisRegister())
     , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
     , m_source(WTFMove(sourceProvider))
@@ -1918,40 +383,56 @@ CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecut
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
-    , m_creationTime(std::chrono::steady_clock::now())
+    , m_creationTime(MonotonicTime::now())
 {
-    m_visitWeaklyHasBeenCalled = false;
-
     ASSERT(heap()->isDeferred());
     ASSERT(m_scopeRegister.isLocal());
 
     ASSERT(m_source);
     setNumParameters(unlinkedCodeBlock->numParameters());
+    
+    vm->heap.codeBlockSet().add(this);
 }
 
-void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
+// The main purpose of this function is to generate linked bytecode from unlinked bytecode. The process
+// of linking is taking an abstract representation of bytecode and tying it to a GlobalObject and scope
+// chain. For example, this process allows us to cache the depth of lexical environment reads that reach
+// outside of this CodeBlock's compilation unit. It also allows us to generate particular constants that
+// we can't generate during unlinked bytecode generation. This process is not allowed to generate control
+// flow or introduce new locals. The reason for this is we rely on liveness analysis to be the same for
+// all the CodeBlocks of an UnlinkedCodeBlock. We rely on this fact by caching the liveness analysis
+// inside UnlinkedCodeBlock.
+bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
     JSScope* scope)
 {
     Base::finishCreation(vm);
+    finishCreationCommon(vm);
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     if (vm.typeProfiler() || vm.controlFlowProfiler())
         vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
 
     setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
+    RETURN_IF_EXCEPTION(throwScope, false);
+
+    setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets());
+    RETURN_IF_EXCEPTION(throwScope, false);
+
     if (unlinkedCodeBlock->usesGlobalObject())
-        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
+        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(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, this, m_globalObject->jsCellForLinkTimeConstant(type));
+            m_constantRegisters[registerIndex].set(vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
     }
 
     // We already have the cloned symbol table for the module environment since we need to instantiate
     // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
     if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(vm, unlinkedCodeBlock)) {
         SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable();
-        if (m_vm->typeProfiler()) {
+        if (vm.typeProfiler()) {
             ConcurrentJSLocker locker(clonedSymbolTable->m_lock);
             clonedSymbolTable->prepareForTypeProfiling(locker);
         }
@@ -1964,7 +445,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
         if (shouldUpdateFunctionHasExecutedCache)
             vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
-        m_functionDecls[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
+        m_functionDecls[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source()));
     }
 
     m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs());
@@ -1972,25 +453,18 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
         if (shouldUpdateFunctionHasExecutedCache)
             vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
-        m_functionExprs[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
+        m_functionExprs[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source()));
     }
 
     if (unlinkedCodeBlock->hasRareData()) {
         createRareDataIfNecessary();
-        if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
-            m_rareData->m_constantBuffers.grow(count);
-            for (size_t i = 0; i < count; i++) {
-                const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
-                m_rareData->m_constantBuffers[i] = buffer;
-            }
-        }
         if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
             m_rareData->m_exceptionHandlers.resizeToFit(count);
             for (size_t i = 0; i < count; i++) {
                 const UnlinkedHandlerInfo& unlinkedHandler = unlinkedCodeBlock->exceptionHandler(i);
                 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
 #if ENABLE(JIT)
-                handler.initialize(unlinkedHandler, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(op_catch))));
+                handler.initialize(unlinkedHandler, CodeLocationLabel<ExceptionHandlerPtrTag>(LLInt::getCodePtr<BytecodePtrTag>(op_catch).retagged<ExceptionHandlerPtrTag>()));
 #else
                 handler.initialize(unlinkedHandler);
 #endif
@@ -2030,6 +504,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         m_arrayAllocationProfiles = RefCountedArray<ArrayAllocationProfile>(size);
     if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
         m_valueProfiles = RefCountedArray<ValueProfile>(size);
+    if (!vm.canUseJIT())
+        RELEASE_ASSERT(!m_valueProfiles.size());
     if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
         m_objectAllocationProfiles = RefCountedArray<ObjectAllocationProfile>(size);
 
@@ -2048,6 +524,12 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
     unsigned valueProfileCount = 0;
     auto linkValueProfile = [&](unsigned bytecodeOffset, unsigned opLength) {
+        if (!vm.canUseJIT()) {
+            ASSERT(vm.noJITValueProfileSingleton);
+            instructions[bytecodeOffset + opLength - 1] = vm.noJITValueProfileSingleton.get();
+            return;
+        }
+
         unsigned valueProfileIndex = valueProfileCount++;
         ValueProfile* profile = &m_valueProfiles[valueProfileIndex];
         ASSERT(profile->m_bytecodeOffset == -1);
@@ -2060,7 +542,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
         unsigned opLength = opcodeLength(pc[0].u.opcode);
 
-        instructions[i] = vm.interpreter->getOpcode(pc[0].u.opcode);
+        instructions[i] = 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;
@@ -2089,15 +571,22 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         case op_get_by_id:
         case op_get_by_id_with_this:
         case op_try_get_by_id:
+        case op_get_by_id_direct:
         case op_get_by_val_with_this:
         case op_get_from_arguments:
         case op_to_number:
+        case op_to_object:
         case op_get_argument: {
             linkValueProfile(i, opLength);
             break;
         }
 
-        case op_in:
+        case op_to_this: {
+            linkValueProfile(i, opLength);
+            break;
+        }
+
+        case op_in_by_val:
         case op_put_by_val:
         case op_put_by_val_direct: {
             int arrayProfileIndex = pc[opLength - 1].u.operand;
@@ -2107,19 +596,26 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         }
 
         case op_new_array:
-        case op_new_array_buffer:
-        case op_new_array_with_size: {
-            int arrayAllocationProfileIndex = pc[opLength - 1].u.operand;
-            instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
+        case op_new_array_with_size:
+        case op_new_array_buffer: {
+            unsigned arrayAllocationProfileIndex;
+            IndexingType recommendedIndexingType;
+            std::tie(arrayAllocationProfileIndex, recommendedIndexingType) = UnlinkedCodeBlock::decompressArrayAllocationProfile(pc[opLength - 1].u.operand);
+
+            ArrayAllocationProfile* profile = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
+            if (pc[0].u.opcode == op_new_array_buffer)
+                profile->initializeIndexingMode(recommendedIndexingType);
+            instructions[i + opLength - 1] = profile;
             break;
         }
+
         case op_new_object: {
             int objectAllocationProfileIndex = pc[opLength - 1].u.operand;
             ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
             int inferredInlineCapacity = pc[opLength - 2].u.operand;
 
             instructions[i + opLength - 1] = objectAllocationProfile;
-            objectAllocationProfile->initialize(vm,
+            objectAllocationProfile->initializeProfile(vm,
                 m_globalObject.get(), this, m_globalObject->objectPrototype(), inferredInlineCapacity);
             break;
         }
@@ -2149,6 +645,8 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             int localScopeDepth = pc[5].u.operand;
 
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
+            RETURN_IF_EXCEPTION(throwScope, false);
+
             instructions[i + 4].u.operand = op.type;
             instructions[i + 5].u.operand = op.depth;
             if (op.lexicalEnvironment) {
@@ -2183,6 +681,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
             const Identifier& ident = identifier(pc[3].u.operand);
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), InitializationMode::NotInitialization);
+            RETURN_IF_EXCEPTION(throwScope, false);
 
             instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
             if (op.type == ModuleVar)
@@ -2218,6 +717,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             int localScopeDepth = pc[5].u.operand;
             instructions[i + 5].u.pointer = nullptr;
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Put, getPutInfo.resolveType(), getPutInfo.initializationMode());
+            RETURN_IF_EXCEPTION(throwScope, false);
 
             instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
             if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
@@ -2252,6 +752,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
                 // we're abstractly "read"ing from a JSScope.
                 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
+                RETURN_IF_EXCEPTION(throwScope, false);
 
                 if (op.type == ClosureVar || op.type == ModuleVar)
                     symbolTable = op.lexicalEnvironment->symbolTable();
@@ -2319,7 +820,7 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         }
 
         case op_debug: {
-            if (pc[1].u.index == DidReachBreakpoint)
+            if (pc[1].u.unsignedValue == DidReachBreakpoint)
                 m_hasDebuggerStatement = true;
             break;
         }
@@ -2327,13 +828,15 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
         case op_create_rest: {
             int numberOfArgumentsToSkip = instructions[i + 3].u.operand;
             ASSERT_UNUSED(numberOfArgumentsToSkip, numberOfArgumentsToSkip >= 0);
-            ASSERT_WITH_MESSAGE(numberOfArgumentsToSkip == numParameters() - 1, "We assume that this is true when rematerializing the rest parameter during OSR exit in the FTL JIT.");
+            // This is used when rematerializing the rest parameter during OSR exit in the FTL JIT.");
+            m_numberOfArgumentsToSkip = numberOfArgumentsToSkip;
             break;
         }
-
+        
         default:
             break;
         }
+
         i += opLength;
     }
 
@@ -2355,17 +858,27 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
     if (Options::dumpGeneratedBytecodes())
         dumpBytecode();
-    
-    heap()->m_codeBlocks->add(this);
+
     heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
+
+    return true;
+}
+
+void CodeBlock::finishCreationCommon(VM& vm)
+{
+    m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this));
 }
 
 CodeBlock::~CodeBlock()
 {
-    if (m_vm->m_perBytecodeProfiler)
-        m_vm->m_perBytecodeProfiler->notifyDestruction(this);
+    VM& vm = *m_poisonedVM;
+
+    vm.heap.codeBlockSet().remove(this);
+    
+    if (UNLIKELY(vm.m_perBytecodeProfiler))
+        vm.m_perBytecodeProfiler->notifyDestruction(this);
 
-    if (unlinkedCodeBlock()->didOptimize() == MixedTriState)
+    if (!vm.heap.isShuttingDown() && unlinkedCodeBlock()->didOptimize() == MixedTriState)
         unlinkedCodeBlock()->setDidOptimize(FalseTriState);
 
 #if ENABLE(VERBOSE_VALUE_PROFILE)
@@ -2385,7 +898,7 @@ CodeBlock::~CodeBlock()
     // destructors.
 
 #if ENABLE(JIT)
-    for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
+    for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
         StructureStubInfo* stub = *iter;
         stub->aboutToDie();
         stub->deref();
@@ -2393,31 +906,66 @@ CodeBlock::~CodeBlock()
 #endif // ENABLE(JIT)
 }
 
+void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    JSGlobalObject* globalObject = m_globalObject.get();
+    ExecState* exec = globalObject->globalExec();
+
+    for (const auto& entry : constants) {
+        const IdentifierSet& set = entry.first;
+
+        Structure* setStructure = globalObject->setStructure();
+        RETURN_IF_EXCEPTION(scope, void());
+        JSSet* jsSet = JSSet::create(exec, vm, setStructure, set.size());
+        RETURN_IF_EXCEPTION(scope, void());
+
+        for (auto setEntry : set) {
+            JSString* jsString = jsOwnedString(&vm, setEntry.get()); 
+            jsSet->add(exec, jsString);
+            RETURN_IF_EXCEPTION(scope, void());
+        }
+        m_constantRegisters[entry.second].set(vm, this, jsSet);
+    }
+}
+
 void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
 {
+    VM& vm = *m_poisonedVM;
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    JSGlobalObject* globalObject = m_globalObject.get();
+    ExecState* exec = globalObject->globalExec();
+
     ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
     size_t count = constants.size();
     m_constantRegisters.resizeToFit(count);
-    bool hasTypeProfiler = !!m_vm->typeProfiler();
+    bool hasTypeProfiler = !!vm.typeProfiler();
     for (size_t i = 0; i < count; i++) {
         JSValue constant = constants[i].get();
 
         if (!constant.isEmpty()) {
-            if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(*vm(), constant)) {
-                if (hasTypeProfiler) {
-                    ConcurrentJSLocker locker(symbolTable->m_lock);
-                    symbolTable->prepareForTypeProfiling(locker);
+            if (constant.isCell()) {
+                JSCell* cell = constant.asCell();
+                if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
+                    if (hasTypeProfiler) {
+                        ConcurrentJSLocker locker(symbolTable->m_lock);
+                        symbolTable->prepareForTypeProfiling(locker);
+                    }
+
+                    SymbolTable* clone = symbolTable->cloneScopePart(vm);
+                    if (wasCompiledWithDebuggingOpcodes())
+                        clone->setRareDataCodeBlock(this);
+
+                    constant = clone;
+                } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
+                    auto* templateObject = descriptor->createTemplateObject(exec);
+                    RETURN_IF_EXCEPTION(scope, void());
+                    constant = templateObject;
                 }
-
-                SymbolTable* clone = symbolTable->cloneScopePart(*m_vm);
-                if (wasCompiledWithDebuggingOpcodes())
-                    clone->setRareDataCodeBlock(this);
-
-                constant = clone;
             }
         }
 
-        m_constantRegisters[i].set(*m_vm, this, constant);
+        m_constantRegisters[i].set(vm, this, constant);
     }
 
     m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation;
@@ -2432,7 +980,7 @@ void CodeBlock::setNumParameters(int newValue)
 {
     m_numParameters = newValue;
 
-    m_argumentValueProfiles = RefCountedArray<ValueProfile>(newValue);
+    m_argumentValueProfiles = RefCountedArray<ValueProfile>(vm()->canUseJIT() ? newValue : 0);
 }
 
 CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
@@ -2447,84 +995,27 @@ CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
 #endif // ENABLE(FTL_JIT)
 }
 
-void CodeBlock::visitWeakly(SlotVisitor& visitor)
-{
-    ConcurrentJSLocker locker(m_lock);
-    if (m_visitWeaklyHasBeenCalled)
-        return;
-    
-    m_visitWeaklyHasBeenCalled = true;
-
-    if (Heap::isMarkedConcurrently(this))
-        return;
-
-    if (shouldVisitStrongly(locker)) {
-        visitor.appendUnbarriered(this);
-        return;
-    }
-    
-    // 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 (!JITCode::isOptimizingJIT(jitType()))
-        return;
-
-    // If we jettison ourselves we'll install our alternative, so make sure that it
-    // survives GC even if we don't.
-    visitor.append(m_alternative);
-    
-    // There are two things that we use weak reference harvesters for: DFG fixpoint for
-    // jettisoning, and trying to find structures that would be live based on some
-    // inline cache. So it makes sense to register them regardless.
-    visitor.addWeakReferenceHarvester(&m_weakReferenceHarvester);
-
-#if ENABLE(DFG_JIT)
-    // We get here if we're live in the sense that our owner executable is live,
-    // but we're not yet live for sure in another sense: we may yet decide that this
-    // code block should be jettisoned based on its outgoing weak references being
-    // stale. Set a flag to indicate that we're still assuming that we're dead, and
-    // perform one round of determining if we're live. The GC may determine, based on
-    // either us marking additional objects, or by other objects being marked for
-    // other reasons, that this iteration should run again; it will notify us of this
-    // decision by calling harvestWeakReferences().
-
-    m_allTransitionsHaveBeenMarked = false;
-    propagateTransitions(locker, visitor);
-
-    m_jitCode->dfgCommon()->livenessHasBeenProved = false;
-    determineLiveness(locker, visitor);
-#endif // ENABLE(DFG_JIT)
-}
-
-size_t CodeBlock::estimatedSize(JSCell* cell)
+size_t CodeBlock::estimatedSize(JSCell* cell, VM& vm)
 {
     CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
     size_t extraMemoryAllocated = thisObject->m_instructions.size() * sizeof(Instruction);
     if (thisObject->m_jitCode)
         extraMemoryAllocated += thisObject->m_jitCode->size();
-    return Base::estimatedSize(cell) + extraMemoryAllocated;
+    return Base::estimatedSize(cell, vm) + extraMemoryAllocated;
 }
 
 void CodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
-    JSCell::visitChildren(thisObject, visitor);
+    Base::visitChildren(cell, visitor);
+    visitor.append(thisObject->m_ownerEdge);
     thisObject->visitChildren(visitor);
 }
 
 void CodeBlock::visitChildren(SlotVisitor& visitor)
 {
     ConcurrentJSLocker locker(m_lock);
-    // 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.appendUnbarriered(otherBlock);
 
@@ -2543,9 +1034,8 @@ void CodeBlock::visitChildren(SlotVisitor& visitor)
 
     stronglyVisitStrongReferences(locker, visitor);
     stronglyVisitWeakReferences(locker, visitor);
-
-    m_allTransitionsHaveBeenMarked = false;
-    propagateTransitions(locker, visitor);
+    
+    VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).add(this);
 }
 
 bool CodeBlock::shouldVisitStrongly(const ConcurrentJSLocker& locker)
@@ -2572,42 +1062,42 @@ bool CodeBlock::shouldJettisonDueToWeakReference()
     return !Heap::isMarked(this);
 }
 
-static std::chrono::milliseconds timeToLive(JITCode::JITType jitType)
+static Seconds timeToLive(JITCode::JITType jitType)
 {
     if (UNLIKELY(Options::useEagerCodeBlockJettisonTiming())) {
         switch (jitType) {
         case JITCode::InterpreterThunk:
-            return std::chrono::milliseconds(10);
+            return 10_ms;
         case JITCode::BaselineJIT:
-            return std::chrono::milliseconds(10 + 20);
+            return 30_ms;
         case JITCode::DFGJIT:
-            return std::chrono::milliseconds(40);
+            return 40_ms;
         case JITCode::FTLJIT:
-            return std::chrono::milliseconds(120);
+            return 120_ms;
         default:
-            return std::chrono::milliseconds::max();
+            return Seconds::infinity();
         }
     }
 
     switch (jitType) {
     case JITCode::InterpreterThunk:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(5));
+        return 5_s;
     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(5 + 10));
+        return 15_s;
     case JITCode::DFGJIT:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(20));
+        return 20_s;
     case JITCode::FTLJIT:
-        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds(60));
+        return 60_s;
     default:
-        return std::chrono::milliseconds::max();
+        return Seconds::infinity();
     }
 }
 
 bool CodeBlock::shouldJettisonDueToOldAge(const ConcurrentJSLocker&)
 {
-    if (Heap::isMarkedConcurrently(this))
+    if (Heap::isMarked(this))
         return false;
 
     if (UNLIKELY(Options::forceCodeBlockToJettisonDueToOldAge()))
@@ -2622,10 +1112,10 @@ bool CodeBlock::shouldJettisonDueToOldAge(const ConcurrentJSLocker&)
 #if ENABLE(DFG_JIT)
 static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
 {
-    if (transition.m_codeOrigin && !Heap::isMarkedConcurrently(transition.m_codeOrigin.get()))
+    if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
         return false;
     
-    if (!Heap::isMarkedConcurrently(transition.m_from.get()))
+    if (!Heap::isMarked(transition.m_from.get()))
         return false;
     
     return true;
@@ -2636,30 +1126,24 @@ void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& vis
 {
     UNUSED_PARAM(visitor);
 
-    if (m_allTransitionsHaveBeenMarked)
-        return;
+    VM& vm = *m_poisonedVM;
 
-    bool allAreMarkedSoFar = true;
-        
-    Interpreter* interpreter = m_vm->interpreter;
     if (jitType() == JITCode::InterpreterThunk) {
         const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
         for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
             Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
-            switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
+            switch (Interpreter::getOpcodeID(instruction[0])) {
             case op_put_by_id: {
                 StructureID oldStructureID = instruction[4].u.structureID;
                 StructureID newStructureID = instruction[6].u.structureID;
                 if (!oldStructureID || !newStructureID)
                     break;
                 Structure* oldStructure =
-                    m_vm->heap.structureIDTable().get(oldStructureID);
+                    vm.heap.structureIDTable().get(oldStructureID);
                 Structure* newStructure =
-                    m_vm->heap.structureIDTable().get(newStructureID);
-                if (Heap::isMarkedConcurrently(oldStructure))
+                    vm.heap.structureIDTable().get(newStructureID);
+                if (Heap::isMarked(oldStructure))
                     visitor.appendUnbarriered(newStructure);
-                else
-                    allAreMarkedSoFar = false;
                 break;
             }
             default:
@@ -2670,16 +1154,19 @@ void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& vis
 
 #if ENABLE(JIT)
     if (JITCode::isJIT(jitType())) {
-        for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter)
-            allAreMarkedSoFar &= (*iter)->propagateTransitions(visitor);
+        for (auto iter = m_stubInfos.begin(); !!iter; ++iter)
+            (*iter)->propagateTransitions(visitor);
     }
 #endif // ENABLE(JIT)
     
 #if ENABLE(DFG_JIT)
     if (JITCode::isOptimizingJIT(jitType())) {
         DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
+        
+        dfgCommon->recordedStatuses.markIfCheap(visitor);
+        
         for (auto& weakReference : dfgCommon->weakStructureReferences)
-            allAreMarkedSoFar &= weakReference->markIfCheap(visitor);
+            weakReference->markIfCheap(visitor);
 
         for (auto& transition : dfgCommon->transitions) {
             if (shouldMarkTransition(transition)) {
@@ -2703,14 +1190,10 @@ void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& vis
                 // live).
 
                 visitor.append(transition.m_to);
-            } else
-                allAreMarkedSoFar = false;
+            }
         }
     }
 #endif // ENABLE(DFG_JIT)
-    
-    if (allAreMarkedSoFar)
-        m_allTransitionsHaveBeenMarked = true;
 }
 
 void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visitor)
@@ -2718,11 +1201,16 @@ void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visito
     UNUSED_PARAM(visitor);
     
 #if ENABLE(DFG_JIT)
-    // Check if we have any remaining work to do.
-    DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
-    if (dfgCommon->livenessHasBeenProved)
+    if (Heap::isMarked(this))
         return;
     
+    // In rare and weird cases, this could be called on a baseline CodeBlock. One that I found was
+    // that we might decide that the CodeBlock should be jettisoned due to old age, so the
+    // isMarked check doesn't protect us.
+    if (!JITCode::isOptimizingJIT(jitType()))
+        return;
+    
+    DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
     // Now check all of our weak references. If all of them are live, then we
     // have proved liveness and so we scan our strong references. If at end of
     // GC we still have not proved liveness, then this code block is toast.
@@ -2730,14 +1218,14 @@ void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visito
     for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
         JSCell* reference = dfgCommon->weakReferences[i].get();
         ASSERT(!jsDynamicCast<CodeBlock*>(*reference->vm(), reference));
-        if (!Heap::isMarkedConcurrently(reference)) {
+        if (!Heap::isMarked(reference)) {
             allAreLiveSoFar = false;
             break;
         }
     }
     if (allAreLiveSoFar) {
         for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
-            if (!Heap::isMarkedConcurrently(dfgCommon->weakStructureReferences[i].get())) {
+            if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
                 allAreLiveSoFar = false;
                 break;
             }
@@ -2751,21 +1239,10 @@ void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visito
     
     // All weak references are live. Record this information so we don't
     // come back here again, and scan the strong references.
-    dfgCommon->livenessHasBeenProved = true;
     visitor.appendUnbarriered(this);
 #endif // ENABLE(DFG_JIT)
 }
 
-void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)
-{
-    CodeBlock* codeBlock =
-        bitwise_cast<CodeBlock*>(
-            bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_weakReferenceHarvester));
-    
-    codeBlock->propagateTransitions(NoLockingNecessary, visitor);
-    codeBlock->determineLiveness(NoLockingNecessary, visitor);
-}
-
 void CodeBlock::clearLLIntGetByIdCache(Instruction* instruction)
 {
     instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id);
@@ -2776,29 +1253,37 @@ void CodeBlock::clearLLIntGetByIdCache(Instruction* instruction)
 
 void CodeBlock::finalizeLLIntInlineCaches()
 {
-    Interpreter* interpreter = m_vm->interpreter;
+    VM& vm = *m_poisonedVM;
     const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
     for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
         Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
-        switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
-        case op_get_by_id:
-        case op_get_by_id_proto_load:
-        case op_get_by_id_unset: {
+        switch (Interpreter::getOpcodeID(curInstruction[0])) {
+        case op_get_by_id: {
             StructureID oldStructureID = curInstruction[4].u.structureID;
-            if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
+            if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
                 break;
             if (Options::verboseOSR())
                 dataLogF("Clearing LLInt property access.\n");
             clearLLIntGetByIdCache(curInstruction);
             break;
         }
+        case op_get_by_id_direct: {
+            StructureID oldStructureID = curInstruction[4].u.structureID;
+            if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
+                break;
+            if (Options::verboseOSR())
+                dataLogF("Clearing LLInt property access.\n");
+            curInstruction[4].u.pointer = nullptr;
+            curInstruction[5].u.pointer = nullptr;
+            break;
+        }
         case op_put_by_id: {
             StructureID oldStructureID = curInstruction[4].u.structureID;
             StructureID newStructureID = curInstruction[6].u.structureID;
             StructureChain* chain = curInstruction[7].u.structureChain.get();
-            if ((!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) &&
-                (!newStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(newStructureID))) &&
-                (!chain || Heap::isMarked(chain)))
+            if ((!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
+                && (!newStructureID || Heap::isMarked(vm.heap.structureIDTable().get(newStructureID)))
+                && (!chain || Heap::isMarked(chain)))
                 break;
             if (Options::verboseOSR())
                 dataLogF("Clearing LLInt put transition.\n");
@@ -2808,6 +1293,12 @@ void CodeBlock::finalizeLLIntInlineCaches()
             curInstruction[7].u.structureChain.clear();
             break;
         }
+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=166418
+        // We need to add optimizations for op_resolve_scope_for_hoisting_func_decl_in_eval to do link time scope resolution.
+        case op_resolve_scope_for_hoisting_func_decl_in_eval:
+            break;
+        case op_get_by_id_proto_load:
+        case op_get_by_id_unset:
         case op_get_array_length:
             break;
         case op_to_this:
@@ -2858,15 +1349,34 @@ void CodeBlock::finalizeLLIntInlineCaches()
             break;
         }
         default:
-            OpcodeID opcodeID = interpreter->getOpcodeID(curInstruction[0].u.opcode);
+            OpcodeID opcodeID = Interpreter::getOpcodeID(curInstruction[0]);
             ASSERT_WITH_MESSAGE_UNUSED(opcodeID, false, "Unhandled opcode in CodeBlock::finalizeUnconditionally, %s(%d) at bc %u", opcodeNames[opcodeID], opcodeID, propertyAccessInstructions[i]);
         }
     }
 
     // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
     // then cleared the cache without GCing in between.
-    m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
-        return !Heap::isMarked(pair.key);
+    m_llintGetByIdWatchpointMap.removeIf([&] (const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
+        auto clear = [&] () {
+            Instruction* instruction = std::get<1>(pair.key);
+            OpcodeID opcode = Interpreter::getOpcodeID(*instruction);
+            if (opcode == op_get_by_id_proto_load || opcode == op_get_by_id_unset) {
+                if (Options::verboseOSR())
+                    dataLogF("Clearing LLInt property access.\n");
+                clearLLIntGetByIdCache(instruction);
+            }
+            return true;
+        };
+
+        if (!Heap::isMarked(std::get<0>(pair.key)))
+            return clear();
+
+        for (const LLIntPrototypeLoadAdaptiveStructureWatchpoint* watchpoint : pair.value) {
+            if (!watchpoint->key().isStillLive())
+                return clear();
+        }
+
+        return false;
     });
 
     for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
@@ -2886,85 +1396,64 @@ void CodeBlock::finalizeBaselineJITInlineCaches()
     for (auto iter = callLinkInfosBegin(); !!iter; ++iter)
         (*iter)->visitWeak(*vm());
 
-    for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
+    for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
         StructureStubInfo& stubInfo = **iter;
         stubInfo.visitWeakReferences(this);
     }
 #endif
 }
 
-void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
+void CodeBlock::finalizeUnconditionally(VM&)
 {
-    CodeBlock* codeBlock = bitwise_cast<CodeBlock*>(
-        bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_unconditionalFinalizer));
+    updateAllPredictions();
     
-    codeBlock->updateAllPredictions();
-    
-    if (!Heap::isMarked(codeBlock)) {
-        if (codeBlock->shouldJettisonDueToWeakReference())
-            codeBlock->jettison(Profiler::JettisonDueToWeakReference);
-        else
-            codeBlock->jettison(Profiler::JettisonDueToOldAge);
-        return;
-    }
-
-    if (JITCode::couldBeInterpreted(codeBlock->jitType()))
-        codeBlock->finalizeLLIntInlineCaches();
-
-#if ENABLE(JIT)
-    if (!!codeBlock->jitCode())
-        codeBlock->finalizeBaselineJITInlineCaches();
-#endif
-}
+    if (JITCode::couldBeInterpreted(jitType()))
+        finalizeLLIntInlineCaches();
 
-void CodeBlock::getStubInfoMap(const ConcurrentJSLocker&, StubInfoMap& result)
-{
 #if ENABLE(JIT)
-    if (JITCode::isJIT(jitType()))
-        toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result);
-#else
-    UNUSED_PARAM(result);
+    if (!!jitCode())
+        finalizeBaselineJITInlineCaches();
 #endif
-}
-
-void CodeBlock::getStubInfoMap(StubInfoMap& result)
-{
-    ConcurrentJSLocker locker(m_lock);
-    getStubInfoMap(locker, result);
-}
 
-void CodeBlock::getCallLinkInfoMap(const ConcurrentJSLocker&, CallLinkInfoMap& result)
-{
-#if ENABLE(JIT)
-    if (JITCode::isJIT(jitType()))
-        toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result);
-#else
-    UNUSED_PARAM(result);
-#endif
-}
+    if (JITCode::isOptimizingJIT(jitType())) {
+        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
+        dfgCommon->recordedStatuses.finalize();
+    }
 
-void CodeBlock::getCallLinkInfoMap(CallLinkInfoMap& result)
-{
-    ConcurrentJSLocker locker(m_lock);
-    getCallLinkInfoMap(locker, result);
+    VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this);
 }
 
-void CodeBlock::getByValInfoMap(const ConcurrentJSLocker&, ByValInfoMap& result)
+void CodeBlock::getICStatusMap(const ConcurrentJSLocker&, ICStatusMap& result)
 {
 #if ENABLE(JIT)
     if (JITCode::isJIT(jitType())) {
-        for (auto* byValInfo : m_byValInfos)
-            result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo);
+        for (StructureStubInfo* stubInfo : m_stubInfos)
+            result.add(stubInfo->codeOrigin, ICStatus()).iterator->value.stubInfo = stubInfo;
+        for (CallLinkInfo* callLinkInfo : m_callLinkInfos)
+            result.add(callLinkInfo->codeOrigin(), ICStatus()).iterator->value.callLinkInfo = callLinkInfo;
+        for (ByValInfo* byValInfo : m_byValInfos)
+            result.add(CodeOrigin(byValInfo->bytecodeIndex), ICStatus()).iterator->value.byValInfo = byValInfo;
+        if (JITCode::isOptimizingJIT(jitType())) {
+            DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
+            for (auto& pair : dfgCommon->recordedStatuses.calls)
+                result.add(pair.first, ICStatus()).iterator->value.callStatus = pair.second.get();
+            for (auto& pair : dfgCommon->recordedStatuses.gets)
+                result.add(pair.first, ICStatus()).iterator->value.getStatus = pair.second.get();
+            for (auto& pair : dfgCommon->recordedStatuses.puts)
+                result.add(pair.first, ICStatus()).iterator->value.putStatus = pair.second.get();
+            for (auto& pair : dfgCommon->recordedStatuses.ins)
+                result.add(pair.first, ICStatus()).iterator->value.inStatus = pair.second.get();
+        }
     }
 #else
     UNUSED_PARAM(result);
 #endif
 }
 
-void CodeBlock::getByValInfoMap(ByValInfoMap& result)
+void CodeBlock::getICStatusMap(ICStatusMap& result)
 {
     ConcurrentJSLocker locker(m_lock);
-    getByValInfoMap(locker, result);
+    getICStatusMap(locker, result);
 }
 
 #if ENABLE(JIT)
@@ -2974,24 +1463,24 @@ StructureStubInfo* CodeBlock::addStubInfo(AccessType accessType)
     return m_stubInfos.add(accessType);
 }
 
-JITAddIC* CodeBlock::addJITAddIC(ArithProfile* arithProfile)
+JITAddIC* CodeBlock::addJITAddIC(ArithProfile* arithProfile, Instruction* instruction)
 {
-    return m_addICs.add(arithProfile);
+    return m_addICs.add(arithProfile, instruction);
 }
 
-JITMulIC* CodeBlock::addJITMulIC(ArithProfile* arithProfile)
+JITMulIC* CodeBlock::addJITMulIC(ArithProfile* arithProfile, Instruction* instruction)
 {
-    return m_mulICs.add(arithProfile);
+    return m_mulICs.add(arithProfile, instruction);
 }
 
-JITSubIC* CodeBlock::addJITSubIC(ArithProfile* arithProfile)
+JITSubIC* CodeBlock::addJITSubIC(ArithProfile* arithProfile, Instruction* instruction)
 {
-    return m_subICs.add(arithProfile);
+    return m_subICs.add(arithProfile, instruction);
 }
 
-JITNegIC* CodeBlock::addJITNegIC(ArithProfile* arithProfile)
+JITNegIC* CodeBlock::addJITNegIC(ArithProfile* arithProfile, Instruction* instruction)
 {
-    return m_negICs.add(arithProfile);
+    return m_negICs.add(arithProfile, instruction);
 }
 
 StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
@@ -3031,7 +1520,7 @@ void CodeBlock::resetJITData()
     
     // We can clear these because no other thread will have references to any stub infos, call
     // link infos, or by val infos if we don't have JIT code. Attempts to query these data
-    // structures using the concurrent API (getStubInfoMap and friends) will return nothing if we
+    // structures using the concurrent API (getICStatusMap and friends) will return nothing if we
     // don't have JIT code.
     m_stubInfos.clear();
     m_callLinkInfos.clear();
@@ -3068,7 +1557,7 @@ void CodeBlock::stronglyVisitStrongReferences(const ConcurrentJSLocker& locker,
     UNUSED_PARAM(locker);
     
     visitor.append(m_globalObject);
-    visitor.append(m_ownerExecutable);
+    visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked.
     visitor.append(m_unlinkedCode);
     if (m_rareData)
         m_rareData->m_directEvalCodeCache.visitAggregate(visitor);
@@ -3135,16 +1624,26 @@ CodeBlock* CodeBlock::baselineAlternative()
 CodeBlock* CodeBlock::baselineVersion()
 {
 #if ENABLE(JIT)
-    if (JITCode::isBaselineCode(jitType()))
+    JITCode::JITType selfJITType = jitType();
+    if (JITCode::isBaselineCode(selfJITType))
         return this;
     CodeBlock* result = replacement();
     if (!result) {
-        // This can happen if we're creating the original CodeBlock for an executable.
-        // Assume that we're the baseline CodeBlock.
-        RELEASE_ASSERT(jitType() == JITCode::None);
-        return this;
+        if (JITCode::isOptimizingJIT(selfJITType)) {
+            // The replacement can be null if we've had a memory clean up and the executable
+            // has been purged of its codeBlocks (see ExecutableBase::clearCode()). Regardless,
+            // the current codeBlock is still live on the stack, and as an optimizing JIT
+            // codeBlock, it will keep its baselineAlternative() alive for us to fetch below.
+            result = this;
+        } else {
+            // This can happen if we're creating the original CodeBlock for an executable.
+            // Assume that we're the baseline CodeBlock.
+            RELEASE_ASSERT(selfJITType == JITCode::None);
+            return this;
+        }
     }
     result = result->baselineAlternative();
+    ASSERT(result);
     return result;
 #else
     return this;
@@ -3154,7 +1653,8 @@ CodeBlock* CodeBlock::baselineVersion()
 #if ENABLE(JIT)
 bool CodeBlock::hasOptimizedReplacement(JITCode::JITType typeToReplace)
 {
-    return JITCode::isHigherTier(replacement()->jitType(), typeToReplace);
+    CodeBlock* replacement = this->replacement();
+    return replacement && JITCode::isHigherTier(replacement->jitType(), typeToReplace);
 }
 
 bool CodeBlock::hasOptimizedReplacement()
@@ -3193,6 +1693,43 @@ CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex origina
 #endif
 }
 
+void CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow(unsigned bytecodeOffset)
+{
+    ASSERT(Interpreter::getOpcodeID(m_instructions[bytecodeOffset]) == op_catch);
+    BytecodeLivenessAnalysis& bytecodeLiveness = livenessAnalysis();
+
+    // We get the live-out set of variables at op_catch, not the live-in. This
+    // is because the variables that the op_catch defines might be dead, and
+    // we can avoid profiling them and extracting them when doing OSR entry
+    // into the DFG.
+    FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(this, bytecodeOffset + OPCODE_LENGTH(op_catch));
+    Vector<VirtualRegister> liveOperands;
+    liveOperands.reserveInitialCapacity(liveLocals.bitCount());
+    liveLocals.forEachSetBit([&] (unsigned liveLocal) {
+        liveOperands.append(virtualRegisterForLocal(liveLocal));
+    });
+
+    for (int i = 0; i < numParameters(); ++i)
+        liveOperands.append(virtualRegisterForArgument(i));
+
+    auto profiles = std::make_unique<ValueProfileAndOperandBuffer>(liveOperands.size());
+    RELEASE_ASSERT(profiles->m_size == liveOperands.size());
+    for (unsigned i = 0; i < profiles->m_size; ++i)
+        profiles->m_buffer.get()[i].m_operand = liveOperands[i].offset();
+
+    // The compiler thread will read this pointer value and then proceed to dereference it
+    // if it is not null. We need to make sure all above stores happen before this store so
+    // the compiler thread reads fully initialized data.
+    WTF::storeStoreFence(); 
+
+    m_instructions[bytecodeOffset + 3].u.pointer = profiles.get();
+
+    {
+        ConcurrentJSLocker locker(m_lock);
+        m_catchProfiles.append(WTFMove(profiles));
+    }
+}
+
 void CodeBlock::removeExceptionHandlerForCallSite(CallSiteIndex callSiteIndex)
 {
     RELEASE_ASSERT(m_rareData);
@@ -3236,11 +1773,10 @@ void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& d
 
 bool CodeBlock::hasOpDebugForLineAndColumn(unsigned line, unsigned column)
 {
-    Interpreter* interpreter = vm()->interpreter;
     const Instruction* begin = instructions().begin();
     const Instruction* end = instructions().end();
     for (const Instruction* it = begin; it != end;) {
-        OpcodeID opcodeID = interpreter->getOpcodeID(it->u.opcode);
+        OpcodeID opcodeID = Interpreter::getOpcodeID(*it);
         if (opcodeID == op_debug) {
             unsigned bytecodeOffset = it - begin;
             int unused;
@@ -3399,6 +1935,7 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
     }
 #endif // ENABLE(DFG_JIT)
 
+    VM& vm = *m_poisonedVM;
     DeferGCForAWhile deferGC(*heap());
     
     // We want to accomplish two things here:
@@ -3408,13 +1945,14 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
 
 #if ENABLE(DFG_JIT)
     if (reason != Profiler::JettisonDueToOldAge) {
-        if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
+        Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get();
+        if (UNLIKELY(compilation))
             compilation->setJettisonReason(reason, detail);
         
         // This accomplishes (1), and does its own book-keeping about whether it has already happened.
         if (!jitCode()->dfgCommon()->invalidate()) {
             // We've already been invalidated.
-            RELEASE_ASSERT(this != replacement() || (m_vm->heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable())));
+            RELEASE_ASSERT(this != replacement() || (vm.heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable())));
             return;
         }
     }
@@ -3440,18 +1978,17 @@ void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mod
     if (alternative())
         alternative()->optimizeAfterWarmUp();
 
-    if (reason != Profiler::JettisonDueToOldAge)
+    if (reason != Profiler::JettisonDueToOldAge && reason != Profiler::JettisonDueToVMTraps)
         tallyFrequentExitSites();
 #endif // ENABLE(DFG_JIT)
 
     // Jettison can happen during GC. We don't want to install code to a dead executable
     // because that would add a dead object to the remembered set.
-    if (m_vm->heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable()))
+    if (vm.heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable()))
         return;
 
     // This accomplishes (2).
-    ownerScriptExecutable()->installCode(
-        m_globalObject->vm(), alternative(), codeType(), specializationKind());
+    ownerScriptExecutable()->installCode(vm, alternative(), codeType(), specializationKind());
 
 #if ENABLE(DFG_JIT)
     if (DFG::shouldDumpDisassembly())
@@ -3580,7 +2117,7 @@ void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
     }
     
     if (callerCodeBlock->capabilityLevelState() == DFG::CapabilityLevelNotSet) {
-        dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
+        dataLog("In call from ", FullCodeOrigin(callerCodeBlock, callerFrame->codeOrigin()), " to ", *this, ": caller's DFG capability level is not set.\n");
         CRASH();
     }
     
@@ -3647,7 +2184,8 @@ unsigned CodeBlock::numberOfDFGCompiles()
             return 1000000;
         return (m_hasBeenCompiledWithFTL ? 1 : 0) + m_reoptimizationRetryCounter;
     }
-    return (JITCode::isOptimizingJIT(replacement()->jitType()) ? 1 : 0) + m_reoptimizationRetryCounter;
+    CodeBlock* replacement = this->replacement();
+    return ((replacement && JITCode::isOptimizingJIT(replacement->jitType())) ? 1 : 0) + m_reoptimizationRetryCounter;
 }
 
 int32_t CodeBlock::codeTypeThresholdMultiplier() const
@@ -3773,6 +2311,55 @@ bool CodeBlock::checkIfOptimizationThresholdReached()
     return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
 }
 
+#if ENABLE(DFG_JIT)
+auto CodeBlock::updateOSRExitCounterAndCheckIfNeedToReoptimize(DFG::OSRExitState& exitState) -> OptimizeAction
+{
+    DFG::OSRExitBase& exit = exitState.exit;
+    if (!exitKindMayJettison(exit.m_kind)) {
+        // FIXME: We may want to notice that we're frequently exiting
+        // at an op_catch that we didn't compile an entrypoint for, and
+        // then trigger a reoptimization of this CodeBlock:
+        // https://bugs.webkit.org/show_bug.cgi?id=175842
+        return OptimizeAction::None;
+    }
+
+    exit.m_count++;
+    m_osrExitCounter++;
+
+    CodeBlock* baselineCodeBlock = exitState.baselineCodeBlock;
+    ASSERT(baselineCodeBlock == baselineAlternative());
+    if (UNLIKELY(baselineCodeBlock->jitExecuteCounter().hasCrossedThreshold()))
+        return OptimizeAction::ReoptimizeNow;
+
+    // We want to figure out if there's a possibility that we're in a loop. For the outermost
+    // code block in the inline stack, we handle this appropriately by having the loop OSR trigger
+    // check the exit count of the replacement of the CodeBlock from which we are OSRing. The
+    // problem is the inlined functions, which might also have loops, but whose baseline versions
+    // don't know where to look for the exit count. Figure out if those loops are severe enough
+    // that we had tried to OSR enter. If so, then we should use the loop reoptimization trigger.
+    // Otherwise, we should use the normal reoptimization trigger.
+
+    bool didTryToEnterInLoop = false;
+    for (InlineCallFrame* inlineCallFrame = exit.m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
+        if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
+            didTryToEnterInLoop = true;
+            break;
+        }
+    }
+
+    uint32_t exitCountThreshold = didTryToEnterInLoop
+        ? exitCountThresholdForReoptimizationFromLoop()
+        : exitCountThresholdForReoptimization();
+
+    if (m_osrExitCounter > exitCountThreshold)
+        return OptimizeAction::ReoptimizeNow;
+
+    // Too few fails. Adjust the execution counter such that the target is to only optimize after a while.
+    baselineCodeBlock->m_jitExecuteCounter.setNewThresholdForOSRExit(exitState.activeThreshold, exitState.memoryUsageAdjustedThreshold);
+    return OptimizeAction::None;
+}
+#endif
+
 void CodeBlock::optimizeNextInvocation()
 {
     if (Options::verboseOSR())
@@ -3833,19 +2420,20 @@ void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResu
         RELEASE_ASSERT_NOT_REACHED();
     }
     
-    CodeBlock* theReplacement = replacement();
-    if ((result == CompilationSuccessful) != (theReplacement != this)) {
+    CodeBlock* replacement = this->replacement();
+    bool hasReplacement = (replacement && replacement != this);
+    if ((result == CompilationSuccessful) != hasReplacement) {
         dataLog(*this, ": we have result = ", result, " but ");
-        if (theReplacement == this)
+        if (replacement == this)
             dataLog("we are our own replacement.\n");
         else
-            dataLog("our replacement is ", pointerDump(theReplacement), "\n");
+            dataLog("our replacement is ", pointerDump(replacement), "\n");
         RELEASE_ASSERT_NOT_REACHED();
     }
     
     switch (result) {
     case CompilationSuccessful:
-        RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()->jitType()));
+        RELEASE_ASSERT(replacement && JITCode::isOptimizingJIT(replacement->jitType()));
         optimizeNextInvocation();
         return;
     case CompilationFailed:
@@ -3976,22 +2564,29 @@ const Identifier& CodeBlock::identifier(int index) const
 void CodeBlock::updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
 {
     ConcurrentJSLocker locker(m_lock);
-    
+
     numberOfLiveNonArgumentValueProfiles = 0;
     numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
+
     for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
-        ValueProfile* profile = getFromAllValueProfiles(i);
-        unsigned numSamples = profile->totalNumberOfSamples();
+        ValueProfile& profile = getFromAllValueProfiles(i);
+        unsigned numSamples = profile.totalNumberOfSamples();
         if (numSamples > ValueProfile::numberOfBuckets)
             numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
         numberOfSamplesInProfiles += numSamples;
-        if (profile->m_bytecodeOffset < 0) {
-            profile->computeUpdatedPrediction(locker);
+        if (profile.m_bytecodeOffset < 0) {
+            profile.computeUpdatedPrediction(locker);
             continue;
         }
-        if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
+        if (profile.numberOfSamples() || profile.m_prediction != SpecNone)
             numberOfLiveNonArgumentValueProfiles++;
-        profile->computeUpdatedPrediction(locker);
+        profile.computeUpdatedPrediction(locker);
+    }
+
+    for (auto& profileBucket : m_catchProfiles) {
+        profileBucket->forEach([&] (ValueProfileAndOperand& profile) {
+            profile.m_profile.computeUpdatedPrediction(locker);
+        });
     }
     
 #if ENABLE(DFG_JIT)
@@ -4014,7 +2609,7 @@ void CodeBlock::updateAllArrayPredictions()
     
     // Don't count these either, for similar reasons.
     for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
-        m_arrayAllocationProfiles[i].updateIndexingType();
+        m_arrayAllocationProfiles[i].updateProfile();
 }
 
 void CodeBlock::updateAllPredictions()
@@ -4099,17 +2694,17 @@ void CodeBlock::dumpValueProfiles()
 {
     dataLog("ValueProfile for ", *this, ":\n");
     for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
-        ValueProfile* profile = getFromAllValueProfiles(i);
-        if (profile->m_bytecodeOffset < 0) {
-            ASSERT(profile->m_bytecodeOffset == -1);
+        ValueProfile& profile = getFromAllValueProfiles(i);
+        if (profile.m_bytecodeOffset < 0) {
+            ASSERT(profile.m_bytecodeOffset == -1);
             dataLogF("   arg = %u: ", i);
         } else
-            dataLogF("   bc = %d: ", profile->m_bytecodeOffset);
-        if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) {
+            dataLogF("   bc = %d: ", profile.m_bytecodeOffset);
+        if (!profile.numberOfSamples() && profile.m_prediction == SpecNone) {
             dataLogF("<empty>\n");
             continue;
         }
-        profile->dump(WTF::dataFile());
+        profile.dump(WTF::dataFile());
         dataLogF("\n");
     }
     dataLog("RareCaseProfile for ", *this, ":\n");
@@ -4150,18 +2745,19 @@ int CodeBlock::stackPointerOffset()
 
 size_t CodeBlock::predictedMachineCodeSize()
 {
-    // This will be called from CodeBlock::CodeBlock before either m_vm or the
+    VM* vm = m_poisonedVM.unpoisoned();
+    // This will be called from CodeBlock::CodeBlock before either m_poisonedVM or the
     // instructions have been initialized. It's OK to return 0 because what will really
     // matter is the recomputation of this value when the slow path is triggered.
-    if (!m_vm)
+    if (!vm)
         return 0;
     
-    if (!*m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
+    if (!*vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
         return 0; // It's as good of a prediction as we'll get.
     
     // Be conservative: return a size that will be an overestimation 84% of the time.
-    double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT->mean() +
-        m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT->standardDeviation();
+    double multiplier = vm->machineCodeBytesPerBytecodeWordForBaselineJIT->mean() +
+        vm->machineCodeBytesPerBytecodeWordForBaselineJIT->standardDeviation();
     
     // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
     // here is OK, since this whole method is just a heuristic.
@@ -4180,31 +2776,6 @@ size_t CodeBlock::predictedMachineCodeSize()
     return static_cast<size_t>(doubleResult);
 }
 
-bool CodeBlock::usesOpcode(OpcodeID opcodeID)
-{
-    Interpreter* interpreter = vm()->interpreter;
-    Instruction* instructionsBegin = instructions().begin();
-    unsigned instructionCount = instructions().size();
-    
-    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
-        switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
-#define DEFINE_OP(curOpcode, length)        \
-        case curOpcode:                     \
-            if (curOpcode == opcodeID)      \
-                return true;                \
-            bytecodeOffset += length;       \
-            break;
-            FOR_EACH_OPCODE_ID(DEFINE_OP)
-#undef DEFINE_OP
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-    }
-    
-    return false;
-}
-
 String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
 {
     for (auto& constantRegister : m_constantRegisters) {
@@ -4223,25 +2794,33 @@ String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
         }
     }
     if (virtualRegister == thisRegister())
-        return ASCIILiteral("this");
+        return "this"_s;
     if (virtualRegister.isArgument())
         return String::format("arguments[%3d]", virtualRegister.toArgument());
 
     return "";
 }
 
-ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
+ValueProfile* CodeBlock::tryGetValueProfileForBytecodeOffset(int bytecodeOffset)
+{
+    return tryBinarySearch<ValueProfile, int>(
+        m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
+        getValueProfileBytecodeOffset<ValueProfile>);
+}
+
+ValueProfile& CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
 {
-    OpcodeID opcodeID = m_vm->interpreter->getOpcodeID(instructions()[bytecodeOffset].u.opcode);
+    OpcodeID opcodeID = Interpreter::getOpcodeID(instructions()[bytecodeOffset]);
     unsigned length = opcodeLength(opcodeID);
-    return instructions()[bytecodeOffset + length - 1].u.profile;
+    ASSERT(!!tryGetValueProfileForBytecodeOffset(bytecodeOffset));
+    return *instructions()[bytecodeOffset + length - 1].u.profile;
 }
 
 void CodeBlock::validate()
 {
     BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
     
-    FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
+    FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(this, 0);
     
     if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) {
         beginValidationDidFail();
@@ -4261,6 +2840,31 @@ void CodeBlock::validate()
             endValidationDidFail();
         }
     }
+
+    for (unsigned i = 0; i + 1 < numberOfValueProfiles(); ++i) {
+        if (valueProfile(i).m_bytecodeOffset > valueProfile(i + 1).m_bytecodeOffset) {
+            beginValidationDidFail();
+            dataLog("    Value profiles are not sorted.\n");
+            endValidationDidFail();
+        }
+    }
+     
+    for (unsigned bytecodeOffset = 0; bytecodeOffset < m_instructions.size(); ) {
+        OpcodeID opcode = Interpreter::getOpcodeID(m_instructions[bytecodeOffset]);
+        if (!!baselineAlternative()->handlerForBytecodeOffset(bytecodeOffset)) {
+            if (opcode == op_catch || opcode == op_enter) {
+                // op_catch/op_enter logically represent an entrypoint. Entrypoints are not allowed to be
+                // inside of a try block because they are responsible for bootstrapping state. And they
+                // are never allowed throw an exception because of this. We rely on this when compiling
+                // in the DFG. Because an entrypoint never throws, the bytecode generator will never
+                // allow once inside a try block.
+                beginValidationDidFail();
+                dataLog("    entrypoint not allowed inside a try block.");
+                endValidationDidFail();
+            }
+        }
+        bytecodeOffset += opcodeLength(opcode);
+    }
 }
 
 void CodeBlock::beginValidationDidFail()
@@ -4316,12 +2920,12 @@ unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
 
 ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset)
 {
-    return arithProfileForPC(instructions().begin() + bytecodeOffset);
+    return arithProfileForPC(&instructions()[bytecodeOffset]);
 }
 
 ArithProfile* CodeBlock::arithProfileForPC(Instruction* pc)
 {
-    auto opcodeID = vm()->interpreter->getOpcodeID(pc[0].u.opcode);
+    auto opcodeID = Interpreter::getOpcodeID(pc[0]);
     switch (opcodeID) {
     case op_negate:
         return bitwise_cast<ArithProfile*>(&pc[3].u.operand);
@@ -4368,12 +2972,12 @@ void CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler(RefCountedArray
         // Because op_profile_control_flow is emitted at the beginning of every basic block, finding 
         // the next op_profile_control_flow will give us the text range of a single basic block.
         size_t startIdx = bytecodeOffsets[i];
-        RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[startIdx].u.opcode) == op_profile_control_flow);
+        RELEASE_ASSERT(Interpreter::getOpcodeID(instructions[startIdx]) == op_profile_control_flow);
         int basicBlockStartOffset = instructions[startIdx + 1].u.operand;
         int basicBlockEndOffset;
         if (i + 1 < offsetsLength) {
             size_t endIdx = bytecodeOffsets[i + 1];
-            RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[endIdx].u.opcode) == op_profile_control_flow);
+            RELEASE_ASSERT(Interpreter::getOpcodeID(instructions[endIdx]) == op_profile_control_flow);
             basicBlockEndOffset = instructions[endIdx + 1].u.operand - 1;
         } else {
             basicBlockEndOffset = m_sourceOffset + ownerScriptExecutable()->source().length() - 1; // Offset before the closing brace.
@@ -4441,7 +3045,7 @@ std::optional<CodeOrigin> CodeBlock::findPC(void* pc)
             return codeOrigin;
     }
 
-    for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
+    for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
         StructureStubInfo* stub = *iter;
         if (stub->containsPC(pc))
             return std::optional<CodeOrigin>(stub->codeOrigin);
@@ -4463,7 +3067,7 @@ std::optional<unsigned> CodeBlock::bytecodeOffsetFromCallSiteIndex(CallSiteIndex
         bytecodeOffset = callSiteIndex.bits();
 #else
         Instruction* instruction = bitwise_cast<Instruction*>(callSiteIndex.bits());
-        bytecodeOffset = instruction - instructions().begin();
+        bytecodeOffset = this->bytecodeOffset(instruction);
 #endif
     } else if (jitType == JITCode::DFGJIT || jitType == JITCode::FTLJIT) {
 #if ENABLE(DFG_JIT)
@@ -4502,6 +3106,37 @@ void CodeBlock::jitSoon()
     m_llintExecuteCounter.setNewThreshold(thresholdForJIT(Options::thresholdForJITSoon()), this);
 }
 
+bool CodeBlock::hasInstalledVMTrapBreakpoints() const
+{
+#if ENABLE(SIGNAL_BASED_VM_TRAPS)
+    // This function may be called from a signal handler. We need to be
+    // careful to not call anything that is not signal handler safe, e.g.
+    // we should not perturb the refCount of m_jitCode.
+    if (!JITCode::isOptimizingJIT(jitType()))
+        return false;
+    return m_jitCode->dfgCommon()->hasInstalledVMTrapsBreakpoints();
+#else
+    return false;
+#endif
+}
+
+bool CodeBlock::installVMTrapBreakpoints()
+{
+#if ENABLE(SIGNAL_BASED_VM_TRAPS)
+    // This function may be called from a signal handler. We need to be
+    // careful to not call anything that is not signal handler safe, e.g.
+    // we should not perturb the refCount of m_jitCode.
+    if (!JITCode::isOptimizingJIT(jitType()))
+        return false;
+    auto& commonData = *m_jitCode->dfgCommon();
+    commonData.installVMTrapBreakpoints(this);
+    return true;
+#else
+    UNREACHABLE_FOR_PLATFORM();
+    return false;
+#endif
+}
+
 void CodeBlock::dumpMathICStats()
 {
 #if ENABLE(MATH_IC_STATS)
@@ -4534,8 +3169,6 @@ void CodeBlock::dumpMathICStats()
             numSubs++;
             totalSubSize += subIC->codeSize();
         }
-
-        return false;
     };
     heap()->forEachCodeBlock(countICs);
 
@@ -4559,16 +3192,22 @@ void CodeBlock::dumpMathICStats()
 #endif
 }
 
-BytecodeLivenessAnalysis& CodeBlock::livenessAnalysisSlow()
+void setPrinter(Printer::PrintRecord& record, CodeBlock* codeBlock)
 {
-    std::unique_ptr<BytecodeLivenessAnalysis> analysis = std::make_unique<BytecodeLivenessAnalysis>(this);
-    {
-        ConcurrentJSLocker locker(m_lock);
-        if (!m_livenessAnalysis)
-            m_livenessAnalysis = WTFMove(analysis);
-        return *m_livenessAnalysis;
-    }
+    Printer::setPrinter(record, toCString(codeBlock));
 }
 
-
 } // namespace JSC
+
+namespace WTF {
+    
+void printInternal(PrintStream& out, JSC::CodeBlock* codeBlock)
+{
+    if (UNLIKELY(!codeBlock)) {
+        out.print("<null codeBlock>");
+        return;
+    }
+    out.print(*codeBlock);
+}
+    
+} // namespace WTF