зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
756c9d5a26
|
@ -10,7 +10,6 @@
|
|||
#include "Accessible-inl.h"
|
||||
#include "AccIterator.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIDOMXULLabeledControlEl.h"
|
||||
#include "mozilla/dom/Text.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -307,20 +306,17 @@ nsTextEquivUtils::AppendFromDOMNode(nsIContent *aContent, nsAString *aString)
|
|||
|
||||
if (aContent->IsXULElement()) {
|
||||
nsAutoString textEquivalent;
|
||||
nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl =
|
||||
do_QueryInterface(aContent);
|
||||
|
||||
if (labeledEl) {
|
||||
labeledEl->GetLabel(textEquivalent);
|
||||
if (aContent->NodeInfo()->Equals(nsGkAtoms::label, kNameSpaceID_XUL)) {
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
|
||||
textEquivalent);
|
||||
} else {
|
||||
if (aContent->NodeInfo()->Equals(nsGkAtoms::label,
|
||||
kNameSpaceID_XUL))
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::value,
|
||||
textEquivalent);
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label,
|
||||
textEquivalent);
|
||||
}
|
||||
|
||||
if (textEquivalent.IsEmpty())
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::tooltiptext, textEquivalent);
|
||||
if (textEquivalent.IsEmpty()) {
|
||||
aContent->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::tooltiptext, textEquivalent);
|
||||
}
|
||||
|
||||
AppendString(aString, textEquivalent);
|
||||
|
|
|
@ -804,20 +804,15 @@ Accessible::XULElmName(DocAccessible* aDocument,
|
|||
*/
|
||||
|
||||
// CASE #1 (via label attribute) -- great majority of the cases
|
||||
nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl = do_QueryInterface(aElm);
|
||||
if (labeledEl) {
|
||||
labeledEl->GetLabel(aName);
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl = do_QueryInterface(aElm);
|
||||
if (itemEl) {
|
||||
itemEl->GetLabel(aName);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl = do_QueryInterface(aElm);
|
||||
if (itemEl) {
|
||||
itemEl->GetLabel(aName);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMXULSelectControlElement> select = do_QueryInterface(aElm);
|
||||
// Use label if this is not a select control element which
|
||||
// uses label attribute to indicate which option is selected
|
||||
if (!select && aElm->IsElement()) {
|
||||
aElm->AsElement()->GetAttribute(NS_LITERAL_STRING("label"), aName);
|
||||
}
|
||||
// Use @label if this is not a select control element, which uses label
|
||||
// attribute to indicate, which option is selected.
|
||||
nsCOMPtr<nsIDOMXULSelectControlElement> select = do_QueryInterface(aElm);
|
||||
if (!select) {
|
||||
aElm->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,10 +72,10 @@
|
|||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name for nsIDOMXULLabeledControlElement.
|
||||
// Name from @label attribute.
|
||||
|
||||
// Gets the name from @label attribute.
|
||||
testName("btn_nsIDOMXULLabeledControlElement", "labeled element");
|
||||
testName("btn_labelattr", "labeled element");
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -271,8 +271,8 @@
|
|||
<button id="btn_labelledby_mixed_menulist"
|
||||
aria-labelledby="labelledby_mixed_menulist"/>
|
||||
|
||||
<!-- nsIDOMXULLabeledControlElement -->
|
||||
<button id="btn_nsIDOMXULLabeledControlElement"
|
||||
<!-- @label -->
|
||||
<button id="btn_labelattr"
|
||||
label="labeled element"/>
|
||||
|
||||
<!-- nsIDOMXULSelectControlItemElement -->
|
||||
|
|
|
@ -5295,7 +5295,8 @@ AssertContentPrivilegedAboutPageHasCSP(nsIURI* aDocumentURI, nsIPrincipal* aPrin
|
|||
|
||||
// Potentially init the legacy whitelist of about URIs without a CSP.
|
||||
static StaticAutoPtr<nsTArray<nsCString>> sLegacyAboutPagesWithNoCSP;
|
||||
if (!sLegacyAboutPagesWithNoCSP) {
|
||||
if (!sLegacyAboutPagesWithNoCSP ||
|
||||
Preferences::GetBool("csp.overrule_content_privileged_about_uris_without_csp_whitelist")) {
|
||||
sLegacyAboutPagesWithNoCSP = new nsTArray<nsCString>();
|
||||
nsAutoCString legacyAboutPages;
|
||||
Preferences::GetCString("csp.content_privileged_about_uris_without_csp",
|
||||
|
@ -5334,6 +5335,10 @@ AssertContentPrivilegedAboutPageHasCSP(nsIURI* aDocumentURI, nsIPrincipal* aPrin
|
|||
csp->GetPolicyString(0, parsedPolicyStr);
|
||||
}
|
||||
}
|
||||
if (Preferences::GetBool("csp.overrule_content_privileged_about_uris_without_csp_whitelist")) {
|
||||
NS_ASSERTION(parsedPolicyStr.Find("default-src") >= 0, "about: page must have a CSP");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(parsedPolicyStr.Find("default-src") >= 0,
|
||||
"about: page must contain a CSP including default-src");
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ XPIDL_SOURCES += [
|
|||
'nsIDOMXULCommandDispatcher.idl',
|
||||
'nsIDOMXULContainerElement.idl',
|
||||
'nsIDOMXULControlElement.idl',
|
||||
'nsIDOMXULLabeledControlEl.idl',
|
||||
'nsIDOMXULMenuListElement.idl',
|
||||
'nsIDOMXULMultSelectCntrlEl.idl',
|
||||
'nsIDOMXULRelatedElement.idl',
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMXULLabeledControlEl.idl"
|
||||
#include "nsIDOMXULControlElement.idl"
|
||||
|
||||
[scriptable, uuid(6ed53cfb-9e59-424c-af8d-e74582381951)]
|
||||
interface nsIDOMXULButtonElement : nsIDOMXULLabeledControlElement {
|
||||
interface nsIDOMXULButtonElement : nsIDOMXULControlElement {
|
||||
attribute DOMString type;
|
||||
attribute DOMString dlgType;
|
||||
|
||||
|
@ -19,4 +19,3 @@ interface nsIDOMXULButtonElement : nsIDOMXULLabeledControlElement {
|
|||
// For buttons of type="radio" only.
|
||||
attribute DOMString group;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMXULControlElement.idl"
|
||||
|
||||
[scriptable, uuid(c58a159f-e27d-40c8-865a-d4dcfd928f62)]
|
||||
interface nsIDOMXULLabeledControlElement : nsIDOMXULControlElement {
|
||||
attribute DOMString crop;
|
||||
attribute DOMString image;
|
||||
attribute DOMString label;
|
||||
attribute DOMString accessKey;
|
||||
attribute DOMString command;
|
||||
|
||||
// void doCommand();
|
||||
};
|
||||
|
|
@ -42,3 +42,5 @@ skip-if = toolkit == 'android'
|
|||
[test_same_site_cookies_toplevel_set_cookie.html]
|
||||
[test_same_site_cookies_iframe.html]
|
||||
[test_same_site_cookies_about.html]
|
||||
[test_assert_about_page_no_csp.html]
|
||||
skip-if = !debug || toolkit == 'android'
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1490977: Test Assertion if content privileged about: page has no CSP</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="testframe"></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
|
||||
// Test Setup:
|
||||
// The test overrules the whitelist of about: pages that are allowed to load without a CSP
|
||||
// and makes sure to hit the assertion within AssertContentPrivilegedAboutPageHasCSP().
|
||||
// However, due to the caching mechanism within AssertContentPrivilegedAboutPageHasCSP this
|
||||
// test loads a second dummy data: URI to reset the old cache and finally resets the pref
|
||||
// used for testing purposes.
|
||||
|
||||
let origWhiteList = SpecialPowers.getCharPref("csp.content_privileged_about_uris_without_csp");
|
||||
|
||||
SpecialPowers.setCharPref("csp.content_privileged_about_uris_without_csp", "");
|
||||
SpecialPowers.setBoolPref("csp.overrule_content_privileged_about_uris_without_csp_whitelist", true);
|
||||
|
||||
ok(true, "sanity: prefs flipped and test runs");
|
||||
let myFrame = document.getElementById("testframe");
|
||||
myFrame.src = "about:blank";
|
||||
// booom :-)
|
||||
|
||||
SpecialPowers.setCharPref("csp.content_privileged_about_uris_without_csp", origWhiteList);
|
||||
myFrame.src = "data:text/html,<body>just a dumy data: URI</body>";
|
||||
|
||||
SpecialPowers.setBoolPref("csp.overrule_content_privileged_about_uris_without_csp_whitelist", false);
|
||||
|
||||
SimpleTest.finish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -66,8 +66,8 @@ pub enum SourceTexture {
|
|||
RenderTaskCache(SavedTargetIndex),
|
||||
}
|
||||
|
||||
pub const ORTHO_NEAR_PLANE: f32 = -1000000.0;
|
||||
pub const ORTHO_FAR_PLANE: f32 = 1000000.0;
|
||||
pub const ORTHO_NEAR_PLANE: f32 = -100000.0;
|
||||
pub const ORTHO_FAR_PLANE: f32 = 100000.0;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
|
|
@ -1 +1 @@
|
|||
6fa046c936b9d720726d27c3b0514ee66a305b69
|
||||
5b5b4145ecef117acb02fd1f9b72bf02e85c650b
|
||||
|
|
|
@ -118,6 +118,9 @@ IsValidAllocKind(AllocKind kind)
|
|||
return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
|
||||
}
|
||||
|
||||
const char*
|
||||
AllocKindName(AllocKind kind);
|
||||
|
||||
inline bool
|
||||
IsObjectAllocKind(AllocKind kind)
|
||||
{
|
||||
|
|
|
@ -1268,8 +1268,8 @@ GCRuntime::parseAndSetZeal(const char* str)
|
|||
return true;
|
||||
}
|
||||
|
||||
static const char*
|
||||
AllocKindName(AllocKind kind)
|
||||
const char*
|
||||
js::gc::AllocKindName(AllocKind kind)
|
||||
{
|
||||
static const char* const names[] = {
|
||||
#define EXPAND_THING_NAME(allocKind, _1, _2, _3, _4, _5, _6) \
|
||||
|
|
|
@ -32,6 +32,6 @@ assertEq(s.format, "wasm");
|
|||
var source2 = s.source;
|
||||
|
||||
// The text is predefined if wasm binary sources are enabled.
|
||||
assertEq(source2.text, '[wasm]');
|
||||
assertEq(source2.text, '[debugger missing wasm binary-to-text conversion]');
|
||||
// The binary contains Uint8Array which is equal to wasm bytecode;
|
||||
arraysEqual(source2.binary, wasmTextToBinary('(module (func) (export "" 0))'));
|
||||
|
|
|
@ -66,9 +66,9 @@ assertEq(gotScript.source.sourceMapURL, 'http://example.org/test');
|
|||
// The sourceMapURL is read-only for wasm
|
||||
assertThrowsInstanceOf(() => gotScript.source.sourceMapURL = 'foo', Error);
|
||||
|
||||
// The sourceMappingURL section is present, but is not available when wasm
|
||||
// The sourceMappingURL section is present, and is still available when wasm
|
||||
// binary source is disabled.
|
||||
dbg.allowWasmBinarySource = false;
|
||||
g.eval(`o = new WebAssembly.Instance(new WebAssembly.Module(toWasm('(module (func) (export "a" 0))', 'http://example.org/test2')));`);
|
||||
assertEq(gotScript.format, "wasm");
|
||||
assertEq(gotScript.source.sourceMapURL, null);
|
||||
assertEq(gotScript.source.sourceMapURL, 'http://example.org/test2');
|
||||
|
|
|
@ -7007,7 +7007,7 @@ JS_PUBLIC_API(RefPtr<JS::WasmModule>)
|
|||
JS::GetWasmModule(HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(JS::IsWasmModuleObject(obj));
|
||||
return &CheckedUnwrap(obj)->as<WasmModuleObject>().module();
|
||||
return const_cast<wasm::Module*>(&CheckedUnwrap(obj)->as<WasmModuleObject>().module());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(RefPtr<JS::WasmModule>)
|
||||
|
|
|
@ -6579,7 +6579,7 @@ struct SharedObjectMailbox
|
|||
SharedArrayRawBuffer* buffer;
|
||||
uint32_t length;
|
||||
} sarb;
|
||||
wasm::Module* module;
|
||||
const wasm::Module* module;
|
||||
};
|
||||
|
||||
SharedObjectMailbox() : tag(MailboxTag::Empty) {}
|
||||
|
|
|
@ -2785,7 +2785,7 @@ UpdateExecutionObservabilityOfScriptsInZone(JSContext* cx, Zone* zone,
|
|||
}
|
||||
|
||||
bool enableTrap = observing == Debugger::IsObserving::Observing;
|
||||
instance->ensureEnterFrameTrapsState(cx, enableTrap);
|
||||
instance->debug().ensureEnterFrameTrapsState(cx, enableTrap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5931,12 +5931,13 @@ struct DebuggerScriptGetLineCountMatcher
|
|||
}
|
||||
return match(script);
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
|
||||
uint32_t result;
|
||||
if (!wasmInstance->instance().debug().totalSourceLines(cx_, &result)) {
|
||||
return false;
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
if (instance.debugEnabled()) {
|
||||
totalLines = double(instance.debug().totalSourceLines());
|
||||
} else {
|
||||
totalLines = 0;
|
||||
}
|
||||
totalLines = double(result);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -6390,15 +6391,16 @@ class DebuggerScriptGetOffsetLocationMatcher
|
|||
}
|
||||
return match(script);
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> instance) {
|
||||
size_t lineno;
|
||||
size_t column;
|
||||
bool found;
|
||||
if (!instance->instance().debug().getOffsetLocation(cx_, offset_, &found, &lineno, &column)) {
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
if (!instance.debugEnabled()) {
|
||||
JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
size_t lineno;
|
||||
size_t column;
|
||||
if (!instance.debug().getOffsetLocation(offset_, &lineno, &column)) {
|
||||
JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET);
|
||||
return false;
|
||||
}
|
||||
|
@ -6696,9 +6698,11 @@ class DebuggerScriptGetAllColumnOffsetsMatcher
|
|||
}
|
||||
return match(script);
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> instance) {
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
|
||||
Vector<wasm::ExprLoc> offsets(cx_);
|
||||
if (!instance->instance().debug().getAllColumnOffsets(cx_, &offsets)) {
|
||||
if (instance.debugEnabled() && !instance.debug().getAllColumnOffsets(cx_, &offsets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6785,9 +6789,11 @@ class DebuggerScriptGetLineOffsetsMatcher
|
|||
}
|
||||
return match(script);
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> instance) {
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
|
||||
Vector<uint32_t> offsets(cx_);
|
||||
if (!instance->instance().debug().getLineOffsets(cx_, lineno_, &offsets)) {
|
||||
if (instance.debugEnabled() && !instance.debug().getLineOffsets(cx_, lineno_, &offsets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -7108,7 +7114,7 @@ struct DebuggerScriptSetBreakpointMatcher
|
|||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
|
||||
wasm::Instance& instance = wasmInstance->instance();
|
||||
if (!instance.debug().hasBreakpointTrapAtOffset(offset_)) {
|
||||
if (!instance.debugEnabled() || !instance.debug().hasBreakpointTrapAtOffset(offset_)) {
|
||||
JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET);
|
||||
return false;
|
||||
}
|
||||
|
@ -7216,8 +7222,12 @@ class DebuggerScriptClearBreakpointMatcher
|
|||
}
|
||||
return match(script);
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> instance) {
|
||||
return instance->instance().debug().clearBreakpointsIn(cx_, instance, dbg_, handler_);
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
if (!instance.debugEnabled()) {
|
||||
return true;
|
||||
}
|
||||
return instance.debug().clearBreakpointsIn(cx_, instanceObj, dbg_, handler_);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7653,13 +7663,15 @@ class DebuggerSourceGetTextMatcher
|
|||
return ss->substring(cx_, 0, ss->length());
|
||||
}
|
||||
|
||||
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
|
||||
if (wasmInstance->instance().debug().maybeBytecode() &&
|
||||
wasmInstance->instance().debug().binarySource())
|
||||
{
|
||||
return NewStringCopyZ<CanGC>(cx_, "[wasm]");
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
const char* msg;
|
||||
if (!instance.debugEnabled()) {
|
||||
msg = "Restart with developer tools open to view WebAssembly source.";
|
||||
} else {
|
||||
msg = "[debugger missing wasm binary-to-text conversion]";
|
||||
}
|
||||
return wasmInstance->instance().debug().createText(cx_);
|
||||
return NewStringCopyZ<CanGC>(cx_, msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7696,22 +7708,22 @@ DebuggerSource_getBinary(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
RootedWasmInstanceObject wasmInstance(cx, referent.as<WasmInstanceObject*>());
|
||||
if (!wasmInstance->instance().debug().binarySource()) {
|
||||
RootedWasmInstanceObject instanceObj(cx, referent.as<WasmInstanceObject*>());
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
|
||||
if (!instance.debugEnabled() || !instance.debug().binarySource()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_DEBUG_NO_BINARY_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bytecode = wasmInstance->instance().debug().maybeBytecode();
|
||||
size_t arrLength = bytecode ? bytecode->length() : 0;
|
||||
RootedObject arr(cx, JS_NewUint8Array(cx, arrLength));
|
||||
const wasm::Bytes& bytecode = instance.debug().bytecode();
|
||||
RootedObject arr(cx, JS_NewUint8Array(cx, bytecode.length()));
|
||||
if (!arr) {
|
||||
return false;
|
||||
}
|
||||
if (bytecode) {
|
||||
memcpy(arr->as<TypedArrayObject>().viewDataUnshared(), bytecode->begin(), arrLength);
|
||||
}
|
||||
|
||||
memcpy(arr->as<TypedArrayObject>().viewDataUnshared(), bytecode.begin(), bytecode.length());
|
||||
|
||||
args.rval().setObject(*arr);
|
||||
return true;
|
||||
|
@ -7735,18 +7747,8 @@ class DebuggerSourceGetURLMatcher
|
|||
}
|
||||
return Nothing();
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
|
||||
if (wasmInstance->instance().metadata().filenameIsURL) {
|
||||
JSString* str = NewStringCopyZ<CanGC>(cx_, wasmInstance->instance().metadata().filename.get());
|
||||
if (!str) {
|
||||
return Nothing();
|
||||
}
|
||||
return Some(str);
|
||||
}
|
||||
if (JSString* str = wasmInstance->instance().debug().debugDisplayURL(cx_)) {
|
||||
return Some(str);
|
||||
}
|
||||
return Nothing();
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
return Some(instanceObj->instance().createDisplayURL(cx_));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8009,17 +8011,18 @@ class DebuggerSourceGetSourceMapURLMatcher
|
|||
result_.set(str);
|
||||
return true;
|
||||
}
|
||||
ReturnType match(Handle<WasmInstanceObject*> wasmInstance) {
|
||||
// sourceMapURL is not available if debugger was not in
|
||||
// allowWasmBinarySource mode.
|
||||
if (!wasmInstance->instance().debug().binarySource()) {
|
||||
ReturnType match(Handle<WasmInstanceObject*> instanceObj) {
|
||||
wasm::Instance& instance = instanceObj->instance();
|
||||
if (!instance.debugEnabled()) {
|
||||
result_.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedString str(cx_);
|
||||
if (!wasmInstance->instance().debug().getSourceMappingURL(cx_, &str)) {
|
||||
if (!instance.debug().getSourceMappingURL(cx_, &str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result_.set(str);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -468,7 +468,7 @@ StatsCellCallback(JSRuntime* rt, void* data, void* thing, JS::TraceKind traceKin
|
|||
// These classes require special handling due to shared resources which
|
||||
// we must be careful not to report twice.
|
||||
if (obj->is<WasmModuleObject>()) {
|
||||
wasm::Module& module = obj->as<WasmModuleObject>().module();
|
||||
const wasm::Module& module = obj->as<WasmModuleObject>().module();
|
||||
if (ScriptSource* ss = module.metadata().maybeScriptSource()) {
|
||||
CollectScriptSourceStats<granularity>(closure, ss);
|
||||
}
|
||||
|
|
|
@ -484,7 +484,7 @@ class ObjectGroupRealm::NewTable : public JS::WeakCache<js::GCHashSet<NewEntry,
|
|||
};
|
||||
|
||||
/* static*/ ObjectGroupRealm&
|
||||
ObjectGroupRealm::get(ObjectGroup* group)
|
||||
ObjectGroupRealm::get(const ObjectGroup* group)
|
||||
{
|
||||
return group->realm()->objectGroups_;
|
||||
}
|
||||
|
@ -1696,7 +1696,7 @@ ObjectGroup::getCopyOnWriteObject(JSScript* script, jsbytecode* pc)
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
ObjectGroup::findAllocationSite(JSContext* cx, ObjectGroup* group,
|
||||
ObjectGroup::findAllocationSite(JSContext* cx, const ObjectGroup* group,
|
||||
JSScript** script, uint32_t* offset)
|
||||
{
|
||||
*script = nullptr;
|
||||
|
|
|
@ -588,7 +588,7 @@ class ObjectGroup : public gc::TenuredCell
|
|||
static ArrayObject* getCopyOnWriteObject(JSScript* script, jsbytecode* pc);
|
||||
|
||||
// Returns false if not found.
|
||||
static bool findAllocationSite(JSContext* cx, ObjectGroup* group,
|
||||
static bool findAllocationSite(JSContext* cx, const ObjectGroup* group,
|
||||
JSScript** script, uint32_t* offset);
|
||||
|
||||
private:
|
||||
|
@ -693,7 +693,7 @@ class ObjectGroupRealm
|
|||
ObjectGroupRealm(ObjectGroupRealm&) = delete;
|
||||
void operator=(ObjectGroupRealm&) = delete;
|
||||
|
||||
static ObjectGroupRealm& get(ObjectGroup* group);
|
||||
static ObjectGroupRealm& get(const ObjectGroup* group);
|
||||
static ObjectGroupRealm& getForNewObject(JSContext* cx);
|
||||
|
||||
void replaceAllocationSiteGroup(JSScript* script, jsbytecode* pc,
|
||||
|
|
|
@ -320,7 +320,7 @@ class JS::Realm : public JS::shadow::Realm
|
|||
// Object group tables and other state in the realm. This is private to
|
||||
// enforce use of ObjectGroupRealm::get(group)/getForNewObject(cx).
|
||||
js::ObjectGroupRealm objectGroups_;
|
||||
friend js::ObjectGroupRealm& js::ObjectGroupRealm::get(js::ObjectGroup* group);
|
||||
friend js::ObjectGroupRealm& js::ObjectGroupRealm::get(const js::ObjectGroup* group);
|
||||
friend js::ObjectGroupRealm& js::ObjectGroupRealm::getForNewObject(JSContext* cx);
|
||||
|
||||
// The global environment record's [[VarNames]] list that contains all
|
||||
|
|
|
@ -139,7 +139,7 @@ TypeSet::ObjectKey::maybeCompartment()
|
|||
}
|
||||
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(JSObject* obj)
|
||||
TypeSet::ObjectType(const JSObject* obj)
|
||||
{
|
||||
if (obj->isSingleton()) {
|
||||
return Type(uintptr_t(obj) | 1);
|
||||
|
@ -148,7 +148,7 @@ TypeSet::ObjectType(JSObject* obj)
|
|||
}
|
||||
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectGroup* group)
|
||||
TypeSet::ObjectType(const ObjectGroup* group)
|
||||
{
|
||||
if (group->singleton()) {
|
||||
return Type(uintptr_t(group->singleton()) | 1);
|
||||
|
@ -157,7 +157,7 @@ TypeSet::ObjectType(ObjectGroup* group)
|
|||
}
|
||||
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectKey* obj)
|
||||
TypeSet::ObjectType(const ObjectKey* obj)
|
||||
{
|
||||
return Type(uintptr_t(obj));
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ static UniqueChars MakeStringCopy(const char* s)
|
|||
}
|
||||
|
||||
/* static */ UniqueChars
|
||||
TypeSet::TypeString(TypeSet::Type type)
|
||||
TypeSet::TypeString(const TypeSet::Type type)
|
||||
{
|
||||
if (type.isPrimitive() || type.isUnknown() || type.isAnyObject()) {
|
||||
return MakeStringCopy(NonObjectTypeString(type));
|
||||
|
@ -163,7 +163,7 @@ TypeSet::TypeString(TypeSet::Type type)
|
|||
}
|
||||
|
||||
/* static */ UniqueChars
|
||||
TypeSet::ObjectGroupString(ObjectGroup* group)
|
||||
TypeSet::ObjectGroupString(const ObjectGroup* group)
|
||||
{
|
||||
return TypeString(TypeSet::ObjectType(group));
|
||||
}
|
||||
|
|
|
@ -435,14 +435,14 @@ class TypeSet
|
|||
return Type(type);
|
||||
}
|
||||
|
||||
static inline Type ObjectType(JSObject* obj);
|
||||
static inline Type ObjectType(ObjectGroup* group);
|
||||
static inline Type ObjectType(ObjectKey* key);
|
||||
static inline Type ObjectType(const JSObject* obj);
|
||||
static inline Type ObjectType(const ObjectGroup* group);
|
||||
static inline Type ObjectType(const ObjectKey* key);
|
||||
|
||||
static const char* NonObjectTypeString(Type type);
|
||||
|
||||
static JS::UniqueChars TypeString(Type type);
|
||||
static JS::UniqueChars ObjectGroupString(ObjectGroup* group);
|
||||
static JS::UniqueChars TypeString(const Type type);
|
||||
static JS::UniqueChars ObjectGroupString(const ObjectGroup* group);
|
||||
|
||||
public:
|
||||
void print(FILE* fp = stderr);
|
||||
|
|
|
@ -367,9 +367,7 @@ struct js::AsmJSMetadata : Metadata, AsmJSMetadataCacheablePod
|
|||
ScriptSource* maybeScriptSource() const override {
|
||||
return scriptSource.get();
|
||||
}
|
||||
bool getFuncName(NameContext ctx, const Bytes* maybeBytecode, uint32_t funcIndex,
|
||||
UTF8Bytes* name) const override
|
||||
{
|
||||
bool getFuncName(NameContext ctx, uint32_t funcIndex, UTF8Bytes* name) const override {
|
||||
const char* p = asmJSFuncNames[funcIndex].get();
|
||||
if (!p) {
|
||||
return true;
|
||||
|
@ -2404,7 +2402,7 @@ IsLiteralInt(ModuleValidator& m, ParseNode* pn, uint32_t* u32)
|
|||
|
||||
namespace {
|
||||
|
||||
typedef Vector<PropertyName*, 4, SystemAllocPolicy> NameVector;
|
||||
typedef Vector<PropertyName*, 4, SystemAllocPolicy> LabelVector;
|
||||
|
||||
// Encapsulates the building of an asm bytecode function from an asm.js function
|
||||
// source code, packing the asm.js code into the asm bytecode form that can
|
||||
|
@ -2534,7 +2532,7 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
return encoder().writeOp(Op::End);
|
||||
}
|
||||
|
||||
bool pushUnbreakableBlock(const NameVector* labels = nullptr) {
|
||||
bool pushUnbreakableBlock(const LabelVector* labels = nullptr) {
|
||||
if (labels) {
|
||||
for (PropertyName* label : *labels) {
|
||||
if (!breakLabels_.putNew(label, blockDepth_)) {
|
||||
|
@ -2546,7 +2544,7 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
return encoder().writeOp(Op::Block) &&
|
||||
encoder().writeFixedU8(uint8_t(ExprType::Void));
|
||||
}
|
||||
bool popUnbreakableBlock(const NameVector* labels = nullptr) {
|
||||
bool popUnbreakableBlock(const LabelVector* labels = nullptr) {
|
||||
if (labels) {
|
||||
for (PropertyName* label : *labels) {
|
||||
removeLabel(label, &breakLabels_);
|
||||
|
@ -2622,7 +2620,7 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
return writeBr(continuableStack_.back());
|
||||
}
|
||||
|
||||
bool addLabels(const NameVector& labels, uint32_t relativeBreakDepth,
|
||||
bool addLabels(const LabelVector& labels, uint32_t relativeBreakDepth,
|
||||
uint32_t relativeContinueDepth)
|
||||
{
|
||||
for (PropertyName* label : labels) {
|
||||
|
@ -2635,7 +2633,7 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||
}
|
||||
return true;
|
||||
}
|
||||
void removeLabels(const NameVector& labels) {
|
||||
void removeLabels(const LabelVector& labels) {
|
||||
for (PropertyName* label : labels) {
|
||||
removeLabel(label, &breakLabels_);
|
||||
removeLabel(label, &continueLabels_);
|
||||
|
@ -5171,7 +5169,7 @@ CheckLoopConditionOnEntry(FunctionValidator& f, ParseNode* cond)
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* labels = nullptr)
|
||||
CheckWhile(FunctionValidator& f, ParseNode* whileStmt, const LabelVector* labels = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(whileStmt->isKind(ParseNodeKind::While));
|
||||
ParseNode* cond = BinaryLeft(whileStmt);
|
||||
|
@ -5213,7 +5211,7 @@ CheckWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* labels
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckFor(FunctionValidator& f, ParseNode* forStmt, const NameVector* labels = nullptr)
|
||||
CheckFor(FunctionValidator& f, ParseNode* forStmt, const LabelVector* labels = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(forStmt->isKind(ParseNodeKind::For));
|
||||
ParseNode* forHead = BinaryLeft(forStmt);
|
||||
|
@ -5299,7 +5297,7 @@ CheckFor(FunctionValidator& f, ParseNode* forStmt, const NameVector* labels = nu
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* labels = nullptr)
|
||||
CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt, const LabelVector* labels = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(whileStmt->isKind(ParseNodeKind::DoWhile));
|
||||
ParseNode* body = BinaryLeft(whileStmt);
|
||||
|
@ -5356,14 +5354,14 @@ CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* label
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool CheckStatementList(FunctionValidator& f, ParseNode*, const NameVector* = nullptr);
|
||||
static bool CheckStatementList(FunctionValidator& f, ParseNode*, const LabelVector* = nullptr);
|
||||
|
||||
static bool
|
||||
CheckLabel(FunctionValidator& f, ParseNode* labeledStmt)
|
||||
{
|
||||
MOZ_ASSERT(labeledStmt->isKind(ParseNodeKind::Label));
|
||||
|
||||
NameVector labels;
|
||||
LabelVector labels;
|
||||
ParseNode* innermost = labeledStmt;
|
||||
do {
|
||||
if (!labels.append(LabeledStatementLabel(innermost))) {
|
||||
|
@ -5751,7 +5749,7 @@ CheckReturn(FunctionValidator& f, ParseNode* returnStmt)
|
|||
}
|
||||
|
||||
static bool
|
||||
CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const NameVector* labels /*= nullptr */)
|
||||
CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const LabelVector* labels /*= nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
|
||||
|
||||
|
@ -6630,7 +6628,7 @@ GetImports(JSContext* cx, const AsmJSMetadata& metadata, HandleValue globalVal,
|
|||
}
|
||||
|
||||
static bool
|
||||
TryInstantiate(JSContext* cx, CallArgs args, Module& module, const AsmJSMetadata& metadata,
|
||||
TryInstantiate(JSContext* cx, CallArgs args, const Module& module, const AsmJSMetadata& metadata,
|
||||
MutableHandleWasmInstanceObject instanceObj, MutableHandleObject exportObj)
|
||||
{
|
||||
HandleValue globalVal = args.get(0);
|
||||
|
@ -6734,7 +6732,7 @@ HandleInstantiationFailure(JSContext* cx, CallArgs args, const AsmJSMetadata& me
|
|||
return InternalCallOrConstruct(cx, args, args.isConstructing() ? CONSTRUCT : NO_CONSTRUCT);
|
||||
}
|
||||
|
||||
static Module&
|
||||
static const Module&
|
||||
AsmJSModuleFunctionToModule(JSFunction* fun)
|
||||
{
|
||||
MOZ_ASSERT(IsAsmJSModule(fun));
|
||||
|
@ -6749,7 +6747,7 @@ js::InstantiateAsmJS(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSFunction* callee = &args.callee().as<JSFunction>();
|
||||
Module& module = AsmJSModuleFunctionToModule(callee);
|
||||
const Module& module = AsmJSModuleFunctionToModule(callee);
|
||||
const AsmJSMetadata& metadata = module.metadata().asAsmJS();
|
||||
|
||||
RootedWasmInstanceObject instanceObj(cx);
|
||||
|
@ -7151,15 +7149,14 @@ struct ScopedCacheEntryOpenedForRead
|
|||
} // unnamed namespace
|
||||
|
||||
static JS::AsmJSCacheResult
|
||||
StoreAsmJSModuleInCache(AsmJSParser& parser, Module& module, const LinkData& linkData, JSContext* cx)
|
||||
StoreAsmJSModuleInCache(AsmJSParser& parser, const Module& module, const LinkData& linkData,
|
||||
JSContext* cx)
|
||||
{
|
||||
ModuleCharsForStore moduleChars;
|
||||
if (!moduleChars.init(parser)) {
|
||||
return JS::AsmJSCache_InternalError;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(module.bytecode().length() == 0);
|
||||
|
||||
size_t moduleSize = module.serializedSize(linkData);
|
||||
MOZ_RELEASE_ASSERT(moduleSize <= UINT32_MAX);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ WasmHandleDebugTrap()
|
|||
DebugFrame* debugFrame = DebugFrame::from(fp);
|
||||
|
||||
if (site->kind() == CallSite::EnterFrame) {
|
||||
if (!instance->enterFrameTrapsEnabled()) {
|
||||
if (!instance->debug().enterFrameTrapsEnabled()) {
|
||||
return true;
|
||||
}
|
||||
debugFrame->setIsDebuggee();
|
||||
|
|
|
@ -281,7 +281,7 @@ AppendToString(const char* str, UTF8Bytes* bytes)
|
|||
#endif
|
||||
|
||||
static void
|
||||
SendCodeRangesToProfiler(const ModuleSegment& ms, const Bytes& bytecode, const Metadata& metadata,
|
||||
SendCodeRangesToProfiler(const ModuleSegment& ms, const Metadata& metadata,
|
||||
const CodeRangeVector& codeRanges)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
@ -304,7 +304,7 @@ SendCodeRangesToProfiler(const ModuleSegment& ms, const Bytes& bytecode, const M
|
|||
uintptr_t size = codeRange.end() - codeRange.begin();
|
||||
|
||||
UTF8Bytes name;
|
||||
if (!metadata.getFuncNameStandalone(&bytecode, codeRange.funcIndex(), &name)) {
|
||||
if (!metadata.getFuncNameStandalone(codeRange.funcIndex(), &name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -404,7 +404,6 @@ ModuleSegment::create(Tier tier, const Bytes& unlinkedBytes, const LinkData& lin
|
|||
|
||||
bool
|
||||
ModuleSegment::initialize(const CodeTier& codeTier,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
const Metadata& metadata,
|
||||
const MetadataTier& metadataTier)
|
||||
|
@ -420,7 +419,7 @@ ModuleSegment::initialize(const CodeTier& codeTier,
|
|||
return false;
|
||||
}
|
||||
|
||||
SendCodeRangesToProfiler(*this, bytecode.bytes, metadata, metadataTier.codeRanges);
|
||||
SendCodeRangesToProfiler(*this, metadata, metadataTier.codeRanges);
|
||||
|
||||
// See comments in CodeSegment::initialize() for why this must be last.
|
||||
return CodeSegment::initialize(codeTier);
|
||||
|
@ -976,24 +975,12 @@ Metadata::serializedSize() const
|
|||
SerializedVectorSize(funcTypeIds) +
|
||||
SerializedPodVectorSize(globals) +
|
||||
SerializedPodVectorSize(tables) +
|
||||
sizeof(moduleName) +
|
||||
SerializedPodVectorSize(funcNames) +
|
||||
SerializedPodVectorSize(customSections) +
|
||||
filename.serializedSize() +
|
||||
sourceMapURL.serializedSize();
|
||||
}
|
||||
|
||||
size_t
|
||||
Metadata::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return SizeOfVectorExcludingThis(funcTypeIds, mallocSizeOf) +
|
||||
globals.sizeOfExcludingThis(mallocSizeOf) +
|
||||
tables.sizeOfExcludingThis(mallocSizeOf) +
|
||||
funcNames.sizeOfExcludingThis(mallocSizeOf) +
|
||||
customSections.sizeOfExcludingThis(mallocSizeOf) +
|
||||
filename.sizeOfExcludingThis(mallocSizeOf) +
|
||||
sourceMapURL.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
Metadata::serialize(uint8_t* cursor) const
|
||||
{
|
||||
|
@ -1002,8 +989,8 @@ Metadata::serialize(uint8_t* cursor) const
|
|||
cursor = SerializeVector(cursor, funcTypeIds);
|
||||
cursor = SerializePodVector(cursor, globals);
|
||||
cursor = SerializePodVector(cursor, tables);
|
||||
cursor = WriteBytes(cursor, &moduleName, sizeof(moduleName));
|
||||
cursor = SerializePodVector(cursor, funcNames);
|
||||
cursor = SerializePodVector(cursor, customSections);
|
||||
cursor = filename.serialize(cursor);
|
||||
cursor = sourceMapURL.serialize(cursor);
|
||||
return cursor;
|
||||
|
@ -1016,8 +1003,8 @@ Metadata::deserialize(const uint8_t* cursor)
|
|||
(cursor = DeserializeVector(cursor, &funcTypeIds)) &&
|
||||
(cursor = DeserializePodVector(cursor, &globals)) &&
|
||||
(cursor = DeserializePodVector(cursor, &tables)) &&
|
||||
(cursor = ReadBytes(cursor, &moduleName, sizeof(moduleName))) &&
|
||||
(cursor = DeserializePodVector(cursor, &funcNames)) &&
|
||||
(cursor = DeserializePodVector(cursor, &customSections)) &&
|
||||
(cursor = filename.deserialize(cursor)) &&
|
||||
(cursor = sourceMapURL.deserialize(cursor));
|
||||
debugEnabled = false;
|
||||
|
@ -1026,6 +1013,17 @@ Metadata::deserialize(const uint8_t* cursor)
|
|||
return cursor;
|
||||
}
|
||||
|
||||
size_t
|
||||
Metadata::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return SizeOfVectorExcludingThis(funcTypeIds, mallocSizeOf) +
|
||||
globals.sizeOfExcludingThis(mallocSizeOf) +
|
||||
tables.sizeOfExcludingThis(mallocSizeOf) +
|
||||
funcNames.sizeOfExcludingThis(mallocSizeOf) +
|
||||
filename.sizeOfExcludingThis(mallocSizeOf) +
|
||||
sourceMapURL.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
struct ProjectFuncIndex
|
||||
{
|
||||
const FuncExportVector& funcExports;
|
||||
|
@ -1057,11 +1055,11 @@ MetadataTier::lookupFuncExport(uint32_t funcIndex, size_t* funcExportIndex) cons
|
|||
}
|
||||
|
||||
static bool
|
||||
AppendNameInBytecode(const Bytes* maybeBytecode, const NameInBytecode& name, UTF8Bytes* bytes)
|
||||
AppendName(const Bytes& namePayload, const Name& name, UTF8Bytes* bytes)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(name.offset <= maybeBytecode->length());
|
||||
MOZ_RELEASE_ASSERT(name.length <= maybeBytecode->length() - name.offset);
|
||||
return bytes->append((const char*)maybeBytecode->begin() + name.offset, name.length);
|
||||
MOZ_RELEASE_ASSERT(name.offsetInNamePayload <= namePayload.length());
|
||||
MOZ_RELEASE_ASSERT(name.length <= namePayload.length() - name.offsetInNamePayload);
|
||||
return bytes->append((const char*)namePayload.begin() + name.offsetInNamePayload, name.length);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1080,11 +1078,10 @@ AppendFunctionIndexName(uint32_t funcIndex, UTF8Bytes* bytes)
|
|||
}
|
||||
|
||||
bool
|
||||
Metadata::getFuncName(NameContext ctx, const Bytes* maybeBytecode, uint32_t funcIndex,
|
||||
UTF8Bytes* name) const
|
||||
Metadata::getFuncName(NameContext ctx, uint32_t funcIndex, UTF8Bytes* name) const
|
||||
{
|
||||
if (moduleName && moduleName->length != 0) {
|
||||
if (!AppendNameInBytecode(maybeBytecode, *moduleName, name)) {
|
||||
if (!AppendName(namePayload->bytes, *moduleName, name)) {
|
||||
return false;
|
||||
}
|
||||
if (!name->append('.')) {
|
||||
|
@ -1093,7 +1090,7 @@ Metadata::getFuncName(NameContext ctx, const Bytes* maybeBytecode, uint32_t func
|
|||
}
|
||||
|
||||
if (funcIndex < funcNames.length() && funcNames[funcIndex].length != 0) {
|
||||
return AppendNameInBytecode(maybeBytecode, funcNames[funcIndex], name);
|
||||
return AppendName(namePayload->bytes, funcNames[funcIndex], name);
|
||||
}
|
||||
|
||||
if (ctx == NameContext::BeforeLocation) {
|
||||
|
@ -1103,6 +1100,25 @@ Metadata::getFuncName(NameContext ctx, const Bytes* maybeBytecode, uint32_t func
|
|||
return AppendFunctionIndexName(funcIndex, name);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeTier::initialize(const Code& code,
|
||||
const LinkData& linkData,
|
||||
const Metadata& metadata)
|
||||
{
|
||||
MOZ_ASSERT(!initialized());
|
||||
code_ = &code;
|
||||
|
||||
MOZ_ASSERT(lazyStubs_.lock()->empty());
|
||||
|
||||
// See comments in CodeSegment::initialize() for why this must be last.
|
||||
if (!segment_->initialize(*this, linkData, metadata, *metadata_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(initialized());
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
CodeTier::serializedSize() const
|
||||
{
|
||||
|
@ -1222,11 +1238,11 @@ Code::Code(UniqueCodeTier tier1, const Metadata& metadata, JumpTables&& maybeJum
|
|||
{}
|
||||
|
||||
bool
|
||||
Code::initialize(const ShareableBytes& bytecode, const LinkData& linkData)
|
||||
Code::initialize(const LinkData& linkData)
|
||||
{
|
||||
MOZ_ASSERT(!initialized());
|
||||
|
||||
if (!tier1_->initialize(*this, bytecode, linkData, *metadata_)) {
|
||||
if (!tier1_->initialize(*this, linkData, *metadata_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1235,13 +1251,12 @@ Code::initialize(const ShareableBytes& bytecode, const LinkData& linkData)
|
|||
}
|
||||
|
||||
bool
|
||||
Code::setTier2(UniqueCodeTier tier2, const ShareableBytes& bytecode,
|
||||
const LinkData& linkData) const
|
||||
Code::setTier2(UniqueCodeTier tier2, const LinkData& linkData) const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!hasTier2());
|
||||
MOZ_RELEASE_ASSERT(tier2->tier() == Tier::Ion && tier1_->tier() == Tier::Baseline);
|
||||
|
||||
if (!tier2->initialize(*this, bytecode, linkData, *metadata_)) {
|
||||
if (!tier2->initialize(*this, linkData, *metadata_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1415,7 +1430,7 @@ Code::lookupTrap(void* pc, Trap* trapOut, BytecodeOffset* bytecode) const
|
|||
// since, once we start sampling, we'll be in a signal-handing context where we
|
||||
// cannot malloc.
|
||||
void
|
||||
Code::ensureProfilingLabels(const Bytes* maybeBytecode, bool profilingEnabled) const
|
||||
Code::ensureProfilingLabels(bool profilingEnabled) const
|
||||
{
|
||||
auto labels = profilingLabels_.lock();
|
||||
|
||||
|
@ -1441,7 +1456,7 @@ Code::ensureProfilingLabels(const Bytes* maybeBytecode, bool profilingEnabled) c
|
|||
MOZ_ASSERT(bytecodeStr);
|
||||
|
||||
UTF8Bytes name;
|
||||
if (!metadata().getFuncNameStandalone(maybeBytecode, codeRange.funcIndex(), &name)) {
|
||||
if (!metadata().getFuncNameStandalone(codeRange.funcIndex(), &name)) {
|
||||
return;
|
||||
}
|
||||
if (!name.append(" (", 2)) {
|
||||
|
@ -1515,26 +1530,6 @@ Code::addSizeOfMiscIfNotSeen(MallocSizeOf mallocSizeOf,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CodeTier::initialize(const Code& code,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
const Metadata& metadata)
|
||||
{
|
||||
MOZ_ASSERT(!initialized());
|
||||
code_ = &code;
|
||||
|
||||
MOZ_ASSERT(lazyStubs_.lock()->empty());
|
||||
|
||||
// See comments in CodeSegment::initialize() for why this must be last.
|
||||
if (!segment_->initialize(*this, bytecode, linkData, metadata, *metadata_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(initialized());
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
Code::serializedSize() const
|
||||
{
|
||||
|
@ -1554,7 +1549,6 @@ Code::serialize(uint8_t* cursor, const LinkData& linkData) const
|
|||
|
||||
/* static */ const uint8_t*
|
||||
Code::deserialize(const uint8_t* cursor,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
Metadata& metadata,
|
||||
SharedCode* out)
|
||||
|
@ -1576,7 +1570,7 @@ Code::deserialize(const uint8_t* cursor,
|
|||
}
|
||||
|
||||
MutableCode code = js_new<Code>(std::move(codeTier), metadata, std::move(jumpTables));
|
||||
if (!code || !code->initialize(bytecode, linkData)) {
|
||||
if (!code || !code->initialize(linkData)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,6 @@ class ModuleSegment : public CodeSegment
|
|||
const LinkData& linkData);
|
||||
|
||||
bool initialize(const CodeTier& codeTier,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
const Metadata& metadata,
|
||||
const MetadataTier& metadataTier);
|
||||
|
@ -327,44 +326,6 @@ enum class MemoryUsage
|
|||
Shared = 2
|
||||
};
|
||||
|
||||
// NameInBytecode represents a name that is embedded in the wasm bytecode.
|
||||
// The presence of NameInBytecode implies that bytecode has been kept.
|
||||
|
||||
struct NameInBytecode
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
|
||||
NameInBytecode()
|
||||
: offset(UINT32_MAX), length(0)
|
||||
{}
|
||||
NameInBytecode(uint32_t offset, uint32_t length)
|
||||
: offset(offset), length(length)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef Vector<NameInBytecode, 0, SystemAllocPolicy> NameInBytecodeVector;
|
||||
|
||||
// CustomSection represents a custom section in the bytecode which can be
|
||||
// extracted via Module.customSections. The (offset, length) pair does not
|
||||
// include the custom section name.
|
||||
|
||||
struct CustomSection
|
||||
{
|
||||
NameInBytecode name;
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
|
||||
CustomSection() = default;
|
||||
CustomSection(NameInBytecode name, uint32_t offset, uint32_t length)
|
||||
: name(name), offset(offset), length(length)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef Vector<CustomSection, 0, SystemAllocPolicy> CustomSectionVector;
|
||||
typedef Vector<ValTypeVector, 0, SystemAllocPolicy> FuncArgTypesVector;
|
||||
typedef Vector<ExprType, 0, SystemAllocPolicy> FuncReturnTypesVector;
|
||||
|
||||
// Metadata holds all the data that is needed to describe compiled wasm code
|
||||
// at runtime (as opposed to data that is only used to statically link or
|
||||
// instantiate a module).
|
||||
|
@ -386,7 +347,7 @@ struct MetadataCacheablePod
|
|||
uint32_t globalDataLength;
|
||||
Maybe<uint32_t> maxMemoryLength;
|
||||
Maybe<uint32_t> startFuncIndex;
|
||||
Maybe<NameInBytecode> moduleName;
|
||||
Maybe<uint32_t> nameCustomSectionIndex;
|
||||
bool filenameIsURL;
|
||||
|
||||
explicit MetadataCacheablePod(ModuleKind kind)
|
||||
|
@ -400,17 +361,24 @@ struct MetadataCacheablePod
|
|||
};
|
||||
|
||||
typedef uint8_t ModuleHash[8];
|
||||
typedef Vector<ValTypeVector, 0, SystemAllocPolicy> FuncArgTypesVector;
|
||||
typedef Vector<ExprType, 0, SystemAllocPolicy> FuncReturnTypesVector;
|
||||
|
||||
struct Metadata : public ShareableBase<Metadata>, public MetadataCacheablePod
|
||||
{
|
||||
FuncTypeWithIdVector funcTypeIds;
|
||||
GlobalDescVector globals;
|
||||
TableDescVector tables;
|
||||
NameInBytecodeVector funcNames;
|
||||
CustomSectionVector customSections;
|
||||
CacheableChars filename;
|
||||
CacheableChars sourceMapURL;
|
||||
|
||||
// namePayload points at the name section's CustomSection::payload so that
|
||||
// the Names (which are use payload-relative offsets) can be used
|
||||
// independently of the Module without duplicating the name section.
|
||||
SharedBytes namePayload;
|
||||
Maybe<Name> moduleName;
|
||||
NameVector funcNames;
|
||||
|
||||
// Debug-enabled code is not serialized.
|
||||
bool debugEnabled;
|
||||
FuncArgTypesVector debugFuncArgTypes;
|
||||
|
@ -459,14 +427,13 @@ struct Metadata : public ShareableBase<Metadata>, public MetadataCacheablePod
|
|||
|
||||
enum NameContext { Standalone, BeforeLocation };
|
||||
|
||||
virtual bool getFuncName(NameContext ctx, const Bytes* maybeBytecode, uint32_t funcIndex,
|
||||
UTF8Bytes* name) const;
|
||||
virtual bool getFuncName(NameContext ctx, uint32_t funcIndex, UTF8Bytes* name) const;
|
||||
|
||||
bool getFuncNameStandalone(const Bytes* maybeBytecode, uint32_t funcIndex, UTF8Bytes* name) const {
|
||||
return getFuncName(NameContext::Standalone, maybeBytecode, funcIndex, name);
|
||||
bool getFuncNameStandalone(uint32_t funcIndex, UTF8Bytes* name) const {
|
||||
return getFuncName(NameContext::Standalone, funcIndex, name);
|
||||
}
|
||||
bool getFuncNameBeforeLocation(const Bytes* maybeBytecode, uint32_t funcIndex, UTF8Bytes* name) const {
|
||||
return getFuncName(NameContext::BeforeLocation, maybeBytecode, funcIndex, name);
|
||||
bool getFuncNameBeforeLocation(uint32_t funcIndex, UTF8Bytes* name) const {
|
||||
return getFuncName(NameContext::BeforeLocation, funcIndex, name);
|
||||
}
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE_VIRTUAL(Metadata);
|
||||
|
@ -634,11 +601,7 @@ class CodeTier
|
|||
{}
|
||||
|
||||
bool initialized() const { return !!code_ && segment_->initialized(); }
|
||||
|
||||
bool initialize(const Code& code,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
const Metadata& metadata);
|
||||
bool initialize(const Code& code, const LinkData& linkData, const Metadata& metadata);
|
||||
|
||||
Tier tier() const { return segment_->tier(); }
|
||||
const ExclusiveData<LazyStubTier>& lazyStubs() const { return lazyStubs_; }
|
||||
|
@ -730,7 +693,7 @@ class Code : public ShareableBase<Code>
|
|||
JumpTables&& maybeJumpTables);
|
||||
bool initialized() const { return tier1_->initialized(); }
|
||||
|
||||
bool initialize(const ShareableBytes& bytecode, const LinkData& linkData);
|
||||
bool initialize(const LinkData& linkData);
|
||||
|
||||
void setTieringEntry(size_t i, void* target) const { jumpTables_.setTieringEntry(i, target); }
|
||||
void** tieringJumpTable() const { return jumpTables_.tiering(); }
|
||||
|
@ -739,8 +702,7 @@ class Code : public ShareableBase<Code>
|
|||
void** getAddressOfJitEntry(size_t i) const { return jumpTables_.getAddressOfJitEntry(i); }
|
||||
uint32_t getFuncIndex(JSFunction* fun) const;
|
||||
|
||||
bool setTier2(UniqueCodeTier tier2, const ShareableBytes& bytecode,
|
||||
const LinkData& linkData) const;
|
||||
bool setTier2(UniqueCodeTier tier2, const LinkData& linkData) const;
|
||||
void commitTier2() const;
|
||||
|
||||
bool hasTier2() const { return hasTier2_; }
|
||||
|
@ -770,7 +732,7 @@ class Code : public ShareableBase<Code>
|
|||
// To save memory, profilingLabels_ are generated lazily when profiling mode
|
||||
// is enabled.
|
||||
|
||||
void ensureProfilingLabels(const Bytes* maybeBytecode, bool profilingEnabled) const;
|
||||
void ensureProfilingLabels(bool profilingEnabled) const;
|
||||
const char* profilingLabel(uint32_t funcIndex) const;
|
||||
|
||||
// about:memory reporting:
|
||||
|
@ -788,7 +750,6 @@ class Code : public ShareableBase<Code>
|
|||
size_t serializedSize() const;
|
||||
uint8_t* serialize(uint8_t* cursor, const LinkData& linkData) const;
|
||||
static const uint8_t* deserialize(const uint8_t* cursor,
|
||||
const ShareableBytes& bytecode,
|
||||
const LinkData& linkData,
|
||||
Metadata& metadata,
|
||||
SharedCode* code);
|
||||
|
|
|
@ -543,12 +543,13 @@ wasm::CompileBuffer(const CompileArgs& args, const ShareableBytes& bytecode, Uni
|
|||
}
|
||||
|
||||
void
|
||||
wasm::CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancelled)
|
||||
wasm::CompileTier2(const CompileArgs& args, const Bytes& bytecode, const Module& module,
|
||||
Atomic<bool>* cancelled)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(wasm::HaveSignalHandlers());
|
||||
|
||||
UniqueChars error;
|
||||
Decoder d(module.bytecode().bytes, 0, &error);
|
||||
Decoder d(bytecode, 0, &error);
|
||||
|
||||
HasGcTypes gcTypesConfigured = HasGcTypes::False; // No Ion support yet
|
||||
CompilerEnvironment compilerEnv(CompileMode::Tier2, Tier::Ion, DebugEnabled::False,
|
||||
|
|
|
@ -92,7 +92,8 @@ CompileBuffer(const CompileArgs& args,
|
|||
// Attempt to compile the second tier of the given wasm::Module.
|
||||
|
||||
void
|
||||
CompileTier2(const CompileArgs& args, Module& module, Atomic<bool>* cancelled);
|
||||
CompileTier2(const CompileArgs& args, const Bytes& bytecode, const Module& module,
|
||||
Atomic<bool>* cancelled);
|
||||
|
||||
// Compile the given WebAssembly module which has been broken into three
|
||||
// partitions:
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include "gc/FreeOp.h"
|
||||
#include "jit/ExecutableAllocator.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
#include "wasm/WasmValidate.h"
|
||||
|
@ -36,26 +34,16 @@ using namespace js::wasm;
|
|||
|
||||
using mozilla::BinarySearchIf;
|
||||
|
||||
DebugState::DebugState(SharedCode code,
|
||||
const ShareableBytes* maybeBytecode,
|
||||
bool binarySource)
|
||||
: code_(std::move(code)),
|
||||
maybeBytecode_(maybeBytecode),
|
||||
DebugState::DebugState(const Code& code, const Module& module, bool binarySource)
|
||||
: code_(&code),
|
||||
module_(&module),
|
||||
binarySource_(binarySource),
|
||||
enterFrameTrapsEnabled_(false),
|
||||
enterAndLeaveFrameTrapsCounter_(0)
|
||||
{
|
||||
MOZ_ASSERT_IF(debugEnabled(), maybeBytecode);
|
||||
MOZ_ASSERT(code.metadata().debugEnabled);
|
||||
}
|
||||
|
||||
const char enabledMessage[] =
|
||||
"Restart with developer tools open to view WebAssembly source.";
|
||||
|
||||
const char noBinarySource[] =
|
||||
"Configure the debugger to display WebAssembly bytecode.";
|
||||
|
||||
const char notGeneratedMessage[] =
|
||||
"WebAssembly text generation was disabled.";
|
||||
|
||||
static const uint32_t DefaultBinarySourceColumnNumber = 1;
|
||||
|
||||
static const CallSite*
|
||||
|
@ -69,32 +57,9 @@ SlowCallSiteSearchByOffset(const MetadataTier& metadata, uint32_t offset)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
JSString*
|
||||
DebugState::createText(JSContext* cx)
|
||||
{
|
||||
StringBuffer buffer(cx);
|
||||
if (!maybeBytecode_) {
|
||||
if (!buffer.append(enabledMessage)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (binarySource_) {
|
||||
if (!buffer.append(notGeneratedMessage)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!buffer.append(noBinarySource)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return buffer.finishString();
|
||||
}
|
||||
|
||||
bool
|
||||
DebugState::getLineOffsets(JSContext* cx, size_t lineno, Vector<uint32_t>* offsets)
|
||||
{
|
||||
if (!debugEnabled()) {
|
||||
return true;
|
||||
}
|
||||
if (!binarySource_) {
|
||||
return true;
|
||||
}
|
||||
|
@ -108,9 +73,6 @@ DebugState::getLineOffsets(JSContext* cx, size_t lineno, Vector<uint32_t>* offse
|
|||
bool
|
||||
DebugState::getAllColumnOffsets(JSContext* cx, Vector<ExprLoc>* offsets)
|
||||
{
|
||||
if (!metadata().debugEnabled) {
|
||||
return true;
|
||||
}
|
||||
if (!binarySource_) {
|
||||
return true;
|
||||
}
|
||||
|
@ -127,38 +89,23 @@ DebugState::getAllColumnOffsets(JSContext* cx, Vector<ExprLoc>* offsets)
|
|||
}
|
||||
|
||||
bool
|
||||
DebugState::getOffsetLocation(JSContext* cx, uint32_t offset, bool* found, size_t* lineno, size_t* column)
|
||||
DebugState::getOffsetLocation(uint32_t offset, size_t* lineno, size_t* column)
|
||||
{
|
||||
*found = false;
|
||||
if (!debugEnabled()) {
|
||||
return true;
|
||||
}
|
||||
if (!binarySource_) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (!SlowCallSiteSearchByOffset(metadata(Tier::Debug), offset)) {
|
||||
return true; // offset was not found
|
||||
return false;
|
||||
}
|
||||
*found = true;
|
||||
*lineno = offset;
|
||||
*column = DefaultBinarySourceColumnNumber;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DebugState::totalSourceLines(JSContext* cx, uint32_t* count)
|
||||
uint32_t
|
||||
DebugState::totalSourceLines()
|
||||
{
|
||||
*count = 0;
|
||||
if (!debugEnabled()) {
|
||||
return true;
|
||||
}
|
||||
if (!binarySource_) {
|
||||
return true;
|
||||
}
|
||||
if (maybeBytecode_) {
|
||||
*count = maybeBytecode_->length();
|
||||
}
|
||||
return true;
|
||||
return binarySource_ ? bytecode().length() : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -170,7 +117,6 @@ DebugState::stepModeEnabled(uint32_t funcIndex) const
|
|||
bool
|
||||
DebugState::incrementStepModeCount(JSContext* cx, uint32_t funcIndex)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
const CodeRange& codeRange = codeRanges(Tier::Debug)[funcToCodeRangeIndex(funcIndex)];
|
||||
MOZ_ASSERT(codeRange.isFunction());
|
||||
|
||||
|
@ -204,7 +150,6 @@ DebugState::incrementStepModeCount(JSContext* cx, uint32_t funcIndex)
|
|||
bool
|
||||
DebugState::decrementStepModeCount(FreeOp* fop, uint32_t funcIndex)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
const CodeRange& codeRange = codeRanges(Tier::Debug)[funcToCodeRangeIndex(funcIndex)];
|
||||
MOZ_ASSERT(codeRange.isFunction());
|
||||
|
||||
|
@ -237,16 +182,12 @@ DebugState::decrementStepModeCount(FreeOp* fop, uint32_t funcIndex)
|
|||
bool
|
||||
DebugState::hasBreakpointTrapAtOffset(uint32_t offset)
|
||||
{
|
||||
if (!debugEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return SlowCallSiteSearchByOffset(metadata(Tier::Debug), offset);
|
||||
}
|
||||
|
||||
void
|
||||
DebugState::toggleBreakpointTrap(JSRuntime* rt, uint32_t offset, bool enabled)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
const CallSite* callSite = SlowCallSiteSearchByOffset(metadata(Tier::Debug), offset);
|
||||
if (!callSite) {
|
||||
return;
|
||||
|
@ -364,7 +305,6 @@ DebugState::toggleDebugTrap(uint32_t offset, bool enabled)
|
|||
void
|
||||
DebugState::adjustEnterAndLeaveFrameTrapsState(JSContext* cx, bool enabled)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
MOZ_ASSERT_IF(!enabled, enterAndLeaveFrameTrapsCounter_ > 0);
|
||||
|
||||
bool wasEnabled = enterAndLeaveFrameTrapsCounter_ > 0;
|
||||
|
@ -390,11 +330,21 @@ DebugState::adjustEnterAndLeaveFrameTrapsState(JSContext* cx, bool enabled)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
DebugState::ensureEnterFrameTrapsState(JSContext* cx, bool enabled)
|
||||
{
|
||||
if (enterFrameTrapsEnabled_ == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
adjustEnterAndLeaveFrameTrapsState(cx, enabled);
|
||||
|
||||
enterFrameTrapsEnabled_ = enabled;
|
||||
}
|
||||
|
||||
bool
|
||||
DebugState::debugGetLocalTypes(uint32_t funcIndex, ValTypeVector* locals, size_t* argsLength)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
|
||||
const ValTypeVector& args = metadata().debugFuncArgTypes[funcIndex];
|
||||
*argsLength = args.length();
|
||||
if (!locals->appendAll(args)) {
|
||||
|
@ -404,17 +354,15 @@ DebugState::debugGetLocalTypes(uint32_t funcIndex, ValTypeVector* locals, size_t
|
|||
// Decode local var types from wasm binary function body.
|
||||
const CodeRange& range = codeRanges(Tier::Debug)[funcToCodeRangeIndex(funcIndex)];
|
||||
// In wasm, the Code points to the function start via funcLineOrBytecode.
|
||||
MOZ_ASSERT(!metadata().isAsmJS() && maybeBytecode_);
|
||||
size_t offsetInModule = range.funcLineOrBytecode();
|
||||
Decoder d(maybeBytecode_->begin() + offsetInModule, maybeBytecode_->end(),
|
||||
offsetInModule, /* error = */ nullptr);
|
||||
Decoder d(bytecode().begin() + offsetInModule, bytecode().end(), offsetInModule,
|
||||
/* error = */ nullptr);
|
||||
return DecodeValidatedLocalEntries(d, locals);
|
||||
}
|
||||
|
||||
ExprType
|
||||
DebugState::debugGetResultType(uint32_t funcIndex)
|
||||
{
|
||||
MOZ_ASSERT(debugEnabled());
|
||||
return metadata().debugFuncReturnTypes[funcIndex];
|
||||
}
|
||||
|
||||
|
@ -475,77 +423,21 @@ DebugState::getGlobal(Instance& instance, uint32_t globalIndex, MutableHandleVal
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
JSString*
|
||||
DebugState::debugDisplayURL(JSContext* cx) const
|
||||
{
|
||||
// Build wasm module URL from following parts:
|
||||
// - "wasm:" as protocol;
|
||||
// - URI encoded filename from metadata (if can be encoded), plus ":";
|
||||
// - 64-bit hash of the module bytes (as hex dump).
|
||||
|
||||
js::StringBuffer result(cx);
|
||||
if (!result.append("wasm:")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (const char* filename = metadata().filename.get()) {
|
||||
// EncodeURI returns false due to invalid chars or OOM -- fail only
|
||||
// during OOM.
|
||||
JSString* filenamePrefix = EncodeURI(cx, filename, strlen(filename));
|
||||
if (!filenamePrefix) {
|
||||
if (cx->isThrowingOutOfMemory()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!cx->isThrowingOverRecursed());
|
||||
cx->clearPendingException(); // ignore invalid URI
|
||||
} else if (!result.append(filenamePrefix)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata().debugEnabled) {
|
||||
if (!result.append(":")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ModuleHash& hash = metadata().debugHash;
|
||||
for (size_t i = 0; i < sizeof(ModuleHash); i++) {
|
||||
char digit1 = hash[i] / 16, digit2 = hash[i] % 16;
|
||||
if (!result.append((char)(digit1 < 10 ? digit1 + '0' : digit1 + 'a' - 10))) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!result.append((char)(digit2 < 10 ? digit2 + '0' : digit2 + 'a' - 10))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.finishString();
|
||||
}
|
||||
|
||||
bool
|
||||
DebugState::getSourceMappingURL(JSContext* cx, MutableHandleString result) const
|
||||
{
|
||||
result.set(nullptr);
|
||||
if (!maybeBytecode_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const CustomSection& customSection : metadata().customSections) {
|
||||
const NameInBytecode& sectionName = customSection.name;
|
||||
if (strlen(SourceMappingURLSectionName) != sectionName.length ||
|
||||
memcmp(SourceMappingURLSectionName, maybeBytecode_->begin() + sectionName.offset,
|
||||
sectionName.length) != 0)
|
||||
for (const CustomSection& customSection : module_->customSections()) {
|
||||
const Bytes& sectionName = customSection.name;
|
||||
if (strlen(SourceMappingURLSectionName) != sectionName.length() ||
|
||||
memcmp(SourceMappingURLSectionName, sectionName.begin(), sectionName.length()) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse found "SourceMappingURL" custom section.
|
||||
Decoder d(maybeBytecode_->begin() + customSection.offset,
|
||||
maybeBytecode_->begin() + customSection.offset + customSection.length,
|
||||
customSection.offset,
|
||||
Decoder d(customSection.payload->begin(), customSection.payload->end(), 0,
|
||||
/* error = */ nullptr);
|
||||
uint32_t nchars;
|
||||
if (!d.readVarU32(&nchars)) {
|
||||
|
@ -587,7 +479,5 @@ DebugState::addSizeOfMisc(MallocSizeOf mallocSizeOf,
|
|||
size_t* data) const
|
||||
{
|
||||
code_->addSizeOfMiscIfNotSeen(mallocSizeOf, seenMetadata, seenCode, code, data);
|
||||
if (maybeBytecode_) {
|
||||
*data += maybeBytecode_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenBytes);
|
||||
}
|
||||
module_->addSizeOfMisc(mallocSizeOf, seenMetadata, seenBytes, seenCode, code, data);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define wasm_debug_h
|
||||
|
||||
#include "js/HashTable.h"
|
||||
#include "wasm/WasmCode.h"
|
||||
#include "wasm/WasmModule.h"
|
||||
#include "wasm/WasmTypes.h"
|
||||
|
||||
namespace js {
|
||||
|
@ -55,13 +55,14 @@ typedef HashMap<uint32_t, WasmBreakpointSite*, DefaultHasher<uint32_t>, SystemAl
|
|||
class DebugState
|
||||
{
|
||||
const SharedCode code_;
|
||||
const SharedBytes maybeBytecode_;
|
||||
const SharedModule module_;
|
||||
bool binarySource_;
|
||||
|
||||
// State maintained when debugging is enabled. In this case, the Code is
|
||||
// not actually shared, but is referenced uniquely by the instance that is
|
||||
// being debugged.
|
||||
|
||||
bool enterFrameTrapsEnabled_;
|
||||
uint32_t enterAndLeaveFrameTrapsCounter_;
|
||||
WasmBreakpointSiteMap breakpointSites_;
|
||||
StepModeCounters stepModeCounters_;
|
||||
|
@ -69,24 +70,23 @@ class DebugState
|
|||
void toggleDebugTrap(uint32_t offset, bool enabled);
|
||||
|
||||
public:
|
||||
DebugState(SharedCode code,
|
||||
const ShareableBytes* maybeBytecode,
|
||||
bool binarySource);
|
||||
DebugState(const Code& code, const Module& module, bool binarySource);
|
||||
|
||||
const Bytes* maybeBytecode() const { return maybeBytecode_ ? &maybeBytecode_->bytes : nullptr; }
|
||||
const Bytes& bytecode() const { return module_->debugBytecode(); }
|
||||
bool binarySource() const { return binarySource_; }
|
||||
|
||||
JSString* createText(JSContext* cx);
|
||||
bool getLineOffsets(JSContext* cx, size_t lineno, Vector<uint32_t>* offsets);
|
||||
bool getAllColumnOffsets(JSContext* cx, Vector<ExprLoc>* offsets);
|
||||
bool getOffsetLocation(JSContext* cx, uint32_t offset, bool* found, size_t* lineno, size_t* column);
|
||||
bool totalSourceLines(JSContext* cx, uint32_t* count);
|
||||
bool getOffsetLocation(uint32_t offset, size_t* lineno, size_t* column);
|
||||
uint32_t totalSourceLines();
|
||||
|
||||
// The Code can track enter/leave frame events. Any such event triggers
|
||||
// debug trap. The enter/leave frame events enabled or disabled across
|
||||
// all functions.
|
||||
|
||||
void adjustEnterAndLeaveFrameTrapsState(JSContext* cx, bool enabled);
|
||||
void ensureEnterFrameTrapsState(JSContext* cx, bool enabled);
|
||||
bool enterFrameTrapsEnabled() const { return enterFrameTrapsEnabled_; }
|
||||
|
||||
// When the Code is debugEnabled, individual breakpoints can be enabled or
|
||||
// disabled at instruction offsets.
|
||||
|
@ -113,14 +113,12 @@ class DebugState
|
|||
|
||||
// Debug URL helpers.
|
||||
|
||||
JSString* debugDisplayURL(JSContext* cx) const;
|
||||
bool getSourceMappingURL(JSContext* cx, MutableHandleString result) const;
|
||||
|
||||
// Accessors for commonly used elements of linked structures.
|
||||
|
||||
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
|
||||
const Metadata& metadata() const { return code_->metadata(); }
|
||||
bool debugEnabled() const { return metadata().debugEnabled; }
|
||||
const CodeRangeVector& codeRanges(Tier t) const { return metadata(t).codeRanges; }
|
||||
const CallSiteVector& callSites(Tier t) const { return metadata(t).callSites; }
|
||||
|
||||
|
|
|
@ -449,17 +449,11 @@ ModuleGenerator::linkCallSites()
|
|||
masm_.haltingAlign(CodeAlignment);
|
||||
|
||||
// Create far jumps for calls that have relative offsets that may otherwise
|
||||
// go out of range. Far jumps are created for two cases: direct calls
|
||||
// between function definitions and calls to trap exits by trap out-of-line
|
||||
// paths. Far jump code is shared when possible to reduce bloat. This method
|
||||
// is called both between function bodies (at a frequency determined by the
|
||||
// ISA's jump range) and once at the very end of a module's codegen after
|
||||
// all possible calls/traps have been emitted.
|
||||
// go out of range. This method is called both between function bodies (at a
|
||||
// frequency determined by the ISA's jump range) and once at the very end of
|
||||
// a module's codegen after all possible calls/traps have been emitted.
|
||||
|
||||
OffsetMap existingCallFarJumps;
|
||||
|
||||
TrapMaybeOffsetArray existingTrapFarJumps;
|
||||
|
||||
for (; lastPatchedCallSite_ < metadataTier_->callSites.length(); lastPatchedCallSite_++) {
|
||||
const CallSite& callSite = metadataTier_->callSites[lastPatchedCallSite_];
|
||||
const CallSiteTarget& target = callSiteTargets_[lastPatchedCallSite_];
|
||||
|
@ -838,7 +832,7 @@ ModuleGenerator::finishFuncDefs()
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::finishCode()
|
||||
ModuleGenerator::finishCodegen()
|
||||
{
|
||||
// Now that all functions and stubs are generated and their CodeRanges
|
||||
// known, patch all calls (which can emit far jumps) and far jumps. Linking
|
||||
|
@ -870,7 +864,7 @@ ModuleGenerator::finishCode()
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
|
||||
ModuleGenerator::finishMetadataTier()
|
||||
{
|
||||
// Assert all sorted metadata is sorted.
|
||||
#ifdef DEBUG
|
||||
|
@ -901,24 +895,6 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Copy over data from the ModuleEnvironment.
|
||||
|
||||
metadata_->memoryUsage = env_->memoryUsage;
|
||||
metadata_->temporaryGcTypesConfigured = env_->gcTypesConfigured;
|
||||
metadata_->minMemoryLength = env_->minMemoryLength;
|
||||
metadata_->maxMemoryLength = env_->maxMemoryLength;
|
||||
metadata_->startFuncIndex = env_->startFuncIndex;
|
||||
metadata_->moduleName = env_->moduleName;
|
||||
metadata_->tables = std::move(env_->tables);
|
||||
metadata_->globals = std::move(env_->globals);
|
||||
metadata_->funcNames = std::move(env_->funcNames);
|
||||
metadata_->customSections = std::move(env_->customSections);
|
||||
|
||||
// Inflate the global bytes up to page size so that the total bytes are a
|
||||
// page size (as required by the allocator functions).
|
||||
|
||||
metadata_->globalDataLength = AlignBytes(metadata_->globalDataLength, gc::SystemPageSize());
|
||||
|
||||
// These Vectors can get large and the excess capacity can be significant,
|
||||
// so realloc them down to size.
|
||||
|
||||
|
@ -931,39 +907,11 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
|
|||
metadataTier_->trapSites[trap].podResizeToFit();
|
||||
}
|
||||
|
||||
// Copy over additional debug information.
|
||||
|
||||
if (env_->debugEnabled()) {
|
||||
metadata_->debugEnabled = true;
|
||||
|
||||
const size_t numFuncTypes = env_->funcTypes.length();
|
||||
if (!metadata_->debugFuncArgTypes.resize(numFuncTypes)) {
|
||||
return false;
|
||||
}
|
||||
if (!metadata_->debugFuncReturnTypes.resize(numFuncTypes)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < numFuncTypes; i++) {
|
||||
if (!metadata_->debugFuncArgTypes[i].appendAll(env_->funcTypes[i]->args())) {
|
||||
return false;
|
||||
}
|
||||
metadata_->debugFuncReturnTypes[i] = env_->funcTypes[i]->ret();
|
||||
}
|
||||
|
||||
static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash),
|
||||
"The ModuleHash size shall not exceed the SHA1 hash size.");
|
||||
mozilla::SHA1Sum::Hash hash;
|
||||
mozilla::SHA1Sum sha1Sum;
|
||||
sha1Sum.update(bytecode.begin(), bytecode.length());
|
||||
sha1Sum.finish(hash);
|
||||
memcpy(metadata_->debugHash, hash, sizeof(ModuleHash));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UniqueModuleSegment
|
||||
ModuleGenerator::finish(const ShareableBytes& bytecode)
|
||||
UniqueCodeTier
|
||||
ModuleGenerator::finishCodeTier()
|
||||
{
|
||||
MOZ_ASSERT(finishedFuncDefs_);
|
||||
|
||||
|
@ -1001,15 +949,71 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
|
|||
|
||||
// Finish linking and metadata.
|
||||
|
||||
if (!finishCode()) {
|
||||
if (!finishCodegen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!finishMetadata(bytecode)) {
|
||||
if (!finishMetadataTier()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ModuleSegment::create(tier(), masm_, *linkData_);
|
||||
UniqueModuleSegment segment = ModuleSegment::create(tier(), masm_, *linkData_);
|
||||
if (!segment) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return js::MakeUnique<CodeTier>(std::move(metadataTier_), std::move(segment));
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::finishMetadata(const Bytes& bytecode)
|
||||
{
|
||||
// Finish initialization of Metadata, which is only needed for constructing
|
||||
// the initial Module, not for tier-2 compilation.
|
||||
MOZ_ASSERT(mode() != CompileMode::Tier2);
|
||||
|
||||
// Copy over data from the ModuleEnvironment.
|
||||
|
||||
metadata_->memoryUsage = env_->memoryUsage;
|
||||
metadata_->temporaryGcTypesConfigured = env_->gcTypesConfigured;
|
||||
metadata_->minMemoryLength = env_->minMemoryLength;
|
||||
metadata_->maxMemoryLength = env_->maxMemoryLength;
|
||||
metadata_->startFuncIndex = env_->startFuncIndex;
|
||||
metadata_->tables = std::move(env_->tables);
|
||||
metadata_->globals = std::move(env_->globals);
|
||||
metadata_->nameCustomSectionIndex = env_->nameCustomSectionIndex;
|
||||
metadata_->moduleName = env_->moduleName;
|
||||
metadata_->funcNames = std::move(env_->funcNames);
|
||||
|
||||
// Copy over additional debug information.
|
||||
|
||||
if (env_->debugEnabled()) {
|
||||
metadata_->debugEnabled = true;
|
||||
|
||||
const size_t numFuncTypes = env_->funcTypes.length();
|
||||
if (!metadata_->debugFuncArgTypes.resize(numFuncTypes)) {
|
||||
return false;
|
||||
}
|
||||
if (!metadata_->debugFuncReturnTypes.resize(numFuncTypes)) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < numFuncTypes; i++) {
|
||||
if (!metadata_->debugFuncArgTypes[i].appendAll(env_->funcTypes[i]->args())) {
|
||||
return false;
|
||||
}
|
||||
metadata_->debugFuncReturnTypes[i] = env_->funcTypes[i]->ret();
|
||||
}
|
||||
|
||||
static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash),
|
||||
"The ModuleHash size shall not exceed the SHA1 hash size.");
|
||||
mozilla::SHA1Sum::Hash hash;
|
||||
mozilla::SHA1Sum sha1Sum;
|
||||
sha1Sum.update(bytecode.begin(), bytecode.length());
|
||||
sha1Sum.finish(hash);
|
||||
memcpy(metadata_->debugHash, hash, sizeof(ModuleHash));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SharedModule
|
||||
|
@ -1017,23 +1021,22 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode, UniqueLinkData* li
|
|||
{
|
||||
MOZ_ASSERT(mode() == CompileMode::Once || mode() == CompileMode::Tier1);
|
||||
|
||||
UniqueModuleSegment moduleSegment = finish(bytecode);
|
||||
if (!moduleSegment) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JumpTables jumpTables;
|
||||
if (!jumpTables.init(mode(), *moduleSegment, metadataTier_->codeRanges)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto codeTier = js::MakeUnique<CodeTier>(std::move(metadataTier_), std::move(moduleSegment));
|
||||
UniqueCodeTier codeTier = finishCodeTier();
|
||||
if (!codeTier) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JumpTables jumpTables;
|
||||
if (!jumpTables.init(mode(), codeTier->segment(), codeTier->metadata().codeRanges)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!finishMetadata(bytecode.bytes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MutableCode code = js_new<Code>(std::move(codeTier), *metadata_, std::move(jumpTables));
|
||||
if (!code || !code->initialize(bytecode, *linkData_)) {
|
||||
if (!code || !code->initialize(*linkData_)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1044,11 +1047,14 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode, UniqueLinkData* li
|
|||
}
|
||||
}
|
||||
|
||||
// Copy over data from the Bytecode, which is going away at the end of
|
||||
// compilation.
|
||||
|
||||
DataSegmentVector dataSegments;
|
||||
if (!dataSegments.reserve(env_->dataSegments.length())) {
|
||||
return nullptr;
|
||||
}
|
||||
for (DataSegmentEnv& srcSeg : env_->dataSegments) {
|
||||
for (const DataSegmentEnv& srcSeg : env_->dataSegments) {
|
||||
MutableDataSegment dstSeg = js_new<DataSegment>(srcSeg);
|
||||
if (!dstSeg) {
|
||||
return nullptr;
|
||||
|
@ -1059,8 +1065,36 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode, UniqueLinkData* li
|
|||
dataSegments.infallibleAppend(std::move(dstSeg));
|
||||
}
|
||||
|
||||
CustomSectionVector customSections;
|
||||
if (!customSections.reserve(env_->customSections.length())) {
|
||||
return nullptr;
|
||||
}
|
||||
for (const CustomSectionEnv& srcSec : env_->customSections) {
|
||||
CustomSection sec;
|
||||
if (!sec.name.append(bytecode.begin() + srcSec.nameOffset, srcSec.nameLength)) {
|
||||
return nullptr;
|
||||
}
|
||||
MutableBytes payload = js_new<ShareableBytes>();
|
||||
if (!payload) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!payload->append(bytecode.begin() + srcSec.payloadOffset, srcSec.payloadLength)) {
|
||||
return nullptr;
|
||||
}
|
||||
sec.payload = std::move(payload);
|
||||
customSections.infallibleAppend(std::move(sec));
|
||||
}
|
||||
|
||||
if (env_->nameCustomSectionIndex) {
|
||||
metadata_->namePayload = customSections[*env_->nameCustomSectionIndex].payload;
|
||||
}
|
||||
|
||||
// See Module debugCodeClaimed_ comments for why we need to make a separate
|
||||
// debug copy.
|
||||
|
||||
UniqueBytes debugUnlinkedCode;
|
||||
UniqueLinkData debugLinkData;
|
||||
const ShareableBytes* debugBytecode = nullptr;
|
||||
if (env_->debugEnabled()) {
|
||||
MOZ_ASSERT(mode() == CompileMode::Once);
|
||||
MOZ_ASSERT(tier() == Tier::Debug);
|
||||
|
@ -1073,23 +1107,28 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode, UniqueLinkData* li
|
|||
masm_.executableCopy(debugUnlinkedCode->begin(), /* flushICache = */ false);
|
||||
|
||||
debugLinkData = std::move(linkData_);
|
||||
debugBytecode = &bytecode;
|
||||
}
|
||||
|
||||
SharedModule module(js_new<Module>(*code,
|
||||
std::move(env_->imports),
|
||||
std::move(env_->exports),
|
||||
std::move(structTypes),
|
||||
std::move(dataSegments),
|
||||
std::move(env_->elemSegments),
|
||||
bytecode,
|
||||
std::move(debugUnlinkedCode),
|
||||
std::move(debugLinkData)));
|
||||
// All the components are finished, so create the complete Module and start
|
||||
// tier-2 compilation if requested.
|
||||
|
||||
MutableModule module = js_new<Module>(*code,
|
||||
std::move(env_->imports),
|
||||
std::move(env_->exports),
|
||||
std::move(structTypes),
|
||||
std::move(dataSegments),
|
||||
std::move(env_->elemSegments),
|
||||
std::move(customSections),
|
||||
std::move(debugUnlinkedCode),
|
||||
std::move(debugLinkData),
|
||||
debugBytecode);
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mode() == CompileMode::Tier1) {
|
||||
module->startTier2(*compileArgs_);
|
||||
module->startTier2(*compileArgs_, bytecode);
|
||||
}
|
||||
|
||||
if (linkData) {
|
||||
|
@ -1102,7 +1141,7 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode, UniqueLinkData* li
|
|||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::finishTier2(Module& module)
|
||||
ModuleGenerator::finishTier2(const Module& module)
|
||||
{
|
||||
MOZ_ASSERT(mode() == CompileMode::Tier2);
|
||||
MOZ_ASSERT(tier() == Tier::Ion);
|
||||
|
@ -1112,13 +1151,8 @@ ModuleGenerator::finishTier2(Module& module)
|
|||
return false;
|
||||
}
|
||||
|
||||
UniqueModuleSegment moduleSegment = finish(module.bytecode());
|
||||
if (!moduleSegment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto code = js::MakeUnique<CodeTier>(std::move(metadataTier_), std::move(moduleSegment));
|
||||
if (!code) {
|
||||
UniqueCodeTier codeTier = finishCodeTier();
|
||||
if (!codeTier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1128,7 +1162,7 @@ ModuleGenerator::finishTier2(Module& module)
|
|||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
|
||||
return module.finishTier2(*linkData_, std::move(code));
|
||||
return module.finishTier2(*linkData_, std::move(codeTier));
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
|
@ -199,9 +199,10 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
bool finishTask(CompileTask* task);
|
||||
bool launchBatchCompile();
|
||||
bool finishOutstandingTask();
|
||||
bool finishCode();
|
||||
bool finishMetadata(const ShareableBytes& bytecode);
|
||||
UniqueModuleSegment finish(const ShareableBytes& bytecode);
|
||||
bool finishCodegen();
|
||||
bool finishMetadataTier();
|
||||
UniqueCodeTier finishCodeTier();
|
||||
bool finishMetadata(const Bytes& bytecode);
|
||||
|
||||
bool isAsmJS() const { return env_->isAsmJS(); }
|
||||
Tier tier() const { return env_->tier(); }
|
||||
|
@ -231,7 +232,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
|||
// called to augment the given Module with tier 2 code.
|
||||
|
||||
SharedModule finishModule(const ShareableBytes& bytecode, UniqueLinkData* linkData = nullptr);
|
||||
MOZ_MUST_USE bool finishTier2(Module& module);
|
||||
MOZ_MUST_USE bool finishTier2(const Module& module);
|
||||
|
||||
ExclusiveDeferredValidationState& deferredValidationState() {
|
||||
return deferredValidationState_;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "jit/InlinableNatives.h"
|
||||
#include "jit/JitCommon.h"
|
||||
#include "jit/JitRealm.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "wasm/WasmBuiltins.h"
|
||||
#include "wasm/WasmModule.h"
|
||||
|
||||
|
@ -697,22 +699,23 @@ Instance::postBarrier(Instance* instance, gc::Cell** location)
|
|||
Instance::Instance(JSContext* cx,
|
||||
Handle<WasmInstanceObject*> object,
|
||||
SharedCode code,
|
||||
UniqueDebugState debug,
|
||||
UniqueTlsData tlsDataIn,
|
||||
HandleWasmMemoryObject memory,
|
||||
SharedTableVector&& tables,
|
||||
Handle<FunctionVector> funcImports,
|
||||
HandleValVector globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs)
|
||||
const WasmGlobalObjectVector& globalObjs,
|
||||
UniqueDebugState maybeDebug)
|
||||
: realm_(cx->realm()),
|
||||
object_(object),
|
||||
code_(code),
|
||||
debug_(std::move(debug)),
|
||||
tlsData_(std::move(tlsDataIn)),
|
||||
memory_(memory),
|
||||
tables_(std::move(tables)),
|
||||
enterFrameTrapsEnabled_(false)
|
||||
maybeDebug_(std::move(maybeDebug))
|
||||
{
|
||||
MOZ_ASSERT(!!maybeDebug_ == metadata().debugEnabled);
|
||||
|
||||
#ifdef DEBUG
|
||||
for (auto t : code_->tiers()) {
|
||||
MOZ_ASSERT(funcImports.length() == metadata(t).funcImports.length());
|
||||
|
@ -1145,7 +1148,7 @@ Instance::getFuncDisplayAtom(JSContext* cx, uint32_t funcIndex) const
|
|||
// The "display name" of a function is primarily shown in Error.stack which
|
||||
// also includes location, so use getFuncNameBeforeLocation.
|
||||
UTF8Bytes name;
|
||||
if (!metadata().getFuncNameBeforeLocation(debug_->maybeBytecode(), funcIndex, &name)) {
|
||||
if (!metadata().getFuncNameBeforeLocation(funcIndex, &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1155,7 +1158,7 @@ Instance::getFuncDisplayAtom(JSContext* cx, uint32_t funcIndex) const
|
|||
void
|
||||
Instance::ensureProfilingLabels(bool profilingEnabled) const
|
||||
{
|
||||
return code_->ensureProfilingLabels(debug_->maybeBytecode(), profilingEnabled);
|
||||
return code_->ensureProfilingLabels(profilingEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1191,15 +1194,63 @@ Instance::deoptimizeImportExit(uint32_t funcImportIndex)
|
|||
import.baselineScript = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Instance::ensureEnterFrameTrapsState(JSContext* cx, bool enabled)
|
||||
JSString*
|
||||
Instance::createDisplayURL(JSContext* cx)
|
||||
{
|
||||
if (enterFrameTrapsEnabled_ == enabled) {
|
||||
return;
|
||||
// In the best case, we simply have a URL, from a streaming compilation of a
|
||||
// fetched Response.
|
||||
|
||||
if (metadata().filenameIsURL) {
|
||||
return NewStringCopyZ<CanGC>(cx, metadata().filename.get());
|
||||
}
|
||||
|
||||
debug_->adjustEnterAndLeaveFrameTrapsState(cx, enabled);
|
||||
enterFrameTrapsEnabled_ = enabled;
|
||||
// Otherwise, build wasm module URL from following parts:
|
||||
// - "wasm:" as protocol;
|
||||
// - URI encoded filename from metadata (if can be encoded), plus ":";
|
||||
// - 64-bit hash of the module bytes (as hex dump).
|
||||
|
||||
StringBuffer result(cx);
|
||||
if (!result.append("wasm:")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (const char* filename = metadata().filename.get()) {
|
||||
// EncodeURI returns false due to invalid chars or OOM -- fail only
|
||||
// during OOM.
|
||||
JSString* filenamePrefix = EncodeURI(cx, filename, strlen(filename));
|
||||
if (!filenamePrefix) {
|
||||
if (cx->isThrowingOutOfMemory()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!cx->isThrowingOverRecursed());
|
||||
cx->clearPendingException();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!result.append(filenamePrefix)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata().debugEnabled) {
|
||||
if (!result.append(":")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ModuleHash& hash = metadata().debugHash;
|
||||
for (size_t i = 0; i < sizeof(ModuleHash); i++) {
|
||||
char digit1 = hash[i] / 16, digit2 = hash[i] % 16;
|
||||
if (!result.append((char)(digit1 < 10 ? digit1 + '0' : digit1 + 'a' - 10))) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!result.append((char)(digit2 < 10 ? digit2 + '0' : digit2 + 'a' - 10))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.finishString();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1217,6 +1268,9 @@ Instance::addSizeOfMisc(MallocSizeOf mallocSizeOf,
|
|||
*data += table->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenTables);
|
||||
}
|
||||
|
||||
debug_->addSizeOfMisc(mallocSizeOf, seenMetadata, seenBytes, seenCode, code, data);
|
||||
if (maybeDebug_) {
|
||||
maybeDebug_->addSizeOfMisc(mallocSizeOf, seenMetadata, seenBytes, seenCode, code, data);
|
||||
}
|
||||
|
||||
code_->addSizeOfMiscIfNotSeen(mallocSizeOf, seenMetadata, seenCode, code, data);
|
||||
}
|
||||
|
|
|
@ -51,13 +51,12 @@ class Instance
|
|||
jit::TrampolinePtr preBarrierCode_;
|
||||
#endif
|
||||
const SharedCode code_;
|
||||
const UniqueDebugState debug_;
|
||||
const UniqueTlsData tlsData_;
|
||||
GCPtrWasmMemoryObject memory_;
|
||||
SharedTableVector tables_;
|
||||
const SharedTableVector tables_;
|
||||
DataSegmentVector passiveDataSegments_;
|
||||
ElemSegmentVector passiveElemSegments_;
|
||||
bool enterFrameTrapsEnabled_;
|
||||
const UniqueDebugState maybeDebug_;
|
||||
|
||||
// Internal helpers:
|
||||
const void** addressOfFuncTypeId(const FuncTypeIdDesc& funcTypeId) const;
|
||||
|
@ -75,13 +74,13 @@ class Instance
|
|||
Instance(JSContext* cx,
|
||||
HandleWasmInstanceObject object,
|
||||
SharedCode code,
|
||||
UniqueDebugState debug,
|
||||
UniqueTlsData tlsData,
|
||||
HandleWasmMemoryObject memory,
|
||||
SharedTableVector&& tables,
|
||||
Handle<FunctionVector> funcImports,
|
||||
HandleValVector globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs);
|
||||
const WasmGlobalObjectVector& globalObjs,
|
||||
UniqueDebugState maybeDebug);
|
||||
~Instance();
|
||||
bool init(JSContext* cx,
|
||||
const DataSegmentVector& dataSegments,
|
||||
|
@ -91,8 +90,8 @@ class Instance
|
|||
JS::Realm* realm() const { return realm_; }
|
||||
const Code& code() const { return *code_; }
|
||||
const CodeTier& code(Tier t) const { return code_->codeTier(t); }
|
||||
DebugState& debug() { return *debug_; }
|
||||
const DebugState& debug() const { return *debug_; }
|
||||
bool debugEnabled() const { return !!maybeDebug_; }
|
||||
DebugState& debug() { return *maybeDebug_; }
|
||||
const ModuleSegment& moduleSegment(Tier t) const { return code_->segment(t); }
|
||||
TlsData* tlsData() const { return tlsData_.get(); }
|
||||
uint8_t* globalData() const { return (uint8_t*)&tlsData_->globalArea; }
|
||||
|
@ -158,11 +157,9 @@ class Instance
|
|||
|
||||
void initElems(const ElemSegment& seg, uint32_t dstOffset, uint32_t srcOffset, uint32_t len);
|
||||
|
||||
// Debug support:
|
||||
// Debugger support:
|
||||
|
||||
bool debugEnabled() const { return metadata().debugEnabled; }
|
||||
bool enterFrameTrapsEnabled() const { return enterFrameTrapsEnabled_; }
|
||||
void ensureEnterFrameTrapsState(JSContext* cx, bool enabled);
|
||||
JSString* createDisplayURL(JSContext* cx);
|
||||
|
||||
// about:memory reporting:
|
||||
|
||||
|
|
|
@ -598,7 +598,7 @@ WasmModuleObject::finalize(FreeOp* fop, JSObject* obj)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsModuleObject(JSObject* obj, Module** module)
|
||||
IsModuleObject(JSObject* obj, const Module** module)
|
||||
{
|
||||
JSObject* unwrapped = CheckedUnwrap(obj);
|
||||
if (!unwrapped || !unwrapped->is<WasmModuleObject>()) {
|
||||
|
@ -610,7 +610,7 @@ IsModuleObject(JSObject* obj, Module** module)
|
|||
}
|
||||
|
||||
static bool
|
||||
GetModuleArg(JSContext* cx, CallArgs args, const char* name, Module** module)
|
||||
GetModuleArg(JSContext* cx, CallArgs args, const char* name, const Module** module)
|
||||
{
|
||||
if (!args.requireAtLeast(cx, name, 1)) {
|
||||
return false;
|
||||
|
@ -732,7 +732,7 @@ WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
Module* module;
|
||||
const Module* module;
|
||||
if (!GetModuleArg(cx, args, "WebAssembly.Module.imports", &module)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -806,7 +806,7 @@ WasmModuleObject::exports(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
Module* module;
|
||||
const Module* module;
|
||||
if (!GetModuleArg(cx, args, "WebAssembly.Module.exports", &module)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -874,7 +874,7 @@ WasmModuleObject::customSections(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
Module* module;
|
||||
const Module* module;
|
||||
if (!GetModuleArg(cx, args, "WebAssembly.Module.customSections", &module)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -898,24 +898,22 @@ WasmModuleObject::customSections(JSContext* cx, unsigned argc, Value* vp)
|
|||
JS::DeflateStringToUTF8Buffer(flat, RangedPtr<char>(name.begin(), name.length()));
|
||||
}
|
||||
|
||||
const uint8_t* bytecode = module->bytecode().begin();
|
||||
|
||||
AutoValueVector elems(cx);
|
||||
RootedArrayBufferObject buf(cx);
|
||||
for (const CustomSection& sec : module->metadata().customSections) {
|
||||
if (name.length() != sec.name.length) {
|
||||
for (const CustomSection& cs : module->customSections()) {
|
||||
if (name.length() != cs.name.length()) {
|
||||
continue;
|
||||
}
|
||||
if (memcmp(name.begin(), bytecode + sec.name.offset, name.length())) {
|
||||
if (memcmp(name.begin(), cs.name.begin(), name.length())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = ArrayBufferObject::create(cx, sec.length);
|
||||
buf = ArrayBufferObject::create(cx, cs.payload->length());
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(buf->dataPointer(), bytecode + sec.offset, sec.length);
|
||||
memcpy(buf->dataPointer(), cs.payload->begin(), cs.payload->length());
|
||||
if (!elems.append(ObjectValue(*buf))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -931,7 +929,7 @@ WasmModuleObject::customSections(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
/* static */ WasmModuleObject*
|
||||
WasmModuleObject::create(JSContext* cx, Module& module, HandleObject proto)
|
||||
WasmModuleObject::create(JSContext* cx, const Module& module, HandleObject proto)
|
||||
{
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
auto* obj = NewObjectWithGivenProto<WasmModuleObject>(cx, proto);
|
||||
|
@ -939,7 +937,7 @@ WasmModuleObject::create(JSContext* cx, Module& module, HandleObject proto)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
obj->initReservedSlot(MODULE_SLOT, PrivateValue(&module));
|
||||
obj->initReservedSlot(MODULE_SLOT, PrivateValue(const_cast<Module*>(&module)));
|
||||
module.AddRef();
|
||||
// We account for the first tier here; the second tier, if different, will be
|
||||
// accounted for separately when it's been compiled.
|
||||
|
@ -1059,11 +1057,11 @@ WasmModuleObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
Module&
|
||||
const Module&
|
||||
WasmModuleObject::module() const
|
||||
{
|
||||
MOZ_ASSERT(is<WasmModuleObject>());
|
||||
return *(Module*)getReservedSlot(MODULE_SLOT).toPrivate();
|
||||
return *(const Module*)getReservedSlot(MODULE_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
@ -1159,7 +1157,6 @@ WasmInstanceObject::create(JSContext* cx,
|
|||
SharedCode code,
|
||||
const DataSegmentVector& dataSegments,
|
||||
const ElemSegmentVector& elemSegments,
|
||||
UniqueDebugState debug,
|
||||
UniqueTlsData tlsData,
|
||||
HandleWasmMemoryObject memory,
|
||||
SharedTableVector&& tables,
|
||||
|
@ -1167,7 +1164,8 @@ WasmInstanceObject::create(JSContext* cx,
|
|||
const GlobalDescVector& globals,
|
||||
HandleValVector globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs,
|
||||
HandleObject proto)
|
||||
HandleObject proto,
|
||||
UniqueDebugState maybeDebug)
|
||||
{
|
||||
UniquePtr<ExportMap> exports = js::MakeUnique<ExportMap>();
|
||||
if (!exports) {
|
||||
|
@ -1227,13 +1225,13 @@ WasmInstanceObject::create(JSContext* cx,
|
|||
auto* instance = cx->new_<Instance>(cx,
|
||||
obj,
|
||||
code,
|
||||
std::move(debug),
|
||||
std::move(tlsData),
|
||||
memory,
|
||||
std::move(tables),
|
||||
funcImports,
|
||||
globalImportValues,
|
||||
globalObjs);
|
||||
globalObjs,
|
||||
std::move(maybeDebug));
|
||||
if (!instance) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1300,7 +1298,7 @@ WasmInstanceObject::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
Module* module;
|
||||
const Module* module;
|
||||
if (!args[0].isObject() || !IsModuleObject(&args[0].toObject(), &module)) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_MOD_ARG);
|
||||
return false;
|
||||
|
@ -2686,7 +2684,7 @@ Reject(JSContext* cx, const CompileArgs& args, Handle<PromiseObject*> promise,
|
|||
}
|
||||
|
||||
static bool
|
||||
Resolve(JSContext* cx, Module& module, Handle<PromiseObject*> promise, bool instantiate,
|
||||
Resolve(JSContext* cx, const Module& module, Handle<PromiseObject*> promise, bool instantiate,
|
||||
HandleObject importObj, const UniqueCharsVector& warnings)
|
||||
{
|
||||
if (!ReportCompileWarnings(cx, warnings)) {
|
||||
|
@ -2879,7 +2877,7 @@ WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp)
|
|||
return RejectWithPendingException(cx, promise, callArgs);
|
||||
}
|
||||
|
||||
Module* module;
|
||||
const Module* module;
|
||||
if (IsModuleObject(firstArg, &module)) {
|
||||
RootedWasmInstanceObject instanceObj(cx);
|
||||
if (!Instantiate(cx, *module, importObj, &instanceObj)) {
|
||||
|
|
|
@ -107,9 +107,9 @@ class WasmModuleObject : public NativeObject
|
|||
static bool construct(JSContext*, unsigned, Value*);
|
||||
|
||||
static WasmModuleObject* create(JSContext* cx,
|
||||
wasm::Module& module,
|
||||
const wasm::Module& module,
|
||||
HandleObject proto = nullptr);
|
||||
wasm::Module& module() const;
|
||||
const wasm::Module& module() const;
|
||||
};
|
||||
|
||||
// The class of WebAssembly.Global. This wraps a storage location, and there is
|
||||
|
@ -216,7 +216,6 @@ class WasmInstanceObject : public NativeObject
|
|||
RefPtr<const wasm::Code> code,
|
||||
const wasm::DataSegmentVector& dataSegments,
|
||||
const wasm::ElemSegmentVector& elemSegments,
|
||||
UniquePtr<wasm::DebugState> debug,
|
||||
wasm::UniqueTlsData tlsData,
|
||||
HandleWasmMemoryObject memory,
|
||||
Vector<RefPtr<wasm::Table>, 0, SystemAllocPolicy>&& tables,
|
||||
|
@ -224,7 +223,8 @@ class WasmInstanceObject : public NativeObject
|
|||
const wasm::GlobalDescVector& globals,
|
||||
wasm::HandleValVector globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs,
|
||||
HandleObject proto);
|
||||
HandleObject proto,
|
||||
UniquePtr<wasm::DebugState> maybeDebug);
|
||||
void initExportsObj(JSObject& exportsObj);
|
||||
|
||||
wasm::Instance& instance() const;
|
||||
|
|
|
@ -39,14 +39,17 @@ using namespace js::wasm;
|
|||
|
||||
class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask
|
||||
{
|
||||
SharedModule module_;
|
||||
SharedCompileArgs compileArgs_;
|
||||
SharedBytes bytecode_;
|
||||
SharedModule module_;
|
||||
Atomic<bool> cancelled_;
|
||||
|
||||
public:
|
||||
Tier2GeneratorTaskImpl(Module& module, const CompileArgs& compileArgs)
|
||||
: module_(&module),
|
||||
compileArgs_(&compileArgs),
|
||||
Tier2GeneratorTaskImpl(const CompileArgs& compileArgs, const ShareableBytes& bytecode,
|
||||
Module& module)
|
||||
: compileArgs_(&compileArgs),
|
||||
bytecode_(&bytecode),
|
||||
module_(&module),
|
||||
cancelled_(false)
|
||||
{}
|
||||
|
||||
|
@ -59,16 +62,16 @@ class Module::Tier2GeneratorTaskImpl : public Tier2GeneratorTask
|
|||
}
|
||||
|
||||
void execute() override {
|
||||
CompileTier2(*compileArgs_, *module_, &cancelled_);
|
||||
CompileTier2(*compileArgs_, bytecode_->bytes, *module_, &cancelled_);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Module::startTier2(const CompileArgs& args)
|
||||
Module::startTier2(const CompileArgs& args, const ShareableBytes& bytecode)
|
||||
{
|
||||
MOZ_ASSERT(!testingTier2Active_);
|
||||
|
||||
auto task = MakeUnique<Tier2GeneratorTaskImpl>(*this, args);
|
||||
auto task = MakeUnique<Tier2GeneratorTaskImpl>(args, bytecode, *this);
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
|
@ -81,14 +84,14 @@ Module::startTier2(const CompileArgs& args)
|
|||
}
|
||||
|
||||
bool
|
||||
Module::finishTier2(const LinkData& linkData2, UniqueCodeTier code2)
|
||||
Module::finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const
|
||||
{
|
||||
MOZ_ASSERT(code().bestTier() == Tier::Baseline && code2->tier() == Tier::Ion);
|
||||
|
||||
// Install the data in the data structures. They will not be visible
|
||||
// until commitTier2().
|
||||
|
||||
if (!code().setTier2(std::move(code2), *bytecode_, linkData2)) {
|
||||
if (!code().setTier2(std::move(code2), linkData2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -173,6 +176,7 @@ Module::serializedSize(const LinkData& linkData) const
|
|||
SerializedVectorSize(structTypes_) +
|
||||
SerializedVectorSize(dataSegments_) +
|
||||
SerializedVectorSize(elemSegments_) +
|
||||
SerializedVectorSize(customSections_) +
|
||||
code_->serializedSize();
|
||||
}
|
||||
|
||||
|
@ -190,11 +194,12 @@ Module::serialize(const LinkData& linkData, uint8_t* begin, size_t size) const
|
|||
cursor = SerializeVector(cursor, structTypes_);
|
||||
cursor = SerializeVector(cursor, dataSegments_);
|
||||
cursor = SerializeVector(cursor, elemSegments_);
|
||||
cursor = SerializeVector(cursor, customSections_);
|
||||
cursor = code_->serialize(cursor, linkData);
|
||||
MOZ_RELEASE_ASSERT(cursor == begin + size);
|
||||
}
|
||||
|
||||
/* static */ SharedModule
|
||||
/* static */ MutableModule
|
||||
Module::deserialize(const uint8_t* begin, size_t size, Metadata* maybeMetadata)
|
||||
{
|
||||
MutableMetadata metadata(maybeMetadata);
|
||||
|
@ -207,13 +212,6 @@ Module::deserialize(const uint8_t* begin, size_t size, Metadata* maybeMetadata)
|
|||
|
||||
const uint8_t* cursor = begin;
|
||||
|
||||
// Temporary. (asm.js doesn't save bytecode)
|
||||
MOZ_RELEASE_ASSERT(maybeMetadata->isAsmJS());
|
||||
MutableBytes bytecode = js_new<ShareableBytes>();
|
||||
if (!bytecode) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LinkData linkData(Tier::Serialized);
|
||||
cursor = linkData.deserialize(cursor);
|
||||
if (!cursor) {
|
||||
|
@ -250,8 +248,21 @@ Module::deserialize(const uint8_t* begin, size_t size, Metadata* maybeMetadata)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CustomSectionVector customSections;
|
||||
cursor = DeserializeVector(cursor, &customSections);
|
||||
if (!cursor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (metadata->nameCustomSectionIndex) {
|
||||
metadata->namePayload = customSections[*metadata->nameCustomSectionIndex].payload;
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(!metadata->moduleName);
|
||||
MOZ_RELEASE_ASSERT(metadata->funcNames.empty());
|
||||
}
|
||||
|
||||
SharedCode code;
|
||||
cursor = Code::deserialize(cursor, *bytecode, linkData, *metadata, &code);
|
||||
cursor = Code::deserialize(cursor, linkData, *metadata, &code);
|
||||
if (!cursor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -265,7 +276,7 @@ Module::deserialize(const uint8_t* begin, size_t size, Metadata* maybeMetadata)
|
|||
std::move(structTypes),
|
||||
std::move(dataSegments),
|
||||
std::move(elemSegments),
|
||||
*bytecode);
|
||||
std::move(customSections));
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
|
@ -309,7 +320,7 @@ MapFile(PRFileDesc* file, PRFileInfo* info)
|
|||
return UniqueMapping(memory, MemUnmap(info->size));
|
||||
}
|
||||
|
||||
SharedModule
|
||||
RefPtr<JS::WasmModule>
|
||||
wasm::DeserializeModule(PRFileDesc* bytecodeFile, UniqueChars filename, unsigned line)
|
||||
{
|
||||
PRFileInfo bytecodeInfo;
|
||||
|
@ -349,7 +360,13 @@ wasm::DeserializeModule(PRFileDesc* bytecodeFile, UniqueChars filename, unsigned
|
|||
|
||||
UniqueChars error;
|
||||
UniqueCharsVector warnings;
|
||||
return CompileBuffer(*args, *bytecode, &error, &warnings);
|
||||
SharedModule module = CompileBuffer(*args, *bytecode, &error, &warnings);
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The public interface is effectively const.
|
||||
return RefPtr<JS::WasmModule>(const_cast<Module*>(module.get()));
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
|
@ -367,7 +384,7 @@ Module::addSizeOfMisc(MallocSizeOf mallocSizeOf,
|
|||
SizeOfVectorExcludingThis(structTypes_, mallocSizeOf) +
|
||||
SizeOfVectorExcludingThis(dataSegments_, mallocSizeOf) +
|
||||
SizeOfVectorExcludingThis(elemSegments_, mallocSizeOf) +
|
||||
bytecode_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenBytes);
|
||||
SizeOfVectorExcludingThis(customSections_, mallocSizeOf);
|
||||
|
||||
if (debugUnlinkedCode_) {
|
||||
*data += debugUnlinkedCode_->sizeOfExcludingThis(mallocSizeOf);
|
||||
|
@ -885,7 +902,7 @@ Module::getDebugEnabledCode() const
|
|||
}
|
||||
|
||||
MutableCode debugCode = js_new<Code>(std::move(codeTier), metadata(), std::move(jumpTables));
|
||||
if (!debugCode || !debugCode->initialize(*bytecode_, *debugLinkData_)) {
|
||||
if (!debugCode || !debugCode->initialize(*debugLinkData_)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1021,48 +1038,28 @@ Module::instantiate(JSContext* cx,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Debugging mutates code (for traps, stepping, etc) and thus may need to
|
||||
// clone the code on each instantiation.
|
||||
|
||||
SharedCode code(code_);
|
||||
SharedCode code;
|
||||
UniqueDebugState maybeDebug;
|
||||
if (metadata().debugEnabled) {
|
||||
code = getDebugEnabledCode();
|
||||
if (!code) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// To support viewing the source of an instance (Instance::createText), the
|
||||
// instance must hold onto a ref of the bytecode (keeping it alive). This
|
||||
// wastes memory for most users, so we try to only save the source when a
|
||||
// developer actually cares: when the realm is debuggable (which is true
|
||||
// when the web console is open), has code compiled with debug flag
|
||||
// enabled or a names section is present (since this going to be stripped
|
||||
// for non-developer builds).
|
||||
|
||||
const ShareableBytes* maybeBytecode = nullptr;
|
||||
if (cx->realm()->isDebuggee() || metadata().debugEnabled ||
|
||||
!metadata().funcNames.empty() || !!metadata().moduleName)
|
||||
{
|
||||
maybeBytecode = bytecode_.get();
|
||||
}
|
||||
|
||||
// The debug object must be present even when debugging is not enabled: It
|
||||
// provides the lazily created source text for the program, even if that
|
||||
// text is a placeholder message when debugging is not enabled.
|
||||
|
||||
bool binarySource = cx->realm()->debuggerObservesBinarySource();
|
||||
auto debug = cx->make_unique<DebugState>(code, maybeBytecode, binarySource);
|
||||
if (!debug) {
|
||||
return false;
|
||||
bool binarySource = cx->realm()->debuggerObservesBinarySource();
|
||||
maybeDebug = cx->make_unique<DebugState>(*code, *this, binarySource);
|
||||
if (!maybeDebug) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
code = code_;
|
||||
}
|
||||
|
||||
instance.set(WasmInstanceObject::create(cx,
|
||||
code,
|
||||
dataSegments_,
|
||||
elemSegments_,
|
||||
std::move(debug),
|
||||
std::move(tlsData),
|
||||
memory,
|
||||
std::move(tables),
|
||||
|
@ -1070,7 +1067,8 @@ Module::instantiate(JSContext* cx,
|
|||
metadata().globals,
|
||||
globalImportValues,
|
||||
globalObjs,
|
||||
instanceProto));
|
||||
instanceProto,
|
||||
std::move(maybeDebug)));
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,13 +48,13 @@ struct CompileArgs;
|
|||
|
||||
class Module : public JS::WasmModule
|
||||
{
|
||||
const SharedCode code_;
|
||||
const ImportVector imports_;
|
||||
const ExportVector exports_;
|
||||
const StructTypeVector structTypes_;
|
||||
const DataSegmentVector dataSegments_;
|
||||
const ElemSegmentVector elemSegments_;
|
||||
const SharedBytes bytecode_;
|
||||
const SharedCode code_;
|
||||
const ImportVector imports_;
|
||||
const ExportVector exports_;
|
||||
const StructTypeVector structTypes_;
|
||||
const DataSegmentVector dataSegments_;
|
||||
const ElemSegmentVector elemSegments_;
|
||||
const CustomSectionVector customSections_;
|
||||
|
||||
// These fields are only meaningful when code_->metadata().debugEnabled.
|
||||
// `debugCodeClaimed_` is set to false initially and then to true when
|
||||
|
@ -67,6 +67,7 @@ class Module : public JS::WasmModule
|
|||
mutable Atomic<bool> debugCodeClaimed_;
|
||||
const UniqueConstBytes debugUnlinkedCode_;
|
||||
const UniqueLinkData debugLinkData_;
|
||||
const SharedBytes debugBytecode_;
|
||||
|
||||
// This flag is only used for testing purposes and is racily updated as soon
|
||||
// as tier-2 compilation finishes (in success or failure).
|
||||
|
@ -96,19 +97,21 @@ class Module : public JS::WasmModule
|
|||
StructTypeVector&& structTypes,
|
||||
DataSegmentVector&& dataSegments,
|
||||
ElemSegmentVector&& elemSegments,
|
||||
const ShareableBytes& bytecode,
|
||||
CustomSectionVector&& customSections,
|
||||
UniqueConstBytes debugUnlinkedCode = nullptr,
|
||||
UniqueLinkData debugLinkData = nullptr)
|
||||
UniqueLinkData debugLinkData = nullptr,
|
||||
const ShareableBytes* debugBytecode = nullptr)
|
||||
: code_(&code),
|
||||
imports_(std::move(imports)),
|
||||
exports_(std::move(exports)),
|
||||
structTypes_(std::move(structTypes)),
|
||||
dataSegments_(std::move(dataSegments)),
|
||||
elemSegments_(std::move(elemSegments)),
|
||||
bytecode_(&bytecode),
|
||||
customSections_(std::move(customSections)),
|
||||
debugCodeClaimed_(false),
|
||||
debugUnlinkedCode_(std::move(debugUnlinkedCode)),
|
||||
debugLinkData_(std::move(debugLinkData)),
|
||||
debugBytecode_(debugBytecode),
|
||||
testingTier2Active_(false)
|
||||
{
|
||||
MOZ_ASSERT_IF(metadata().debugEnabled, debugUnlinkedCode_ && debugLinkData_);
|
||||
|
@ -121,7 +124,8 @@ class Module : public JS::WasmModule
|
|||
const MetadataTier& metadata(Tier t) const { return code_->metadata(t); }
|
||||
const ImportVector& imports() const { return imports_; }
|
||||
const ExportVector& exports() const { return exports_; }
|
||||
const ShareableBytes& bytecode() const { return *bytecode_; }
|
||||
const CustomSectionVector& customSections() const { return customSections_; }
|
||||
const Bytes& debugBytecode() const { return debugBytecode_->bytes; }
|
||||
uint32_t codeLength(Tier t) const { return code_->segment(t).length(); }
|
||||
|
||||
// Instantiate this module with the given imports:
|
||||
|
@ -140,8 +144,8 @@ class Module : public JS::WasmModule
|
|||
// finishTier2() from a helper thread, passing tier-variant data which will
|
||||
// be installed and made visible.
|
||||
|
||||
void startTier2(const CompileArgs& args);
|
||||
bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2);
|
||||
void startTier2(const CompileArgs& args, const ShareableBytes& bytecode);
|
||||
bool finishTier2(const LinkData& linkData2, UniqueCodeTier code2) const;
|
||||
|
||||
void testingBlockOnTier2Complete() const;
|
||||
bool testingTier2Active() const { return testingTier2Active_; }
|
||||
|
@ -171,11 +175,12 @@ class Module : public JS::WasmModule
|
|||
bool extractCode(JSContext* cx, Tier tier, MutableHandleValue vp) const;
|
||||
};
|
||||
|
||||
typedef RefPtr<Module> SharedModule;
|
||||
typedef RefPtr<Module> MutableModule;
|
||||
typedef RefPtr<const Module> SharedModule;
|
||||
|
||||
// JS API implementations:
|
||||
|
||||
SharedModule
|
||||
RefPtr<JS::WasmModule>
|
||||
DeserializeModule(PRFileDesc* bytecode, UniqueChars filename, unsigned line);
|
||||
|
||||
} // namespace wasm
|
||||
|
|
|
@ -73,7 +73,7 @@ wasm::Realm::registerInstance(JSContext* cx, HandleWasmInstanceObject instanceOb
|
|||
instance.ensureProfilingLabels(cx->runtime()->geckoProfiler().enabled());
|
||||
|
||||
if (instance.debugEnabled() && instance.realm()->debuggerObservesAllExecution()) {
|
||||
instance.ensureEnterFrameTrapsState(cx, true);
|
||||
instance.debug().ensureEnterFrameTrapsState(cx, true);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -517,6 +517,50 @@ DataSegment::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
|||
return bytes.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
CustomSection::serializedSize() const
|
||||
{
|
||||
return SerializedPodVectorSize(name) +
|
||||
SerializedPodVectorSize(payload->bytes);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
CustomSection::serialize(uint8_t* cursor) const
|
||||
{
|
||||
cursor = SerializePodVector(cursor, name);
|
||||
cursor = SerializePodVector(cursor, payload->bytes);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
const uint8_t*
|
||||
CustomSection::deserialize(const uint8_t* cursor)
|
||||
{
|
||||
cursor = DeserializePodVector(cursor, &name);
|
||||
if (!cursor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bytes bytes;
|
||||
cursor = DeserializePodVector(cursor, &bytes);
|
||||
if (!cursor) {
|
||||
return nullptr;
|
||||
}
|
||||
payload = js_new<ShareableBytes>(std::move(bytes));
|
||||
if (!payload) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
size_t
|
||||
CustomSection::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return name.sizeOfExcludingThis(mallocSizeOf) +
|
||||
sizeof(*payload) +
|
||||
payload->sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
// Heap length on ARM should fit in an ARM immediate. We approximate the set
|
||||
// of valid ARM immediates with the predicate:
|
||||
// 2^n for n in [16, 24)
|
||||
|
@ -922,8 +966,6 @@ wasm::LookupInSorted(const CodeRangeVector& codeRanges, CodeRange::OffsetInCode
|
|||
UniqueTlsData
|
||||
wasm::CreateTlsData(uint32_t globalDataLength)
|
||||
{
|
||||
MOZ_ASSERT(globalDataLength % gc::SystemPageSize() == 0);
|
||||
|
||||
void* allocatedBase = js_calloc(TlsDataAlign + offsetof(TlsData, globalArea) + globalDataLength);
|
||||
if (!allocatedBase) {
|
||||
return nullptr;
|
||||
|
|
|
@ -1179,6 +1179,48 @@ typedef RefPtr<DataSegment> MutableDataSegment;
|
|||
typedef SerializableRefPtr<const DataSegment> SharedDataSegment;
|
||||
typedef Vector<SharedDataSegment, 0, SystemAllocPolicy> DataSegmentVector;
|
||||
|
||||
// The CustomSection(Env) structs are like DataSegment(Env): CustomSectionEnv is
|
||||
// stored in the ModuleEnvironment and CustomSection holds a copy of the payload
|
||||
// and is stored in the wasm::Module.
|
||||
|
||||
struct CustomSectionEnv
|
||||
{
|
||||
uint32_t nameOffset;
|
||||
uint32_t nameLength;
|
||||
uint32_t payloadOffset;
|
||||
uint32_t payloadLength;
|
||||
};
|
||||
|
||||
typedef Vector<CustomSectionEnv, 0, SystemAllocPolicy> CustomSectionEnvVector;
|
||||
|
||||
struct CustomSection
|
||||
{
|
||||
Bytes name;
|
||||
SharedBytes payload;
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE(CustomSection)
|
||||
};
|
||||
|
||||
typedef Vector<CustomSection, 0, SystemAllocPolicy> CustomSectionVector;
|
||||
|
||||
// A Name represents a string of utf8 chars embedded within the name custom
|
||||
// section. The offset of a name is expressed relative to the beginning of the
|
||||
// name section's payload so that Names can stored in wasm::Code, which only
|
||||
// holds the name section's bytes, not the whole bytecode.
|
||||
|
||||
struct Name
|
||||
{
|
||||
// All fields are treated as cacheable POD:
|
||||
uint32_t offsetInNamePayload;
|
||||
uint32_t length;
|
||||
|
||||
Name()
|
||||
: offsetInNamePayload(UINT32_MAX), length(0)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef Vector<Name, 0, SystemAllocPolicy> NameVector;
|
||||
|
||||
// FuncTypeIdDesc describes a function type that can be used by call_indirect
|
||||
// and table-entry prologues to structurally compare whether the caller and
|
||||
// callee's signatures *structurally* match. To handle the general case, a
|
||||
|
|
|
@ -204,29 +204,32 @@ Decoder::startCustomSection(const char* expected, size_t expectedLength, ModuleE
|
|||
goto fail;
|
||||
}
|
||||
|
||||
NameInBytecode name;
|
||||
if (!readVarU32(&name.length) || name.length > bytesRemain()) {
|
||||
CustomSectionEnv sec;
|
||||
if (!readVarU32(&sec.nameLength) || sec.nameLength > bytesRemain()) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
name.offset = currentOffset();
|
||||
uint32_t payloadOffset = name.offset + name.length;
|
||||
sec.nameOffset = currentOffset();
|
||||
sec.payloadOffset = sec.nameOffset + sec.nameLength;
|
||||
|
||||
uint32_t payloadEnd = (*range)->start + (*range)->size;
|
||||
if (payloadOffset > payloadEnd) {
|
||||
if (sec.payloadOffset > payloadEnd) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sec.payloadLength = payloadEnd - sec.payloadOffset;
|
||||
|
||||
// Now that we have a valid custom section, record its offsets in the
|
||||
// metadata which can be queried by the user via Module.customSections.
|
||||
// Note: after an entry is appended, it may be popped if this loop or
|
||||
// the loop in startSection needs to rewind.
|
||||
if (!env->customSections.emplaceBack(name, payloadOffset, payloadEnd - payloadOffset)) {
|
||||
if (!env->customSections.append(sec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is the expected custom section, we're done.
|
||||
if (!expected || (expectedLength == name.length && !memcmp(cur_, expected, name.length))) {
|
||||
cur_ += name.length;
|
||||
if (!expected || (expectedLength == sec.nameLength && !memcmp(cur_, expected, sec.nameLength))) {
|
||||
cur_ += sec.nameLength;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2505,7 +2508,7 @@ DecodeDataSection(Decoder& d, ModuleEnvironment* env)
|
|||
}
|
||||
|
||||
static bool
|
||||
DecodeModuleNameSubsection(Decoder& d, ModuleEnvironment* env)
|
||||
DecodeModuleNameSubsection(Decoder& d, const CustomSectionEnv& nameSection, ModuleEnvironment* env)
|
||||
{
|
||||
Maybe<uint32_t> endOffset;
|
||||
if (!d.startNameSubsection(NameType::Module, &endOffset)) {
|
||||
|
@ -2515,20 +2518,16 @@ DecodeModuleNameSubsection(Decoder& d, ModuleEnvironment* env)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Don't use NameInBytecode for module name; instead store a copy of the
|
||||
// string. This way supplying a module name doesn't need to save the whole
|
||||
// bytecode. While function names are likely to be stripped in practice,
|
||||
// module names aren't necessarily.
|
||||
|
||||
uint32_t nameLength;
|
||||
if (!d.readVarU32(&nameLength)) {
|
||||
Name moduleName;
|
||||
if (!d.readVarU32(&moduleName.length)) {
|
||||
return d.fail("failed to read module name length");
|
||||
}
|
||||
|
||||
NameInBytecode moduleName(d.currentOffset(), nameLength);
|
||||
MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset);
|
||||
moduleName.offsetInNamePayload = d.currentOffset() - nameSection.payloadOffset;
|
||||
|
||||
const uint8_t* bytes;
|
||||
if (!d.readBytes(nameLength, &bytes)) {
|
||||
if (!d.readBytes(moduleName.length, &bytes)) {
|
||||
return d.fail("failed to read module name bytes");
|
||||
}
|
||||
|
||||
|
@ -2538,7 +2537,7 @@ DecodeModuleNameSubsection(Decoder& d, ModuleEnvironment* env)
|
|||
}
|
||||
|
||||
static bool
|
||||
DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
|
||||
DecodeFunctionNameSubsection(Decoder& d, const CustomSectionEnv& nameSection, ModuleEnvironment* env)
|
||||
{
|
||||
Maybe<uint32_t> endOffset;
|
||||
if (!d.startNameSubsection(NameType::Function, &endOffset)) {
|
||||
|
@ -2553,7 +2552,7 @@ DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
|
|||
return d.fail("bad function name count");
|
||||
}
|
||||
|
||||
NameInBytecodeVector funcNames;
|
||||
NameVector funcNames;
|
||||
|
||||
for (uint32_t i = 0; i < nameCount; ++i) {
|
||||
uint32_t funcIndex = 0;
|
||||
|
@ -2566,12 +2565,12 @@ DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
|
|||
return d.fail("invalid function index");
|
||||
}
|
||||
|
||||
uint32_t nameLength = 0;
|
||||
if (!d.readVarU32(&nameLength) || nameLength > MaxStringLength) {
|
||||
Name funcName;
|
||||
if (!d.readVarU32(&funcName.length) || funcName.length > MaxStringLength) {
|
||||
return d.fail("unable to read function name length");
|
||||
}
|
||||
|
||||
if (!nameLength) {
|
||||
if (!funcName.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2579,9 +2578,10 @@ DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
|
|||
return false;
|
||||
}
|
||||
|
||||
NameInBytecode funcName(d.currentOffset(), nameLength);
|
||||
MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset);
|
||||
funcName.offsetInNamePayload = d.currentOffset() - nameSection.payloadOffset;
|
||||
|
||||
if (!d.readBytes(nameLength)) {
|
||||
if (!d.readBytes(funcName.length)) {
|
||||
return d.fail("unable to read function name bytes");
|
||||
}
|
||||
|
||||
|
@ -2609,13 +2609,16 @@ DecodeNameSection(Decoder& d, ModuleEnvironment* env)
|
|||
return true;
|
||||
}
|
||||
|
||||
env->nameCustomSectionIndex = Some(env->customSections.length() - 1);
|
||||
const CustomSectionEnv& nameSection = env->customSections.back();
|
||||
|
||||
// Once started, custom sections do not report validation errors.
|
||||
|
||||
if (!DecodeModuleNameSubsection(d, env)) {
|
||||
if (!DecodeModuleNameSubsection(d, nameSection, env)) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!DecodeFunctionNameSubsection(d, env)) {
|
||||
if (!DecodeFunctionNameSubsection(d, nameSection, env)) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
|
@ -179,9 +179,10 @@ struct ModuleEnvironment
|
|||
|
||||
// Fields decoded as part of the wasm module tail:
|
||||
DataSegmentEnvVector dataSegments;
|
||||
Maybe<NameInBytecode> moduleName;
|
||||
NameInBytecodeVector funcNames;
|
||||
CustomSectionVector customSections;
|
||||
CustomSectionEnvVector customSections;
|
||||
Maybe<uint32_t> nameCustomSectionIndex;
|
||||
Maybe<Name> moduleName;
|
||||
NameVector funcNames;
|
||||
|
||||
explicit ModuleEnvironment(HasGcTypes gcTypesConfigured,
|
||||
CompilerEnvironment* compilerEnv,
|
||||
|
@ -436,7 +437,7 @@ class Encoder
|
|||
}
|
||||
|
||||
// A "section" is a contiguous range of bytes that stores its own size so
|
||||
// that it may be trivially skipped without examining the contents. Sections
|
||||
// that it may be trivially skipped without examining the payload. Sections
|
||||
// require backpatching since the size of the section is only known at the
|
||||
// end while the size's varU32 must be stored at the beginning. Immediately
|
||||
// after the section length is the string id of the section.
|
||||
|
|
|
@ -323,6 +323,26 @@ nsBlockFrame::~nsBlockFrame()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const
|
||||
{
|
||||
nsContainerFrame::AddSizeOfExcludingThisForTree(aWindowSizes);
|
||||
|
||||
// Add the size of any nsLineBox::mFrames hashtables we might have:
|
||||
for (ConstLineIterator line = LinesBegin(), line_end = LinesEnd();
|
||||
line != line_end; ++line) {
|
||||
line->AddSizeOfExcludingThis(aWindowSizes);
|
||||
}
|
||||
const FrameLines* overflowLines = GetOverflowLines();
|
||||
if (overflowLines) {
|
||||
ConstLineIterator line = overflowLines->mLines.begin(),
|
||||
line_end = overflowLines->mLines.end();
|
||||
for (; line != line_end; ++line) {
|
||||
line->AddSizeOfExcludingThis(aWindowSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
|
||||
{
|
||||
|
|
|
@ -595,6 +595,10 @@ public:
|
|||
int32_t aDepth,
|
||||
int32_t aIncrement,
|
||||
bool aForCounting) override;
|
||||
|
||||
// @see nsIFrame::AddSizeOfExcludingThisForTree
|
||||
void AddSizeOfExcludingThisForTree(nsWindowSizes&) const override;
|
||||
|
||||
protected:
|
||||
/** @see DoRemoveFrame */
|
||||
void DoRemoveFrameInternal(nsIFrame* aDeletedFrame, uint32_t aFlags,
|
||||
|
|
|
@ -3610,7 +3610,7 @@ public:
|
|||
// nsIFrames themselves are in the nsPresArena, and so are not measured here.
|
||||
// Instead, this measures heap-allocated things hanging off the nsIFrame, and
|
||||
// likewise for its descendants.
|
||||
void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
|
||||
virtual void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
|
||||
|
||||
/**
|
||||
* Return true if and only if this frame obeys visibility:hidden.
|
||||
|
|
|
@ -11,13 +11,14 @@
|
|||
#include "mozilla/ArenaObjectID.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/WritingModes.h"
|
||||
#include "nsBidiPresUtils.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
#include "nsPresArena.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "nsWindowSizes.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
static int32_t ctorCount;
|
||||
|
@ -93,6 +94,15 @@ NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
|
|||
return newLine;
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBox::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const
|
||||
{
|
||||
if (mFlags.mHasHashedFrames) {
|
||||
aSizes.mLayoutFramePropertiesSize +=
|
||||
mFrames->ShallowSizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBox::StealHashTableFrom(nsLineBox* aFromLine, uint32_t aFromLineNewCount)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ class nsLineBox;
|
|||
class nsFloatCache;
|
||||
class nsFloatCacheList;
|
||||
class nsFloatCacheFreeList;
|
||||
class nsWindowSizes;
|
||||
|
||||
// State cached after reflowing a float. This state is used during
|
||||
// incremental reflow when we avoid reflowing a float.
|
||||
|
@ -582,6 +583,8 @@ public:
|
|||
nsIFrame* LastChild() const;
|
||||
#endif
|
||||
|
||||
void AddSizeOfExcludingThis(nsWindowSizes& aSizes) const;
|
||||
|
||||
private:
|
||||
int32_t IndexOf(nsIFrame* aFrame) const;
|
||||
public:
|
||||
|
|
|
@ -2578,6 +2578,8 @@ pref("security.notification_enable_delay", 500);
|
|||
|
||||
#if defined(DEBUG) && !defined(ANDROID)
|
||||
pref("csp.content_privileged_about_uris_without_csp", "blank,printpreview,srcdoc");
|
||||
// the following pref is for testing purposes only.
|
||||
pref("csp.overrule_content_privileged_about_uris_without_csp_whitelist", false);
|
||||
#endif
|
||||
|
||||
// Default Content Security Policy to apply to signed contents.
|
||||
|
|
|
@ -1206,7 +1206,7 @@ class BootstrapScope {
|
|||
}
|
||||
|
||||
update(data, reason) {
|
||||
Management.emit("update", {id: data.id, resourceURI: data.resourceURI});
|
||||
return Management.emit("update", {id: data.id, resourceURI: data.resourceURI});
|
||||
}
|
||||
|
||||
startup(data, reason) {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</binding>
|
||||
|
||||
<binding id="basetext" extends="chrome://global/content/bindings/general.xml#basecontrol">
|
||||
<implementation implements="nsIDOMXULLabeledControlElement">
|
||||
<implementation>
|
||||
<!-- public implementation -->
|
||||
<property name="label" onset="this.setAttribute('label',val); return val;"
|
||||
onget="return this.getAttribute('label');"/>
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
var control = this.labeledControlElement;
|
||||
if (!control) {
|
||||
var bindingParent = document.getBindingParent(this);
|
||||
if (bindingParent instanceof Ci.nsIDOMXULLabeledControlElement) {
|
||||
if ("accessKey" in bindingParent) {
|
||||
control = bindingParent; // For controls that make the <label> an anon child
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</xul:moz-input-box>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMXULLabeledControlElement">
|
||||
<implementation>
|
||||
<!-- nsIDOMXULLabeledControlElement -->
|
||||
<field name="crop">""</field>
|
||||
<field name="image">""</field>
|
||||
|
|
|
@ -1797,6 +1797,10 @@ class AddonInstall {
|
|||
if (this.existingAddon) {
|
||||
await XPIInternal.BootstrapScope.get(this.existingAddon).update(
|
||||
this.addon, !this.addon.disabled, install);
|
||||
|
||||
if (this.addon.disabled) {
|
||||
flushJarCache(this.file);
|
||||
}
|
||||
} else {
|
||||
await install();
|
||||
await XPIInternal.BootstrapScope.get(this.addon).install(undefined, true);
|
||||
|
|
|
@ -1768,7 +1768,7 @@ class BootstrapScope {
|
|||
|
||||
async _install(reason, callUpdate, startup, extraArgs) {
|
||||
if (callUpdate) {
|
||||
this.callBootstrapMethod("update", reason, extraArgs);
|
||||
await this.callBootstrapMethod("update", reason, extraArgs);
|
||||
} else {
|
||||
this.callBootstrapMethod("install", reason, extraArgs);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче