summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmValidate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/wasm/WasmValidate.cpp')
-rw-r--r--js/src/wasm/WasmValidate.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp
index d67967fa41..3a0f865d46 100644
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -2929,6 +2929,92 @@ bool wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end,
return false;
}
+#ifdef ENABLE_WASM_BRANCH_HINTING
+static bool ParseBranchHintingSection(Decoder& d, ModuleEnvironment* env) {
+ uint32_t functionCount;
+ if (!d.readVarU32(&functionCount)) {
+ return d.fail("failed to read function count");
+ }
+
+ for (uint32_t i = 0; i < functionCount; i++) {
+ uint32_t functionIndex;
+ if (!d.readVarU32(&functionIndex)) {
+ return d.fail("failed to read function index");
+ }
+
+ // Disallow branch hints on imported functions.
+ if ((functionIndex >= env->funcs.length()) ||
+ (functionIndex < env->numFuncImports)) {
+ return d.fail("invalid function index in branch hint");
+ }
+
+ uint32_t hintCount;
+ if (!d.readVarU32(&hintCount)) {
+ return d.fail("failed to read hint count");
+ }
+
+ BranchHintVector hintVector;
+ if (!hintVector.reserve(hintCount)) {
+ return false;
+ }
+
+ // Branch hint offsets must appear in increasing byte offset order, at most
+ // once for each offset.
+ uint32_t prevOffsetPlus1 = 0;
+ for (uint32_t hintIndex = 0; hintIndex < hintCount; hintIndex++) {
+ uint32_t branchOffset;
+ if (!d.readVarU32(&branchOffset)) {
+ return d.fail("failed to read branch offset");
+ }
+ if (branchOffset <= prevOffsetPlus1) {
+ return d.fail("Invalid offset in code hint");
+ }
+
+ uint32_t reserved;
+ if (!d.readVarU32(&reserved) || (reserved != 1)) {
+ return d.fail("Invalid reserved value for code hint");
+ }
+
+ uint32_t branchHintValue;
+ if (!d.readVarU32(&branchHintValue) ||
+ (branchHintValue >= MaxBranchHintValue)) {
+ return d.fail("Invalid branch hint value");
+ }
+
+ BranchHint branchHint = static_cast<BranchHint>(branchHintValue);
+ BranchHintEntry entry(branchOffset, branchHint);
+ hintVector.infallibleAppend(entry);
+
+ prevOffsetPlus1 = branchOffset;
+ }
+
+ // Save this collection in the module
+ if (!env->branchHints.addHintsForFunc(functionIndex,
+ std::move(hintVector))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool DecodeBranchHintingSection(Decoder& d, ModuleEnvironment* env) {
+ MaybeSectionRange range;
+ if (!d.startCustomSection(BranchHintingSectionName, env, &range)) {
+ return false;
+ }
+ if (!range) {
+ return true;
+ }
+
+ // Skip this custom section if errors are encountered during parsing.
+ env->parsedBranchHints = ParseBranchHintingSection(d, env);
+
+ d.finishCustomSection(BranchHintingSectionName, *range);
+ return true;
+}
+#endif
+
bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) {
if (!DecodePreamble(d)) {
return false;
@@ -2984,6 +3070,12 @@ bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) {
return false;
}
+#ifdef ENABLE_WASM_BRANCH_HINTING
+ if (env->branchHintingEnabled() && !DecodeBranchHintingSection(d, env)) {
+ return false;
+ }
+#endif
+
if (!d.startSection(SectionId::Code, env, &env->codeSection, "code")) {
return false;
}