static bool DecodeFunctionBody(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t funcIndex) { int64_t before = PRMJ_Now(); uint32_t bodySize; if (!d.readVarU32(&bodySize)) return Fail(cx, d, "expected number of function body bytes"); if (d.bytesRemain() < bodySize) return Fail(cx, d, "function body length too big"); const uint8_t* bodyBegin = d.currentPosition(); const uint8_t* bodyEnd = bodyBegin + bodySize; FunctionGenerator fg; if (!mg.startFuncDef(d.currentOffset(), &fg)) return false; ValTypeVector locals; if (!locals.appendAll(mg.funcSig(funcIndex).args())) return false; if (!DecodeLocalEntries(d, &locals)) return Fail(cx, d, "failed decoding local entries"); for (ValType type : locals) { if (!CheckValType(cx, d, type)) return false; } FunctionDecoder f(cx, d, mg, fg, funcIndex, locals); ExprType type = ExprType::Void; while (d.currentPosition() < bodyEnd) { if (!DecodeExpr(f, &type)) return false; } if (!CheckType(f, type, f.sig().ret())) return false; if (d.currentPosition() != bodyEnd) return Fail(cx, d, "function body length mismatch"); if (!fg.bytes().resize(bodySize)) return false; memcpy(fg.bytes().begin(), bodyBegin, bodySize); int64_t after = PRMJ_Now(); unsigned generateTime = (after - before) / PRMJ_USEC_PER_MSEC; return mg.finishFuncDef(funcIndex, generateTime, &fg); }
static bool DecodeFunc(JSContext* cx, Decoder& d, ModuleGenerator& mg, uint32_t funcIndex) { int64_t before = PRMJ_Now(); FunctionGenerator fg; if (!mg.startFuncDef(d.currentOffset(), &fg)) return false; if (!d.readCStringIf(FuncSubsection)) return Fail(cx, d, "expected 'func' tag"); uint32_t sectionStart; if (!d.startSection(§ionStart)) return Fail(cx, d, "expected func section byte size"); const DeclaredSig& sig = mg.funcSig(funcIndex); for (ValType type : sig.args()) { if (!fg.addLocal(type)) return false; } uint32_t numVars; if (!d.readVarU32(&numVars)) return Fail(cx, d, "expected number of local vars"); for (uint32_t i = 0; i < numVars; i++) { ValType type; if (!DecodeValType(cx, d, &type)) return false; if (!fg.addLocal(type)) return false; } if (!DecodeFuncBody(cx, d, mg, fg, funcIndex)) return false; if (!d.finishSection(sectionStart)) return Fail(cx, d, "func section byte size mismatch"); int64_t after = PRMJ_Now(); unsigned generateTime = (after - before) / PRMJ_USEC_PER_MSEC; return mg.finishFuncDef(funcIndex, generateTime, &fg); }
static bool DecodeFunctionExport(JSContext* cx, Decoder& d, ModuleGenerator& mg, CStringSet* dupSet) { uint32_t funcIndex; if (!d.readVarU32(&funcIndex)) return Fail(cx, d, "expected export internal index"); if (funcIndex >= mg.numFuncSigs()) return Fail(cx, d, "export function index out of range"); if (!CheckTypeForJS(cx, d, mg.funcSig(funcIndex))) return false; UniqueChars fieldName = DecodeExportName(cx, d, dupSet); if (!fieldName) return false; return mg.declareExport(Move(fieldName), funcIndex); }