static void rattr(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer) { int data = verb & 31; verb >>= 5; int nameIndex, valueIndex; switch (verb) { case kAttr_Value_Value_Verb: nameIndex = rec.fNextName; // record before the ++ set(rec.fNames, rec.fNextName++, s, data); valueIndex = rec.fNextValue; // record before the ++ set(rec.fValues, rec.fNextValue++, s, 31); break; case kAttr_Value_Index_Verb: nameIndex = rec.fNextName; // record before the ++ set(rec.fNames, rec.fNextName++, s, data); valueIndex = rbyte(s); break; case kAttr_Index_Value_Verb: nameIndex = rdata(s, data); valueIndex = rec.fNextValue; // record before the ++ set(rec.fValues, rec.fNextValue++, s, 31); break; case kAttr_Index_Index_Verb: nameIndex = rdata(s, data); valueIndex = rbyte(s); break; default: SkDEBUGFAIL("bad verb"); return; } writer.addAttribute(rec.fNames[nameIndex], rec.fValues[valueIndex]); }
static int rdata(SkStream& s, int data) { SkASSERT((data & ~31) == 0); if (data == 31) { data = rbyte(s); if (data == 0xFF) { data = rbyte(s); data = (data << 8) | rbyte(s); } } return data; }
void addDbgGuardImpl(SrcKey sk) { Asm a { tx64->mainCode }; // Emit the checks for debugger attach emitTLSLoad<ThreadInfo>(a, ThreadInfo::s_threadInfo, reg::rAsm); a. load_reg64_disp_reg32(reg::rAsm, dbgOff, reg::rAsm); a. testb((int8_t)0xff, rbyte(reg::rAsm)); // Branch to a special REQ_INTERPRET if attached TCA fallback = emitServiceReq(tx64->stubsCode, REQ_INTERPRET, sk.offset(), 0); a. jnz(fallback); }
/* * Read 32 bits of data + 8 bit checksum from the * DHT sensor. Returns relative humidity and * temperature in Celcius when successful. The * function returns zero if there was a checksum * error. */ static int rsensor(int *relhumidity,int *celsius) { unsigned char u[5], cs = 0, x; for ( x=0; x<5; ++x ) { u[x] = rbyte(); if ( x < 4 ) /* Only checksum data.. */ cs += u[x]; /* Checksum */ } if ( (cs & 0xFF) == u[4] ) { *relhumidity = (int)u[0]; *celsius = (int)u[2]; return 1; } return 0; }
static void relem(unsigned verb, SkStream& s, BMLW& rec, SkXMLWriter& writer) { int data = verb & 31; verb >>= 5; int elemIndex; if (verb == kStartElem_Value_Verb) { elemIndex = rec.fNextElem; // record before the ++ set(rec.fElems, rec.fNextElem++, s, data); } else { SkASSERT(verb == kStartElem_Index_Verb); elemIndex = rdata(s, data); } writer.startElement(rec.fElems[elemIndex]); for (;;) { verb = rbyte(s); switch (verb >> 5) { case kAttr_Value_Value_Verb: case kAttr_Value_Index_Verb: case kAttr_Index_Value_Verb: case kAttr_Index_Index_Verb: rattr(verb, s, rec, writer); break; case kStartElem_Value_Verb: case kStartElem_Index_Verb: relem(verb, s, rec, writer); break; case kEndElem_Verb: writer.endElement(); return; default: SkDEBUGFAIL("bad verb"); } } }
/* * Service request stub emitter. * * Emit a service request stub of type `sr' at `start' in `cb'. */ void emit_svcreq(CodeBlock& cb, TCA start, bool persist, folly::Optional<FPInvOffset> spOff, ServiceRequest sr, const ArgVec& argv) { FTRACE(2, "svcreq @{} {}(", start, to_name(sr)); auto const is_reused = start != cb.frontier(); CodeBlock stub; stub.init(start, stub_size(), "svcreq_stub"); { Vauto vasm{stub}; auto& v = vasm.main(); // If we have an spOff, materialize rvmsp() so that handleSRHelper() can do // a VM reg sync. (When we don't have an spOff, the caller of the service // request was responsible for making sure rvmsp already contained the top // of the stack.) if (spOff) { v << lea{rvmfp()[-cellsToBytes(spOff->offset)], rvmsp()}; } auto live_out = leave_trace_regs(); assert(argv.size() <= kMaxArgs); // Pick up CondCode arguments first---vasm may optimize immediate loads // into operations which clobber status flags. for (auto i = 0; i < argv.size(); ++i) { auto const& arg = argv[i]; if (arg.kind != Arg::Kind::CondCode) continue; FTRACE(2, "c({}), ", cc_names[arg.cc]); v << setcc{arg.cc, r_svcreq_sf(), rbyte(r_svcreq_arg(i))}; } for (auto i = 0; i < argv.size(); ++i) { auto const& arg = argv[i]; auto const r = r_svcreq_arg(i); switch (arg.kind) { case Arg::Kind::Immed: FTRACE(2, "{}, ", arg.imm); v << copy{v.cns(arg.imm), r}; break; case Arg::Kind::Address: FTRACE(2, "{}(%rip), ", arg.imm); v << leap{reg::rip[arg.imm], r}; break; case Arg::Kind::CondCode: break; } live_out |= r; } FTRACE(2, ") : stub@"); if (persist) { FTRACE(2, "<none>"); v << copy{v.cns(0), r_svcreq_stub()}; } else { FTRACE(2, "{}", stub.base()); v << leap{reg::rip[int64_t(stub.base())], r_svcreq_stub()}; } v << copy{v.cns(sr), r_svcreq_req()}; live_out |= r_svcreq_stub(); live_out |= r_svcreq_req(); v << jmpi{TCA(handleSRHelper), live_out}; // We pad ephemeral stubs unconditionally. This is required for // correctness by the x64 code relocator. vasm.unit().padding = !persist; } if (!is_reused) cb.skip(stub.used()); }
void BML_XMLParser::Read(SkStream& s, SkXMLWriter& writer) { BMLW rec; writer.writeHeader(); relem(rbyte(s), s, rec, writer); }
TCA emitServiceReqWork(CodeBlock& cb, TCA start, bool persist, SRFlags flags, ServiceRequest req, const ServiceReqArgVec& argv) { assert(start); const bool align = flags & SRFlags::Align; Asm as { cb }; /* * Remember previous state of the code cache. */ folly::Optional<CodeCursor> maybeCc = folly::none; if (start != as.frontier()) { maybeCc.emplace(cb, start); } /* max space for moving to align, saving VM regs plus emitting args */ static const int kVMRegSpace = 0x14, kMovSize = 0xa, kNumServiceRegs = sizeof(serviceReqArgRegs) / sizeof(PhysReg), kMaxStubSpace = kJmpTargetAlign - 1 + kVMRegSpace + kNumServiceRegs * kMovSize; if (align) { moveToAlign(cb); } TCA retval = as.frontier(); TRACE(3, "Emit Service Req @%p %s(", start, serviceReqName(req)); /* * Move args into appropriate regs. Eager VMReg save may bash flags, * so set the CondCode arguments first. */ for (int i = 0; i < argv.size(); ++i) { assert(i < kNumServiceReqArgRegs); auto reg = serviceReqArgRegs[i]; const auto& argInfo = argv[i]; switch(argv[i].m_kind) { case ServiceReqArgInfo::Immediate: { TRACE(3, "%" PRIx64 ", ", argInfo.m_imm); as. emitImmReg(argInfo.m_imm, reg); } break; case ServiceReqArgInfo::CondCode: { // Already set before VM reg save. DEBUG_ONLY TCA start = as.frontier(); as. setcc(argInfo.m_cc, rbyte(reg)); assert(start - as.frontier() <= kMovSize); TRACE(3, "cc(%x), ", argInfo.m_cc); } break; default: not_reached(); } } emitEagerVMRegSave(as, RegSaveFlags::SaveFP); if (persist) { as. emitImmReg(0, JIT::X64::rAsm); } else { as. emitImmReg((uint64_t)start, JIT::X64::rAsm); } TRACE(3, ")\n"); as. emitImmReg(req, JIT::reg::rdi); /* * Weird hand-shaking with enterTC: reverse-call a service routine. * * In the case of some special stubs (m_callToExit, m_retHelper), we * have already unbalanced the return stack by doing a ret to * something other than enterTCHelper. In that case * SRJmpInsteadOfRet indicates to fake the return. */ if (flags & SRFlags::JmpInsteadOfRet) { as. pop(JIT::reg::rax); as. jmp(JIT::reg::rax); } else { as. ret(); } // TODO(2796856): we should record an OpServiceRequest pseudo-bytecode here. if (debug) { // not reached as.ud2(); } if (!persist) { /* * Recycled stubs need to be uniformly sized. Make space for the * maximal possible service requests. */ assert(as.frontier() - start <= kMaxStubSpace); as.emitNop(start + kMaxStubSpace - as.frontier()); assert(as.frontier() - start == kMaxStubSpace); } return retval; }