void
wasm::ToggleProfiling(const Code& code, const CallSite& callSite, bool enabled)
{
    if (callSite.kind() != CallSite::FuncDef)
        return;

    uint8_t* callerRetAddr = code.segment().base() + callSite.returnAddressOffset();

#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
    void* callee = X86Encoding::GetRel32Target(callerRetAddr);
#elif defined(JS_CODEGEN_ARM)
    uint8_t* caller = callerRetAddr - 4;
    Instruction* callerInsn = reinterpret_cast<Instruction*>(caller);
    BOffImm calleeOffset;
    callerInsn->as<InstBLImm>()->extractImm(&calleeOffset);
    void* callee = calleeOffset.getDest(callerInsn);
#elif defined(JS_CODEGEN_ARM64)
    MOZ_CRASH();
    void* callee = nullptr;
    (void)callerRetAddr;
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
    uint8_t* caller = callerRetAddr - 2 * sizeof(uint32_t);
    InstImm* callerInsn = reinterpret_cast<InstImm*>(caller);
    BOffImm16 calleeOffset;
    callerInsn->extractImm16(&calleeOffset);
    void* callee = calleeOffset.getDest(reinterpret_cast<Instruction*>(caller));
#elif defined(JS_CODEGEN_NONE)
    MOZ_CRASH();
    void* callee = nullptr;
#else
# error "Missing architecture"
#endif

    const CodeRange* codeRange = code.lookupRange(callee);
    if (!codeRange->isFunction())
        return;

    uint8_t* from = code.segment().base() + codeRange->funcNonProfilingEntry();
    uint8_t* to = code.segment().base() + codeRange->funcProfilingEntry();
    if (!enabled)
        Swap(from, to);

    MOZ_ASSERT(callee == from);

#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
    X86Encoding::SetRel32(callerRetAddr, to);
#elif defined(JS_CODEGEN_ARM)
    new (caller) InstBLImm(BOffImm(to - caller), Assembler::Always);
#elif defined(JS_CODEGEN_ARM64)
    (void)to;
    MOZ_CRASH();
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
    new (caller) InstImm(op_regimm, zero, rt_bgezal, BOffImm16(to - caller));
#elif defined(JS_CODEGEN_NONE)
    MOZ_CRASH();
#else
# error "Missing architecture"
#endif
}
// Patch all internal (asm.js->asm.js) callsites to call the profiling
// prologues:
void
wasm::EnableProfilingPrologue(const Module& module, const CallSite& callSite, bool enabled)
{
    if (callSite.kind() != CallSite::Relative)
        return;

    uint8_t* callerRetAddr = module.code() + callSite.returnAddressOffset();

#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
    void* callee = X86Encoding::GetRel32Target(callerRetAddr);
#elif defined(JS_CODEGEN_ARM)
    uint8_t* caller = callerRetAddr - 4;
    Instruction* callerInsn = reinterpret_cast<Instruction*>(caller);
    BOffImm calleeOffset;
    callerInsn->as<InstBLImm>()->extractImm(&calleeOffset);
    void* callee = calleeOffset.getDest(callerInsn);
#elif defined(JS_CODEGEN_ARM64)
    MOZ_CRASH();
    void* callee = nullptr;
    (void)callerRetAddr;
#elif defined(JS_CODEGEN_MIPS32)
    Instruction* instr = (Instruction*)(callerRetAddr - 4 * sizeof(uint32_t));
    void* callee = (void*)Assembler::ExtractLuiOriValue(instr, instr->next());
#elif defined(JS_CODEGEN_MIPS64)
    Instruction* instr = (Instruction*)(callerRetAddr - 6 * sizeof(uint32_t));
    void* callee = (void*)Assembler::ExtractLoad64Value(instr);
#elif defined(JS_CODEGEN_NONE)
    MOZ_CRASH();
    void* callee = nullptr;
#else
# error "Missing architecture"
#endif

    const CodeRange* codeRange = module.lookupCodeRange(callee);
    if (!codeRange->isFunction())
        return;

    uint8_t* from = module.code() + codeRange->funcNonProfilingEntry();
    uint8_t* to = module.code() + codeRange->funcProfilingEntry();
    if (!enabled)
        Swap(from, to);

    MOZ_ASSERT(callee == from);

#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
    X86Encoding::SetRel32(callerRetAddr, to);
#elif defined(JS_CODEGEN_ARM)
    new (caller) InstBLImm(BOffImm(to - caller), Assembler::Always);
#elif defined(JS_CODEGEN_ARM64)
    (void)to;
    MOZ_CRASH();
#elif defined(JS_CODEGEN_MIPS32)
    Assembler::WriteLuiOriInstructions(instr, instr->next(),
                                       ScratchRegister, (uint32_t)to);
    instr[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
#elif defined(JS_CODEGEN_MIPS64)
    Assembler::WriteLoad64Instructions(instr, ScratchRegister, (uint64_t)to);
    instr[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
#elif defined(JS_CODEGEN_NONE)
    MOZ_CRASH();
#else
# error "Missing architecture"
#endif
}