Commit d5a626c0 authored by Julien Pages's avatar Julien Pages Committed by Pier Angelo Vendrame
Browse files

Bug 19988957 - wasm: Avoid an out of memory situation when creating lazy stubs. r=rhunt

parent 035a36d9
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
oomTest(function() {
  var x = new WebAssembly.Instance(
    new WebAssembly.Module(
      wasmTextToBinary(
        '(module (func $g (result f32) f32.const 1)(table (export "table") 1 funcref)(elem (i32.const 0) $g))',
      ),
    ),
  ).exports.table.get(0);
  try {
    x.apply();
  } catch (e) {}
  x.call();
});
+37 −9
Original line number Diff line number Diff line
@@ -483,6 +483,16 @@ bool Code::createManyLazyEntryStubs(const WriteGuard& guard,

  *stubBlockIndex = guard->blocks.length();

  if (!guard->lazyExports.reserve(guard->lazyExports.length() +
                                  funcExportIndices.length()) ||
      !addCodeBlock(guard, std::move(stubCodeBlock), nullptr)) {
    return false;
  }

  // Everything after this point must be guaranteed to succeed. A failure after
  // this point can leave things in an inconsistent state, and be observed if we
  // retry to create a lazy stub.

  uint32_t codeRangeIndex = 0;
  for (uint32_t funcExportIndex : funcExportIndices) {
    const FuncExport& fe = funcExports[funcExportIndex];
@@ -511,17 +521,17 @@ bool Code::createManyLazyEntryStubs(const WriteGuard& guard,
      MOZ_ASSERT(oldKind == CodeBlockKind::SharedStubs ||
                 oldKind == CodeBlockKind::BaselineTier);
      guard->lazyExports[exportIndex] = std::move(lazyExport);
    } else if (!guard->lazyExports.insert(
                   guard->lazyExports.begin() + exportIndex,
                   std::move(lazyExport))) {
      return false;
    } else {
      // We reserved memory earlier, this should not fail.
      MOZ_RELEASE_ASSERT(guard->lazyExports.insert(
          guard->lazyExports.begin() + exportIndex, std::move(lazyExport)));
    }
  }

  stubCodeBlock->sendToProfiler(*codeMeta_, *codeTailMeta_, codeMetaForAsmJS_,
                                FuncIonPerfSpewerSpan(),
                                FuncBaselinePerfSpewerSpan());
  return addCodeBlock(guard, std::move(stubCodeBlock), nullptr);
  return true;
}

bool Code::createOneLazyEntryStub(const WriteGuard& guard,
@@ -787,10 +797,28 @@ bool Code::addCodeBlock(const WriteGuard& guard, UniqueCodeBlock block,

  CodeBlock* blockPtr = block.get();
  size_t codeBlockIndex = guard->blocks.length();
  return guard->blocks.append(std::move(block)) &&
         guard->blocksLinkData.append(std::move(maybeLinkData)) &&
         blockMap_.insert(blockPtr) &&
         blockPtr->initialize(*this, codeBlockIndex);

  if (!guard->blocks.reserve(guard->blocks.length() + 1) ||
      !guard->blocksLinkData.reserve(guard->blocksLinkData.length() + 1)) {
    return false;
  }

  // If anything fails here, be careful to reset our state back so that we are
  // not in an inconsistent state.
  if (!blockPtr->initialize(*this, codeBlockIndex)) {
    return false;
  }

  if (!blockMap_.insert(blockPtr)) {
    // We don't need to deinitialize the blockPtr, because that will be
    // automatically handled by its destructor.
    return false;
  }

  guard->blocks.infallibleAppend(std::move(block));
  guard->blocksLinkData.infallibleAppend(std::move(maybeLinkData));

  return true;
}

SharedCodeSegment Code::createFuncCodeSegmentFromPool(