static void StaticallyLink(CodeSegment& cs, const LinkData& linkData, ExclusiveContext* cx) { for (LinkData::InternalLink link : linkData.internalLinks) { uint8_t* patchAt = cs.code() + link.patchAtOffset; void* target = cs.code() + link.targetOffset; if (link.isRawPointerPatch()) *(void**)(patchAt) = target; else Assembler::PatchInstructionImmediate(patchAt, PatchedImmPtr(target)); } for (auto imm : MakeEnumeratedRange(SymbolicAddress::Limit)) { const Uint32Vector& offsets = linkData.symbolicLinks[imm]; for (size_t i = 0; i < offsets.length(); i++) { uint8_t* patchAt = cs.code() + offsets[i]; void* target = AddressOf(imm, cx); Assembler::PatchDataWithValueCheck(CodeLocationLabel(patchAt), PatchedImmPtr(target), PatchedImmPtr((void*)-1)); } } // These constants are logically part of the code: *(double*)(cs.globalData() + NaN64GlobalDataOffset) = GenericNaN(); *(float*)(cs.globalData() + NaN32GlobalDataOffset) = GenericNaN(); }
static void SpecializeToMemory(CodeSegment& cs, const Metadata& metadata, HandleWasmMemoryObject memory) { for (const BoundsCheck& check : metadata.boundsChecks) Assembler::UpdateBoundsCheck(check.patchAt(cs.code()), memory->buffer().byteLength()); #if defined(JS_CODEGEN_X86) uint8_t* base = memory->buffer().dataPointerEither().unwrap(); for (const MemoryAccess& access : metadata.memoryAccesses) { // Patch memory pointer immediate. void* addr = access.patchMemoryPtrImmAt(cs.code()); uint32_t disp = reinterpret_cast<uint32_t>(X86Encoding::GetPointer(addr)); MOZ_ASSERT(disp <= INT32_MAX); X86Encoding::SetPointer(addr, (void*)(base + disp)); } #endif }
bool Module::instantiateTable(JSContext* cx, const CodeSegment& cs, SharedTableVector* tables) const { for (const TableDesc& tableDesc : metadata_->tables) { SharedTable table = Table::create(cx, tableDesc.kind, tableDesc.length); if (!table || !tables->emplaceBack(table)) return false; for (size_t i = 0; i < table->length(); i++) table->array()[i] = cs.badIndirectCallCode(); } for (const ElemSegment& seg : elemSegments_) { SharedTable& table = (*tables)[seg.tableIndex]; MOZ_ASSERT(seg.offset + seg.elems.length() <= table->length()); for (size_t i = 0; i < seg.elems.length(); i++) table->array()[seg.offset + i] = cs.code() + seg.elems[i]; } return true; }
static bool SendCodeRangesToProfiler(JSContext* cx, CodeSegment& cs, const Bytes& bytecode, const Metadata& metadata) { bool enabled = false; #ifdef JS_ION_PERF enabled |= PerfFuncEnabled(); #endif #ifdef MOZ_VTUNE enabled |= IsVTuneProfilingActive(); #endif if (!enabled) return true; for (const CodeRange& codeRange : metadata.codeRanges) { if (!codeRange.isFunction()) continue; uintptr_t start = uintptr_t(cs.code() + codeRange.begin()); uintptr_t end = uintptr_t(cs.code() + codeRange.end()); uintptr_t size = end - start; TwoByteName name(cx); if (!metadata.getFuncName(cx, &bytecode, codeRange.funcIndex(), &name)) return false; UniqueChars chars( (char*)JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, name.begin(), name.length()).get()); if (!chars) return false; // Avoid "unused" warnings (void)start; (void)size; #ifdef JS_ION_PERF if (PerfFuncEnabled()) { const char* file = metadata.filename.get(); unsigned line = codeRange.funcLineOrBytecode(); unsigned column = 0; writePerfSpewerAsmJSFunctionMap(start, size, file, line, column, chars.get()); } #endif #ifdef MOZ_VTUNE if (IsVTuneProfilingActive()) { unsigned method_id = iJIT_GetNewMethodID(); if (method_id == 0) return true; iJIT_Method_Load method; method.method_id = method_id; method.method_name = chars.get(); method.method_load_address = (void*)start; method.method_size = size; method.line_number_size = 0; method.line_number_table = nullptr; method.class_id = 0; method.class_file_name = nullptr; method.source_file_name = nullptr; iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&method); } #endif } return true; }