void wasm::ToggleProfiling(const Code& code, const CodeRange& codeRange, bool enabled) { if (!codeRange.isFunction()) return; uint8_t* codeBase = code.segment().base(); uint8_t* profilingEntry = codeBase + codeRange.funcProfilingEntry(); uint8_t* tableProfilingJump = codeBase + codeRange.funcTableProfilingJump(); uint8_t* profilingJump = codeBase + codeRange.funcProfilingJump(); uint8_t* profilingEpilogue = codeBase + codeRange.funcProfilingEpilogue(); if (enabled) { MacroAssembler::patchNopToNearJump(tableProfilingJump, profilingEntry); MacroAssembler::patchNopToNearJump(profilingJump, profilingEpilogue); } else { MacroAssembler::patchNearJumpToNop(tableProfilingJump); MacroAssembler::patchNearJumpToNop(profilingJump); } }
// Replace all the nops in all the epilogues of asm.js functions with jumps // to the profiling epilogues. void wasm::EnableProfilingEpilogue(const Module& module, const CodeRange& codeRange, bool enabled) { if (!codeRange.isFunction()) return; uint8_t* jump = module.code() + codeRange.functionProfilingJump(); uint8_t* profilingEpilogue = module.code() + codeRange.funcProfilingEpilogue(); #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) // An unconditional jump with a 1 byte offset immediate has the opcode // 0x90. The offset is relative to the address of the instruction after // the jump. 0x66 0x90 is the canonical two-byte nop. ptrdiff_t jumpImmediate = profilingEpilogue - jump - 2; MOZ_ASSERT(jumpImmediate > 0 && jumpImmediate <= 127); if (enabled) { MOZ_ASSERT(jump[0] == 0x66); MOZ_ASSERT(jump[1] == 0x90); jump[0] = 0xeb; jump[1] = jumpImmediate; } else { MOZ_ASSERT(jump[0] == 0xeb); MOZ_ASSERT(jump[1] == jumpImmediate); jump[0] = 0x66; jump[1] = 0x90; } #elif defined(JS_CODEGEN_ARM) if (enabled) { MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>()); new (jump) InstBImm(BOffImm(profilingEpilogue - jump), Assembler::Always); } else { MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstBImm>()); new (jump) InstNOP(); } #elif defined(JS_CODEGEN_ARM64) (void)jump; (void)profilingEpilogue; MOZ_CRASH(); #elif defined(JS_CODEGEN_MIPS32) Instruction* instr = (Instruction*)jump; if (enabled) { Assembler::WriteLuiOriInstructions(instr, instr->next(), ScratchRegister, (uint32_t)profilingEpilogue); instr[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr); } else { for (unsigned i = 0; i < 3; i++) instr[i].makeNop(); } #elif defined(JS_CODEGEN_MIPS64) Instruction* instr = (Instruction*)jump; if (enabled) { Assembler::WriteLoad64Instructions(instr, ScratchRegister, (uint64_t)profilingEpilogue); instr[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr); } else { for (unsigned i = 0; i < 5; i++) instr[i].makeNop(); } #elif defined(JS_CODEGEN_NONE) MOZ_CRASH(); #else # error "Missing architecture" #endif }