This commit is contained in:
Phil Ringnalda 2016-01-09 11:40:40 -08:00
Родитель b88ea4e7ba 495196598b
Коммит c5e1a2b4ca
197 изменённых файлов: 2875 добавлений и 2746 удалений

Просмотреть файл

@ -597,7 +597,8 @@ static void
MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
{
NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
if (aAtkObj->name && newNameUTF8.Equals(aAtkObj->name))
if (aAtkObj->name &&
!strncmp(aAtkObj->name, newNameUTF8.get(), newNameUTF8.Length()))
return;
// Below we duplicate the functionality of atk_object_set_name(),

Просмотреть файл

@ -91,8 +91,13 @@ void
AccessibleWrap::Shutdown()
{
#ifdef _WIN64
if (mID != kNoID)
static_cast<DocAccessibleWrap*>(mDoc)->RemoveID(mID);
if (mID != kNoID) {
auto doc = static_cast<DocAccessibleWrap*>(mDoc);
MOZ_ASSERT(doc);
if (doc) {
doc->RemoveID(mID);
}
}
#endif
Accessible::Shutdown();

Просмотреть файл

@ -28,10 +28,6 @@
@RESPATH@/chrome/@AB_CD@.manifest
@RESPATH@/@PREF_DIR@/b2g-l10n.js
@RESPATH@/searchplugins/*
@RESPATH@/defaults/profile/bookmarks.html
@RESPATH@/defaults/profile/localstore.rdf
@RESPATH@/defaults/profile/mimeTypes.rdf
@RESPATH@/defaults/profile/chrome/*
#ifdef MOZ_UPDATER
@RESPATH@/update.locale
@RESPATH@/updater.ini
@ -768,7 +764,6 @@
@RESPATH@/@PREF_DIR@/channel-prefs.js
@RESPATH@/greprefs.js
@RESPATH@/defaults/autoconfig/prefcalls.js
@RESPATH@/defaults/profile/prefs.js
; Services (gre) prefs
#ifdef MOZ_SERVICES_SYNC

Просмотреть файл

@ -46,9 +46,6 @@
@RESPATH@/browser/chrome/@AB_CD@.manifest
@RESPATH@/chrome/@AB_CD@@JAREXT@
@RESPATH@/chrome/@AB_CD@.manifest
@RESPATH@/browser/defaults/profile/chrome/*
@RESPATH@/browser/defaults/profile/localstore.rdf
@RESPATH@/browser/defaults/profile/mimeTypes.rdf
@RESPATH@/dictionaries/*
@RESPATH@/hyphenation/*
@RESPATH@/browser/@PREF_DIR@/firefox-l10n.js
@ -704,7 +701,6 @@
@RESPATH@/browser/@PREF_DIR@/firefox-branding.js
@RESPATH@/greprefs.js
@RESPATH@/defaults/autoconfig/prefcalls.js
@RESPATH@/browser/defaults/profile/prefs.js
@RESPATH@/browser/defaults/permissions
; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)

Просмотреть файл

@ -94,21 +94,8 @@ $(STAGEDIST): $(DIST)/branding
$(DIST)/branding:
$(NSINSTALL) -D $@
PROFILE_FILES = \
localstore.rdf \
mimeTypes.rdf \
$(NULL)
PROFILE_CHROME = userChrome-example.css userContent-example.css
DEFINES += -DBOOKMARKS_INCLUDE_DIR=$(dir $(call MERGE_FILE,profile/bookmarks.inc))
libs:: $(addprefix generic/profile/,$(PROFILE_FILES))
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile
libs:: $(call MERGE_FILES,$(addprefix profile/chrome/,$(PROFILE_CHROME)))
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile/chrome
libs-%:
$(NSINSTALL) -D $(DIST)/install
@$(MAKE) -C ../../toolkit/locales libs-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'

Просмотреть файл

@ -1,50 +0,0 @@
/* 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/. */
/*
* Edit this file and copy it as userChrome.css into your
* profile-directory/chrome/
*/
/*
* This file can be used to customize the look of Mozilla's user interface
* You should consider using !important on rules which you want to
* override default settings.
*/
/*
* Do not remove the @namespace line -- it's required for correct functioning
*/
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
/*
* Some possible accessibility enhancements:
*/
/*
* Make all the default font sizes 20 pt:
*
* * {
* font-size: 20pt !important
* }
*/
/*
* Make menu items in particular 15 pt instead of the default size:
*
* menupopup > * {
* font-size: 15pt !important
* }
*/
/*
* Give the Location (URL) Bar a fixed-width font
*
* #urlbar {
* font-family: monospace !important;
* }
*/
/*
* For more examples see http://www.mozilla.org/unix/customizing.html
*/

Просмотреть файл

@ -1,32 +0,0 @@
/* 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/. */
/*
* Edit this file and copy it as userContent.css into your
* profile-directory/chrome/
*/
/*
* This file can be used to apply a style to all web pages you view
* Rules without !important are overruled by author rules if the
* author sets any. Rules with !important overrule author rules.
*/
/*
* example: give all tables a 2px border
*
* table { border: 2px solid; }
*/
/*
* example: turn off "marquee" element
*
* marquee { -moz-binding: none; }
*
*/
/*
* For more examples see http://www.mozilla.org/unix/customizing.html
*/

Просмотреть файл

@ -1,9 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<RDF:RDF
xmlns:NC="http://home.netscape.com/NC-rdf#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
</RDF:RDF>

Просмотреть файл

@ -1,17 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:NC="http://home.netscape.com/NC-rdf#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Description about="urn:mimetypes">
<NC:MIME-types>
<Seq about="urn:mimetypes:root">
</Seq>
</NC:MIME-types>
</Description>
</RDF>

Просмотреть файл

@ -1200,7 +1200,11 @@ void DiagnosticsMatcher::TrivialCtorDtorChecker::run(
"class %0 must have trivial constructors and destructors");
const CXXRecordDecl *node = Result.Nodes.getNodeAs<CXXRecordDecl>("node");
bool badCtor = !node->hasTrivialDefaultConstructor();
// We need to accept non-constexpr trivial constructors as well. This occurs
// when a struct contains pod members, which will not be initialized. As
// constexpr values are initialized, the constructor is non-constexpr.
bool badCtor = !(node->hasConstexprDefaultConstructor() ||
node->hasTrivialDefaultConstructor());
bool badDtor = !node->hasTrivialDestructor();
if (badCtor || badDtor)
Diag.Report(node->getLocStart(), errorID) << node;

Просмотреть файл

@ -5,6 +5,15 @@ struct MOZ_TRIVIAL_CTOR_DTOR EmptyClass{};
template <class T>
struct MOZ_TRIVIAL_CTOR_DTOR TemplateEmptyClass{};
struct MOZ_TRIVIAL_CTOR_DTOR NonEmptyClass {
void *m;
};
template <class T>
struct MOZ_TRIVIAL_CTOR_DTOR TemplateNonEmptyClass {
T* m;
};
struct MOZ_TRIVIAL_CTOR_DTOR BadUserDefinedCtor { // expected-error {{class 'BadUserDefinedCtor' must have trivial constructors and destructors}}
BadUserDefinedCtor() {}
};
@ -17,7 +26,7 @@ struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualDtor { // expected-error {{class 'BadVirt
virtual ~BadVirtualDtor() {}
};
struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualMember { // expected-error {{class 'BadVirtualMember' must have trivial constructors and destructors}}
struct MOZ_TRIVIAL_CTOR_DTOR OkVirtualMember {
virtual void f();
};
@ -53,6 +62,22 @@ struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialDtorInMember { // expected-error {{cla
NonTrivialDtor m;
};
struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualMemberInMember { // expected-error {{class 'BadVirtualMemberInMember' must have trivial constructors and destructors}}
struct MOZ_TRIVIAL_CTOR_DTOR OkVirtualMemberInMember {
VirtualMember m;
};
struct MOZ_TRIVIAL_CTOR_DTOR OkConstExprConstructor {
constexpr OkConstExprConstructor() {}
};
struct MOZ_TRIVIAL_CTOR_DTOR OkConstExprConstructorInMember {
OkConstExprConstructor m;
};
// XXX: This error is unfortunate, but is unlikely to come up in real code.
// In this situation, it should be possible to define a constexpr constructor
// which explicitly initializes the members.
struct MOZ_TRIVIAL_CTOR_DTOR BadUnfortunateError { // expected-error {{class 'BadUnfortunateError' must have trivial constructors and destructors}}
OkConstExprConstructor m;
void *n;
};

Просмотреть файл

@ -126,6 +126,67 @@ function* spawnTest() {
exec: {
output: 'Test Plug-in 1.0.0.0 enabled.'
}
},
{
setup: 'addon ctp Test_Plug-in_1.0.0.0',
check: {
input: 'addon ctp Test_Plug-in_1.0.0.0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
command: { name: 'addon ctp' },
addon: {
value: function(addon) {
is(addon.name, 'Test Plug-in', 'test plugin name');
},
status: 'VALID'
}
}
},
exec: {
output: 'Test Plug-in 1.0.0.0 set to click-to-play.'
}
},
{
setup: 'addon ctp OpenH264_Video_Codec_provided_by_Cisco_Systems,_Inc._null',
check: {
input: 'addon ctp OpenH264_Video_Codec_provided_by_Cisco_Systems,_Inc._null',
hints: '',
status: 'VALID',
args: {
command: { name: 'addon ctp' },
addon: {
value: function(addon) {
is(addon.name, 'OpenH264 Video Codec provided by Cisco Systems, Inc.', 'openh264');
},
status: 'VALID'
}
}
},
exec: {
output: 'OpenH264 Video Codec provided by Cisco Systems, Inc. null cannot be set to click-to-play.'
}
},
{
setup: 'addon ctp Mochitest_1.0',
check: {
input: 'addon ctp Mochitest_1.0',
hints: '',
status: 'VALID',
args: {
command: { name: 'addon ctp' },
addon: {
value: function(addon) {
is(addon.name, 'Mochitest', 'mochitest');
},
status: 'VALID'
}
}
},
exec: {
output: 'Mochitest 1.0 cannot be set to click-to-play because it is not a plugin.'
}
}
]);

Просмотреть файл

@ -189,10 +189,17 @@ exports.executeSoon = function executeSoon(aFn) {
if (isWorker) {
setImmediate(aFn);
} else {
let stack = components.stack;
let executor = () => {
Cu.callFunctionWithAsyncStack(aFn, stack, "DevToolsUtils.executeSoon");
};
let executor;
// Only enable async stack reporting when DEBUG_JS_MODULES is set
// (customized local builds) to avoid a performance penalty.
if (AppConstants.DEBUG_JS_MODULES || exports.testing) {
let stack = components.stack;
executor = () => {
Cu.callFunctionWithAsyncStack(aFn, stack, "DevToolsUtils.executeSoon");
};
} else {
executor = aFn;
}
Services.tm.mainThread.dispatch({
run: exports.makeInfallible(executor)
}, Ci.nsIThread.DISPATCH_NORMAL);

Просмотреть файл

@ -279,6 +279,41 @@ var items = [
return l10n.lookupFormat("addonAlreadyDisabled", [ name ]);
}
},
{
item: "command",
runAt: "client",
name: "addon ctp",
description: l10n.lookup("addonCtpDesc"),
params: [
{
name: "addon",
type: "addon",
description: l10n.lookup("addonNameDesc")
}
],
exec: function(args, context) {
let name = (args.addon.name + " " + args.addon.version).trim();
if (args.addon.type !== "plugin") {
return l10n.lookupFormat("addonCantCtp", [ name ]);
}
if (!args.addon.userDisabled ||
args.addon.userDisabled === true) {
args.addon.userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE;
if (args.addon.userDisabled !== AddonManager.STATE_ASK_TO_ACTIVATE) {
// Some plugins (e.g. OpenH264 shipped with Firefox) cannot be set to
// click-to-play. Handle this.
return l10n.lookupFormat("addonNoCtp", [ name ]);
}
return l10n.lookupFormat("addonCtp", [ name ]);
}
return l10n.lookupFormat("addonAlreadyCtp", [ name ]);
}
}
];

Просмотреть файл

@ -836,6 +836,30 @@ addonAlreadyDisabled=%S is already disabled.
# command when an add-on is disabled.
addonDisabled=%S disabled.
# LOCALIZATION NOTE (addonCtpDesc) A very short description of the
# 'addon ctp <type>' command. This string is designed to be shown in a menu
# alongside the command name, which is why it should be as short as possible.
addonCtpDesc=Set the specified plugin to click-to-play.
# LOCALIZATION NOTE (addonCtp) Used in the output of the 'addon ctp'
# command when a plugin is set to click-to-play.
addonCtp=%S set to click-to-play.
# LOCALIZATION NOTE (addonAlreadyCtp) Used in the output of the
# 'addon ctp' command when an attempt is made to set a plugin to
# click-to-play that is already set to click-to-play.
addonAlreadyCtp=%S is already set to click-to-play.
# LOCALIZATION NOTE (addonCantCtp) Used in the output of the 'addon
# ctp' command when an attempt is made to set an addon to click-to-play,
# but the addon is not a plugin.
addonCantCtp=%S cannot be set to click-to-play because it is not a plugin.
# LOCALIZATION NOTE (addonNoCtp) Used in the output of the 'addon
# ctp' command when an attempt is made to set an addon to click-to-play,
# but the plugin cannot be set to click-to-play for some reason.
addonNoCtp=%S cannot be set to click-to-play.
# LOCALIZATION NOTE (exportDesc) A very short description of the 'export'
# command. This string is designed to be shown in a menu alongside the command
# name, which is why it should be as short as possible.

Просмотреть файл

@ -7,6 +7,11 @@ var Cr = Components.results;
var {require} = Cu.import("resource://devtools/shared/Loader.jsm");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
DevToolsUtils.testing = true;
do_register_cleanup(() => {
DevToolsUtils.testing = false;
});
// Register a console listener, so console messages don't just disappear
// into the ether.

Просмотреть файл

@ -1271,6 +1271,13 @@ public:
return JS::AsmJSCache_Success;
}
void Cleanup()
{
#ifdef DEBUG
NoteActorDestroyed();
#endif
}
private:
~ChildRunnable()
{
@ -1329,7 +1336,7 @@ private:
ActorDestroy(ActorDestroyReason why) override
{
MOZ_ASSERT(NS_IsMainThread());
mActorDestroyed = true;
NoteActorDestroyed();
}
void
@ -1368,6 +1375,11 @@ private:
mCondVar.Notify();
}
void NoteActorDestroyed()
{
mActorDestroyed = true;
}
nsIPrincipal* const mPrincipal;
nsAutoPtr<PrincipalInfo> mPrincipalInfo;
WriteParams mWriteParams;
@ -1553,6 +1565,7 @@ OpenFile(nsIPrincipal* aPrincipal,
JS::AsmJSCacheResult openResult =
childRunnable->BlockUntilOpen(aChildRunnable);
if (openResult != JS::AsmJSCache_Success) {
childRunnable->Cleanup();
return openResult;
}

Просмотреть файл

@ -957,6 +957,32 @@ BlobImplFile::LookupAndCacheIsDirectory()
mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
}
////////////////////////////////////////////////////////////////////////////
// BlobImplEmptyFile implementation
NS_IMPL_ISUPPORTS_INHERITED0(BlobImplEmptyFile, BlobImpl)
already_AddRefed<BlobImpl>
BlobImplEmptyFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
MOZ_ASSERT(!aStart && !aLength);
RefPtr<BlobImpl> impl = new BlobImplEmptyFile(aContentType);
return impl.forget();
}
void
BlobImplEmptyFile::GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv)
{
nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
}
////////////////////////////////////////////////////////////////////////////
// BlobImplMemory implementation

Просмотреть файл

@ -833,6 +833,31 @@ private:
bool mIsTemporary;
};
class BlobImplEmptyFile final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
explicit BlobImplEmptyFile(const nsAString& aContentType)
: BlobImplBase(EmptyString(), aContentType, 0 /* aLength */)
{}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
~BlobImplEmptyFile() {}
};
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -179,6 +179,8 @@ FormData::Has(const nsAString& aName)
nsresult
FormData::AddNameFilePair(const nsAString& aName, File* aFile)
{
MOZ_ASSERT(aFile);
FormDataTuple* data = mFormData.AppendElement();
SetNameFilePair(data, aName, aFile);
return NS_OK;
@ -272,12 +274,10 @@ FormData::SetNameFilePair(FormDataTuple* aData,
File* aFile)
{
MOZ_ASSERT(aData);
MOZ_ASSERT(aFile);
aData->name = aName;
if (aFile) {
aData->value.SetAsFile() = aFile;
} else {
aData->value.SetAsUSVString() = EmptyString();
}
aData->value.SetAsFile() = aFile;
}
// -------------------------------------------------------------------------
@ -364,7 +364,7 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
fs.AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString());
} else {
fs.AddNameFilePair(mFormData[i].name, nullptr);
MOZ_CRASH("This should no be possible.");
}
}

Просмотреть файл

@ -7659,7 +7659,7 @@ nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
{
return LayoutDeviceIntPoint::FromAppUnitsRounded(
(CSSPoint::ToAppUnits(aPoint) +
aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()),
aOffset).ApplyResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(aPresContext->PresShell())),
aPresContext->AppUnitsPerDevPixel());
}

Просмотреть файл

@ -3755,8 +3755,8 @@ nsIDocument::ShouldThrottleFrameRequests()
return false;
}
if (!mIsShowing) {
// We're not showing (probably in a background tab or the bf cache).
if (Hidden()) {
// We're not visible (probably in a background tab or the bf cache).
return true;
}

Просмотреть файл

@ -258,7 +258,7 @@ protected:
void TraceWrapper(JSTracer* aTrc, const char* name)
{
if (mWrapper) {
JS_CallUnbarrieredObjectTracer(aTrc, &mWrapper, name);
js::UnsafeTraceManuallyBarrieredEdge(aTrc, &mWrapper, name);
}
}

Просмотреть файл

@ -14,7 +14,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=789315
<form id="a"><input name="b" type="file"/></form>
<script type="text/javascript">
is(new FormData(document.getElementById('a')).get('b'), "", "This should return an empty string.");
var obj = new FormData(document.getElementById('a')).get('b');
ok(obj instanceof File, "This should return an empty File");
is(obj.size, 0, "Size should be 0");
is(obj.name, "", "Name should be an empty string");
is(obj.type, "application/octet-stream", "Type should be application/octet-stream");
var o = obj.slice(10, 100, "foo/bar");
is(o.size, 0, "The new blob has size 0");
is(o.type, "foo/bar", "The new blob has type foo/bar");
</script>
</body>

Просмотреть файл

@ -2095,7 +2095,7 @@ class SequenceTracer<JSObject*, false, false, false>
public:
static void TraceSequence(JSTracer* trc, JSObject** objp, JSObject** end) {
for (; objp != end; ++objp) {
JS_CallUnbarrieredObjectTracer(trc, objp, "sequence<object>");
JS::UnsafeTraceRoot(trc, objp, "sequence<object>");
}
}
};
@ -2109,7 +2109,7 @@ class SequenceTracer<JS::Value, false, false, false>
public:
static void TraceSequence(JSTracer* trc, JS::Value* valp, JS::Value* end) {
for (; valp != end; ++valp) {
JS_CallUnbarrieredValueTracer(trc, valp, "sequence<any>");
JS::UnsafeTraceRoot(trc, valp, "sequence<any>");
}
}
};

Просмотреть файл

@ -9620,7 +9620,7 @@ class CGUnionStruct(CGThing):
if t.isObject():
traceCases.append(
CGCase("e" + vars["name"],
CGGeneric('JS_CallUnbarrieredObjectTracer(trc, %s, "%s");\n' %
CGGeneric('JS::UnsafeTraceRoot(trc, %s, "%s");\n' %
("&mValue.m" + vars["name"] + ".Value()",
"mValue.m" + vars["name"]))))
elif t.isDictionary():
@ -12603,12 +12603,12 @@ class CGDictionary(CGThing):
memberLoc)
if type.isObject():
trace = CGGeneric('JS_CallUnbarrieredObjectTracer(trc, %s, "%s");\n' %
trace = CGGeneric('JS::UnsafeTraceRoot(trc, %s, "%s");\n' %
("&"+memberData, memberName))
if type.nullable():
trace = CGIfWrapper(trace, memberData)
elif type.isAny():
trace = CGGeneric('JS_CallUnbarrieredValueTracer(trc, %s, "%s");\n' %
trace = CGGeneric('JS::UnsafeTraceRoot(trc, %s, "%s");\n' %
("&"+memberData, memberName))
elif (type.isSequence() or type.isDictionary() or
type.isSpiderMonkeyInterface() or type.isUnion()):

Просмотреть файл

@ -45,10 +45,10 @@ public:
inline void TraceSelf(JSTracer* trc)
{
if (mTypedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mTypedObj");
JS::UnsafeTraceRoot(trc, &mTypedObj, "TypedArray.mTypedObj");
}
if (mWrappedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mWrappedObj");
JS::UnsafeTraceRoot(trc, &mTypedObj, "TypedArray.mWrappedObj");
}
}

Просмотреть файл

@ -287,6 +287,20 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname)
return tmp.forget();
}
static bool
ValidateQueryEnum(WebGLContext* webgl, GLenum pname, const char* info)
{
switch (pname) {
case LOCAL_GL_QUERY_RESULT_AVAILABLE:
case LOCAL_GL_QUERY_RESULT:
return true;
default:
webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
return false;
}
}
void
WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
JS::MutableHandleValue retval)
@ -296,6 +310,9 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
if (IsContextLost())
return;
if (!ValidateQueryEnum(this, pname, "getQueryParameter"))
return;
if (!query) {
/* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1):
* If id is not the name of a query object, or if the query object
@ -330,6 +347,9 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
// We must wait for an event loop before the query can be available
if (!query->mCanBeAvailable && !gfxPrefs::WebGLImmediateQueries()) {
if (pname == LOCAL_GL_QUERY_RESULT_AVAILABLE) {
retval.set(JS::BooleanValue(false));
}
return;
}

Просмотреть файл

@ -125,7 +125,7 @@ WebGL2Context::GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::M
MakeContextCurrent();
gl->fGetSynciv(sync->mGLName, pname, 1, nullptr, &result);
retval.set(JS::Int32Value(result));
break;
return;
}
ErrorInvalidEnum("getSyncParameter: Invalid pname 0x%04x", pname);

Просмотреть файл

@ -933,7 +933,7 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
if (aPresContext->PresShell()) {
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution());
pt = pt.RemoveResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(aPresContext->PresShell()));
}
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),

Просмотреть файл

@ -5593,9 +5593,10 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
}
if (files.IsEmpty()) {
// If no file was selected, pretend we had an empty file with an
// empty filename.
aFormSubmission->AddNameFilePair(name, nullptr);
RefPtr<BlobImpl> blobImpl =
new BlobImplEmptyFile(NS_LITERAL_STRING("application/octet-stream"));
RefPtr<File> file = File::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
aFormSubmission->AddNameFilePair(name, file);
}
return NS_OK;

Просмотреть файл

@ -167,15 +167,15 @@ nsresult
nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
File* aFile)
{
MOZ_ASSERT(aFile);
if (!mWarnedFileControl) {
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
mWarnedFileControl = true;
}
nsAutoString filename;
if (aFile) {
aFile->GetName(filename);
}
aFile->GetName(filename);
return AddNameValuePair(aName, filename);
}
@ -441,61 +441,60 @@ nsresult
nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
File* aFile)
{
MOZ_ASSERT(aFile);
// Encode the control name
nsAutoCString nameStr;
nsresult rv = EncodeVal(aName, nameStr, true);
NS_ENSURE_SUCCESS(rv, rv);
nsCString filename, contentType;
nsAutoString filename16;
aFile->GetName(filename16);
ErrorResult error;
nsAutoString filepath16;
aFile->GetPath(filepath16, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
if (!filepath16.IsEmpty()) {
// File.path includes trailing "/"
filename16 = filepath16 + filename16;
}
nsAutoCString filename;
rv = EncodeVal(filename16, filename, true);
NS_ENSURE_SUCCESS(rv, rv);
// Get content type
nsAutoString contentType16;
aFile->GetType(contentType16);
if (contentType16.IsEmpty()) {
contentType16.AssignLiteral("application/octet-stream");
}
nsAutoCString contentType;
contentType.Adopt(nsLinebreakConverter::
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakSpace));
// Get input stream
nsCOMPtr<nsIInputStream> fileStream;
if (aFile) {
nsAutoString filename16;
aFile->GetName(filename16);
aFile->GetInternalStream(getter_AddRefs(fileStream), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
ErrorResult error;
nsAutoString filepath16;
aFile->GetPath(filepath16, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
if (!filepath16.IsEmpty()) {
// File.path includes trailing "/"
filename16 = filepath16 + filename16;
}
rv = EncodeVal(filename16, filename, true);
if (fileStream) {
// Create buffered stream (for efficiency)
nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
fileStream, 8192);
NS_ENSURE_SUCCESS(rv, rv);
// Get content type
nsAutoString contentType16;
aFile->GetType(contentType16);
if (contentType16.IsEmpty()) {
contentType16.AssignLiteral("application/octet-stream");
}
contentType.Adopt(nsLinebreakConverter::
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakSpace));
// Get input stream
aFile->GetInternalStream(getter_AddRefs(fileStream), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
if (fileStream) {
// Create buffered stream (for efficiency)
nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
fileStream, 8192);
NS_ENSURE_SUCCESS(rv, rv);
fileStream = bufferedStream;
}
}
else {
contentType.AssignLiteral("application/octet-stream");
fileStream = bufferedStream;
}
//
@ -619,9 +618,7 @@ nsFSTextPlain::AddNameFilePair(const nsAString& aName,
File* aFile)
{
nsAutoString filename;
if (aFile) {
aFile->GetName(filename);
}
aFile->GetName(filename);
AddNameValuePair(aName, filename);
return NS_OK;

Просмотреть файл

@ -258,7 +258,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=523771
<p>
File input:
<input type=file name="file_1" class="setfile">
<input type=file name="file_2" class="setfile empty">
<input type=file name="file_2">
<input type=file name="" class="setfile">
<input type=file name="">
<input type=file class="setfile">
@ -268,7 +268,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=523771
Multifile input:
<input multiple type=file name="file_3" class="setfile">
<input multiple type=file name="file_4" class="setfile multi">
<input multiple type=file name="file_5" class="setfile empty">
<input multiple type=file name="file_5">
<input multiple type=file name="" class="setfile">
<input multiple type=file name="" class="setfile multi">
<input multiple type=file name="">
@ -426,7 +426,6 @@ function onFilesOpened(files) {
let singleFile = textFile;
let multiFile = [textFile, imageFile];
emptyFile = new File([], "", { type: "application/octet-stream" });
var addList = document.getElementsByClassName("setfile");
let i = 0;
@ -434,8 +433,6 @@ function onFilesOpened(files) {
while (input = addList[i++]) {
if (input.classList.contains("multi")) {
SpecialPowers.wrap(input).mozSetFileArray(multiFile);
} else if (input.classList.contains("empty")) {
SpecialPowers.wrap(input).mozSetFileArray([emptyFile]);
} else {
SpecialPowers.wrap(input).mozSetFileArray([singleFile]);
}
@ -449,6 +446,7 @@ function onFilesOpened(files) {
myFile2 = input.files[1];
is(myFile1.size, 20, "File1 size");
is(myFile2.size, 2711, "File2 size");
emptyFile = { name: "", type: "application/octet-stream" };
// Now, actually run the tests; see below.
onFilesSet();

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -618,7 +618,26 @@ ContentChild::Init(MessageLoop* aIOLoop,
IPC::Channel* aChannel)
{
#ifdef MOZ_WIDGET_GTK
gtk_init(nullptr, nullptr);
// We need to pass a display down to gtk_init because it's not going to
// use the one from the environment on its own when deciding which backend
// to use, and when starting under XWayland, it may choose to start with
// the wayland backend instead of the x11 backend.
// The DISPLAY environment variable is normally set by the parent process.
char* display_name = PR_GetEnv("DISPLAY");
if (display_name) {
int argc = 3;
char option_name[] = "--display";
char* argv[] = {
nullptr,
option_name,
display_name,
nullptr
};
char** argvp = argv;
gtk_init(&argc, &argvp);
} else {
gtk_init(nullptr, nullptr);
}
#endif
#ifdef MOZ_WIDGET_QT
@ -1572,7 +1591,7 @@ ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
mozilla::PRemoteSpellcheckEngineChild *
ContentChild::AllocPRemoteSpellcheckEngineChild()
{
NS_NOTREACHED("Default Constructor for PRemoteSpellcheckEngineChild should never be called");
MOZ_CRASH("Default Constructor for PRemoteSpellcheckEngineChild should never be called");
return nullptr;
}
@ -1599,7 +1618,7 @@ ContentChild::SendPBlobConstructor(PBlobChild* aActor,
PPresentationChild*
ContentChild::AllocPPresentationChild()
{
NS_NOTREACHED("We should never be manually allocating PPresentationChild actors");
MOZ_CRASH("We should never be manually allocating PPresentationChild actors");
return nullptr;
}
@ -1704,7 +1723,7 @@ ContentChild::SendPIccConstructor(PIccChild* aActor,
PIccChild*
ContentChild::AllocPIccChild(const uint32_t& aServiceId)
{
NS_NOTREACHED("No one should be allocating PIccChild actors");
MOZ_CRASH("No one should be allocating PIccChild actors");
return nullptr;
}
@ -1760,7 +1779,7 @@ ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDev
PFileSystemRequestChild*
ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
{
NS_NOTREACHED("Should never get here!");
MOZ_CRASH("Should never get here!");
return nullptr;
}
@ -1793,7 +1812,7 @@ PMobileConnectionChild*
ContentChild::AllocPMobileConnectionChild(const uint32_t& aClientId)
{
#ifdef MOZ_B2G_RIL
NS_NOTREACHED("No one should be allocating PMobileConnectionChild actors");
MOZ_CRASH("No one should be allocating PMobileConnectionChild actors");
return nullptr;
#else
MOZ_CRASH("No support for mobileconnection on this platform!");;
@ -1832,7 +1851,7 @@ ContentChild::AllocPPrintingChild()
// which implements PPrintingChild. Instead, the nsPrintingProxy service is
// requested and instantiated via XPCOM, and the constructor of
// nsPrintingProxy sets up the IPC connection.
NS_NOTREACHED("Should never get here!");
MOZ_CRASH("Should never get here!");
return nullptr;
}
@ -1851,7 +1870,7 @@ ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
// nsScreenManagerProxy. Instead, the nsScreenManagerProxy
// service is requested and instantiated via XPCOM, and the
// constructor of nsScreenManagerProxy sets up the IPC connection.
NS_NOTREACHED("Should never get here!");
MOZ_CRASH("Should never get here!");
return nullptr;
}
@ -2007,7 +2026,7 @@ ContentChild::DeallocPMediaChild(media::PMediaChild *aActor)
PStorageChild*
ContentChild::AllocPStorageChild()
{
NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
MOZ_CRASH("We should never be manually allocating PStorageChild actors");
return nullptr;
}
@ -3023,7 +3042,7 @@ ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
}
return true;
#else
NS_NOTREACHED("ContentChild::RecvUpdateWindow calls unexpected on this platform.");
MOZ_ASSERT(false, "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
return false;
#endif
}

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

16
dom/ipc/ContentParent.cpp Executable file → Normal file
Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -5433,10 +5433,14 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
// The content process should never be in charge of computing whether or
// not a window should be private or remote - the parent will do that.
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW));
const uint32_t badFlags =
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
| nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW
| nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME
| nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
if (!!(aChromeFlags & badFlags)) {
return false;
}
TabParent* thisTabParent = nullptr;
if (aThisTab) {

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

Просмотреть файл

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=8 et tw=80 :
* This Source Code Form is subject to the terms of the Mozilla Public
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "CrashReporterParent.h"

Просмотреть файл

@ -867,7 +867,7 @@ TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
NS_IMETHODIMP
TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
{
NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild");
NS_WARNING("TabChild::GetWebBrowser not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -875,7 +875,7 @@ TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
NS_IMETHODIMP
TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
{
NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
NS_WARNING("TabChild::SetWebBrowser not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -890,7 +890,7 @@ TabChild::GetChromeFlags(uint32_t* aChromeFlags)
NS_IMETHODIMP
TabChild::SetChromeFlags(uint32_t aChromeFlags)
{
NS_NOTREACHED("trying to SetChromeFlags from content process?");
NS_WARNING("trying to SetChromeFlags from content process?");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -898,7 +898,7 @@ TabChild::SetChromeFlags(uint32_t aChromeFlags)
NS_IMETHODIMP
TabChild::DestroyBrowserWindow()
{
NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
NS_WARNING("TabChild::DestroyBrowserWindow not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -906,7 +906,7 @@ TabChild::DestroyBrowserWindow()
NS_IMETHODIMP
TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
{
NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild");
NS_WARNING("TabChild::SizeBrowserTo not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -914,7 +914,7 @@ TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
NS_IMETHODIMP
TabChild::ShowAsModal()
{
NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild");
NS_WARNING("TabChild::ShowAsModal not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -929,7 +929,7 @@ TabChild::IsWindowModal(bool* aRetVal)
NS_IMETHODIMP
TabChild::ExitModalEventLoop(nsresult aStatus)
{
NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild");
NS_WARNING("TabChild::ExitModalEventLoop not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1001,7 +1001,7 @@ TabChild::SetVisibility(bool aVisibility)
NS_IMETHODIMP
TabChild::GetTitle(char16_t** aTitle)
{
NS_NOTREACHED("TabChild::GetTitle not supported in TabChild");
NS_WARNING("TabChild::GetTitle not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1017,7 +1017,7 @@ TabChild::SetTitle(const char16_t* aTitle)
NS_IMETHODIMP
TabChild::GetSiteWindow(void** aSiteWindow)
{
NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild");
NS_WARNING("TabChild::GetSiteWindow not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

Просмотреть файл

@ -205,7 +205,7 @@ MP3TrackDemuxer::FastSeek(const TimeUnit& aTime) {
if (!aTime.ToMicroseconds()) {
// Quick seek to the beginning of the stream.
mFrameIndex = 0;
} else if (vbr.IsTOCPresent()) {
} else if (vbr.IsTOCPresent() && Duration().ToMicroseconds() > 0) {
// Use TOC for more precise seeking.
const float durationFrac = static_cast<float>(aTime.ToMicroseconds()) /
Duration().ToMicroseconds();
@ -358,7 +358,9 @@ MP3TrackDemuxer::Duration() const {
// Unknown length, we can't estimate duration.
return TimeUnit::FromMicroseconds(-1);
}
numFrames = (streamLen - mFirstFrameOffset) / AverageFrameLength();
if (AverageFrameLength() > 0) {
numFrames = (streamLen - mFirstFrameOffset) / AverageFrameLength();
}
}
return Duration(numFrames);
}
@ -534,7 +536,7 @@ MP3TrackDemuxer::OffsetFromFrameIndex(int64_t aFrameIndex) const {
int64_t offset = 0;
const auto& vbr = mParser.VBRInfo();
if (vbr.NumBytes() && vbr.NumAudioFrames()) {
if (vbr.IsValid()) {
offset = mFirstFrameOffset + aFrameIndex * vbr.NumBytes().value() /
vbr.NumAudioFrames().value();
} else if (AverageFrameLength() > 0) {
@ -550,7 +552,7 @@ MP3TrackDemuxer::FrameIndexFromOffset(int64_t aOffset) const {
int64_t frameIndex = 0;
const auto& vbr = mParser.VBRInfo();
if (vbr.NumBytes() && vbr.NumAudioFrames()) {
if (vbr.IsValid()) {
frameIndex = static_cast<float>(aOffset - mFirstFrameOffset) /
vbr.NumBytes().value() * vbr.NumAudioFrames().value();
frameIndex = std::min<int64_t>(vbr.NumAudioFrames().value(), frameIndex);
@ -626,7 +628,7 @@ MP3TrackDemuxer::AverageFrameLength() const {
return static_cast<double>(mTotalFrameLen) / mNumParsedFrames;
}
const auto& vbr = mParser.VBRInfo();
if (vbr.NumBytes() && vbr.NumAudioFrames()) {
if (vbr.IsValid() && vbr.NumAudioFrames().value() + 1) {
return static_cast<double>(vbr.NumBytes().value()) /
(vbr.NumAudioFrames().value() + 1);
}
@ -962,6 +964,16 @@ FrameParser::VBRHeader::IsTOCPresent() const {
return mTOC.size() == vbr_header::TOC_SIZE;
}
bool
FrameParser::VBRHeader::IsValid() const {
return mType != NONE &&
mNumAudioFrames.valueOr(0) > 0 &&
mNumBytes.valueOr(0) > 0 &&
// We don't care about the scale for any computations here.
// mScale < 101 &&
true;
}
int64_t
FrameParser::VBRHeader::Offset(float aDurationFac) const {
if (!IsTOCPresent()) {

Просмотреть файл

@ -232,6 +232,9 @@ public:
// Returns true iff Xing/Info TOC (table of contents) is present.
bool IsTOCPresent() const;
// Returns whether the header is valid (containing reasonable field values).
bool IsValid() const;
// Returns the byte offset for the given duration percentage as a factor
// (0: begin, 1.0: end).
int64_t Offset(float aDurationFac) const;

Просмотреть файл

@ -48,13 +48,12 @@ function ontimeupdate(e) {
delta_wallclock = (t.timestamp - t.startTimestamp - t.bufferingTime) / 1000;
t.mozPreservesPitch = false;
is(t.mozPreservesPitch, false, "If we disable the pitch preservation, it should appear as such.");
is(t.mozPreservesPitch, false, t.name + ": If we disable the pitch preservation, it should appear as such.");
t.bufferingTime = 0;
is(t.playbackRate, SLOW_RATE,
"The playback rate shoud be "+SLOW_RATE+"." + t.token);
ok(checkPlaybackRate(delta_wallclock, delta, SLOW_RATE, 0.25), "We are effectively slowing down playback. (" + delta_wallclock + ", " + delta + ") for " + t.token);
is(t.playbackRate, SLOW_RATE, t.name + ": The playback rate shoud be "+SLOW_RATE+".");
ok(checkPlaybackRate(delta_wallclock, delta, SLOW_RATE, 0.25), t.name + ": We are effectively slowing down playback. (" + delta_wallclock + ", " + delta + ")");
t.removeEventListener("timeupdate", ontimeupdate);
t.addEventListener("pause", onpaused);
t.playbackRate = NULL_RATE;
@ -80,14 +79,14 @@ function afterNullPlaybackRate(e) {
t.testedForNull = true;
ok(t.currentTime == t.oldCurrentTime, "Current time should not change when playbackRate is null (" + t.currentTime + " " + t.oldCurrentTime + ").");
ok(!t.paused, "The element should not be in paused state.");
ok(t.currentTime == t.oldCurrentTime, t.name + ": Current time should not change when playbackRate is null (" + t.currentTime + " " + t.oldCurrentTime + ").");
ok(!t.paused, t.name + ": The element should not be in paused state.");
t.removeEventListener("paused", onpaused);
is(t.pausedReceived, undefined, "Paused event should not have been received.");
is(t.pausedReceived, undefined, t.name + ": Paused event should not have been received.");
t.timestamp = Date.now();
t.oldCurrentTime = t.currentTime;
t.playbackRate = VERY_FAST_RATE;
is(t.playbackRate, FAST_RATE, "Playback rate should be clamped to " + FAST_RATE + ".");
is(t.playbackRate, FAST_RATE, t.name + ": Playback rate should be clamped to " + FAST_RATE + ".");
}
function onended(e) {
@ -97,9 +96,9 @@ function onended(e) {
t.bufferingTime = 0;
// If we got "ended" too early, skip these tests.
if (t.testedForSlowdown && t.testedForNull) {
is(t.playbackRate, FAST_RATE, "The playback rate should still be "+FAST_RATE+".");
ok(!t.muted, "The audio should be muted when playing at high speed, but should not appear as such.");
is(t.currentTime, t.duration, "Current time should be equal to the duration (not change by playback rate).");
is(t.playbackRate, FAST_RATE, t.name + ": The playback rate should still be "+FAST_RATE+".");
ok(!t.muted, t.name + ": The audio should be muted when playing at high speed, but should not appear as such.");
is(t.currentTime, t.duration, t.name + ": Current time should be equal to the duration (not change by playback rate).");
}
finish_test(t);
}
@ -134,13 +133,14 @@ function onwaiting(e) {
}
function onvolumechange(e) {
ok(false, "We should not receive a volumechange event when changing the playback rate.");
ok(false, e.target.name + ": We should not receive a volumechange event when changing the playback rate.");
}
function startTest(test, token) {
let elemType = /^audio/.test(test.type) ? "audio" : "video";
let element = document.createElement(elemType);
element.src = test.name;
element.name = test.name;
element.preload = "metadata";
element.token = token;
element.controls = true;
@ -154,12 +154,12 @@ function startTest(test, token) {
element.addEventListener("volumechange", onvolumechange);
manager.started(token);
element.startTimestamp = Date.now();
is(element.mozPreservesPitch, true, "Pitch preservation should be enabled by default.");
is(element.mozPreservesPitch, true, test.name + ": Pitch preservation should be enabled by default.");
element.addEventListener("loadedmetadata", function() {
is(element.playbackRate, 1.0, "playbackRate should be initially 1.0");
is(element.defaultPlaybackRate, 1.0, "defaultPlaybackRate should be initially 1.0");
is(element.playbackRate, 1.0, test.name + ": playbackRate should be initially 1.0");
is(element.defaultPlaybackRate, 1.0, test.name + ": defaultPlaybackRate should be initially 1.0");
element.playbackRate = VERY_SLOW_RATE;
is(element.playbackRate, SLOW_RATE, "PlaybackRate should be clamped to " + SLOW_RATE + ".");
is(element.playbackRate, SLOW_RATE, test.name + ": PlaybackRate should be clamped to " + SLOW_RATE + ".");
element.play();
element.playbackRate = SLOW_RATE;
});

Просмотреть файл

@ -286,7 +286,7 @@ TraceJSObjWrappers(JSTracer *trc, void *data)
// any of them moved.
for (JSObjWrapperTable::Enum e(sJSObjWrappers); !e.empty(); e.popFront()) {
nsJSObjWrapperKey key = e.front().key();
JS_CallUnbarrieredObjectTracer(trc, &key.mJSObj, "sJSObjWrappers key object");
JS::UnsafeTraceRoot(trc, &key.mJSObj, "sJSObjWrappers key object");
nsJSObjWrapper *wrapper = e.front().value();
JS::TraceNullableEdge(trc, &wrapper->mJSObj, "sJSObjWrappers wrapper object");
if (key != e.front().key()) {
@ -1101,7 +1101,7 @@ JSObjWrapperKeyMarkCallback(JSTracer *trc, JSObject *obj, void *data) {
if (!p)
return;
JS_CallUnbarrieredObjectTracer(trc, &obj, "sJSObjWrappers key object");
js::UnsafeTraceManuallyBarrieredEdge(trc, &obj, "sJSObjWrappers key object");
nsJSObjWrapperKey newKey(obj, npp);
sJSObjWrappers.rekeyIfMoved(oldKey, newKey);
}

Просмотреть файл

@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=642338
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=642338">Mozilla Bug 642338</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
@ -42,7 +42,7 @@ function testWindow(w)
function checkFeature(feature, prefname) {
if (prefname === undefined)
prefname = feature;
if (SpecialPowers.getBoolPref('dom.disable_window_open_feature.' + prefname)) {
is(w[feature].visible, true, feature + ' should always be true.');
}
@ -81,7 +81,7 @@ var allBarsWindow =
'personalbar=yes,status=yes,scrollbars=yes',
true);
var noBarsWindow =
var noBarsWindow =
window.open('file_window_bar.html?false', 'no-bars',
'menubar=no,toolbar=no,location=no,' +
'personalbar=no,status=no,scrollbars=no',

Просмотреть файл

@ -25,7 +25,7 @@ support-files =
[test_MessageEvent.html]
[test_postMessage_basehref.html]
[test_postMessage_closed.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 894914 - wrong data - got FAIL, expected message # b2g(bug 894914 - wrong data - got FAIL, expected message) b2g-debug(bug 894914 - wrong data - got FAIL, expected message) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected message # b2g(bug 894914 - wrong data - got FAIL, expected message) b2g-debug(bug 894914 - wrong data - got FAIL, expected message) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_postMessage_hash.html]
[test_postMessage.html]
[test_postMessage_idn.xhtml]

Просмотреть файл

@ -46,7 +46,12 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
mWindowId = innerWindow->WindowID();
}
aDoc->GetURL(mUrl);
nsCOMPtr<nsIURI> originalURI = aDoc->GetOriginalURI();
if (originalURI) {
nsAutoCString spec;
originalURI->GetSpec(spec);
CopyUTF8toUTF16(spec, mUrl);
}
mVisibilityState = aDoc->VisibilityState();
ErrorResult result;

Просмотреть файл

@ -2920,8 +2920,10 @@ ServiceWorkerManager::LoadRegistration(
registration = CreateNewRegistration(aRegistration.scope(), principal);
} else {
RefPtr<ServiceWorkerInfo> newest = registration->Newest();
// If the script spec matches and our active worker state matches our
// expectations for a "current worker", then we are done.
if (newest && newest->ScriptSpec() == aRegistration.scriptSpec() &&
!!registration->mActiveWorker == aRegistration.currentWorkerURL().IsEmpty()) {
!registration->mActiveWorker == aRegistration.currentWorkerURL().IsEmpty()) {
// No needs for updates.
return;
}
@ -3599,7 +3601,8 @@ ServiceWorkerManager::DispatchFetchEvent(const PrincipalOriginAttributes& aOrigi
internalChannel->GetLoadGroup(getter_AddRefs(loadGroup));
documentId = aDocumentIdForTopLevelNavigation;
// TODO: Use aDocumentIdForTopLevelNavigation for potentialClientId, pending
// the spec change.
nsCOMPtr<nsIURI> uri;
aRv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri));

Просмотреть файл

@ -1243,7 +1243,9 @@ private:
init.mRequest.Value() = request;
init.mBubbles = false;
init.mCancelable = true;
init.mClientId = mClientId;
if (!mClientId.IsEmpty()) {
init.mClientId = mClientId;
}
init.mIsReload = mIsReload;
RefPtr<FetchEvent> event =
FetchEvent::Constructor(globalObj, NS_LITERAL_STRING("fetch"), init, result);

Просмотреть файл

@ -1139,8 +1139,7 @@ DefaultTooltipTextProvider::GetNodeText(nsIDOMNode* aNode, char16_t** aText,
nsCOMPtr<nsIURI> uri(linkContent->GetURIExternal());
if (uri) {
currElement->GetAttributeNS(
NS_LITERAL_STRING("http://www.w3.org/1999/xlink"),
NS_LITERAL_STRING("title"), outText);
xlinkNS, NS_LITERAL_STRING("title"), outText);
if (outText.Length()) {
found = true;
}
@ -1150,7 +1149,7 @@ DefaultTooltipTextProvider::GetNodeText(nsIDOMNode* aNode, char16_t** aText,
lookingForSVGTitle = UseSVGTitle(currElement);
}
if (lookingForSVGTitle) {
nsINodeList* childNodes = node->ChildNodes();
nsINodeList* childNodes = content->ChildNodes();
uint32_t childNodeCount = childNodes->Length();
for (uint32_t i = 0; i < childNodeCount; i++) {
nsIContent* child = childNodes->Item(i);

Просмотреть файл

@ -31,8 +31,8 @@ interface nsIWebBrowserChrome : nsISupports
/**
* The currently loaded WebBrowser. The browser chrome may be
* told to set the WebBrowser object to a new object by setting this
* attribute. In this case the implementer is responsible for taking the
* new WebBrowser object and doing any necessary initialization or setup
* attribute. In this case the implementer is responsible for taking the
* new WebBrowser object and doing any necessary initialization or setup
* as if it had created the WebBrowser itself. This includes positioning
* setting up listeners etc.
*/
@ -53,7 +53,7 @@ interface nsIWebBrowserChrome : nsISupports
const unsigned long CHROME_SCROLLBARS = 0x00000200;
const unsigned long CHROME_TITLEBAR = 0x00000400;
const unsigned long CHROME_EXTRA = 0x00000800;
// createBrowserWindow specific flags
const unsigned long CHROME_WITH_SIZE = 0x00001000;
const unsigned long CHROME_WITH_POSITION = 0x00002000;
@ -98,12 +98,12 @@ interface nsIWebBrowserChrome : nsISupports
// Note: The modal style bit just affects the way the window looks and does
// mean it's actually modal.
const unsigned long CHROME_MODAL = 0x20000000;
const unsigned long CHROME_MODAL = 0x20000000;
const unsigned long CHROME_OPENAS_DIALOG = 0x40000000;
const unsigned long CHROME_OPENAS_CHROME = 0x80000000;
const unsigned long CHROME_ALL = 0x00000ffe;
/**
* The chrome flags for this browser chrome. The implementation should
* reflect the value of this attribute by hiding or showing its chrome
@ -118,20 +118,20 @@ interface nsIWebBrowserChrome : nsISupports
void destroyBrowserWindow();
/**
* Tells the chrome to size itself such that the browser will be the
* Tells the chrome to size itself such that the browser will be the
* specified size.
* @param aCX new width of the browser
* @param aCY new height of the browser
*/
void sizeBrowserTo(in long aCX, in long aCY);
/**
* Shows the window as a modal window.
* @return (the function error code) the status value specified by
* in exitModalEventLoop.
*/
void showAsModal();
/**
* Is the window modal (that is, currently executing a modal loop)?
* @return true if it's a modal window
@ -145,4 +145,3 @@ interface nsIWebBrowserChrome : nsISupports
*/
void exitModalEventLoop(in nsresult aStatus);
};

Просмотреть файл

@ -808,7 +808,7 @@ CreateCGPattern(const Pattern &aPattern, CGAffineTransform aUserSpace)
yStep = static_cast<CGFloat>(1 << 22);
break;
case ExtendMode::REFLECT:
assert(0);
MOZ_FALLTHROUGH_ASSERT("ExtendMode::REFLECT");
case ExtendMode::REPEAT:
xStep = static_cast<CGFloat>(CGImageGetWidth(image));
yStep = static_cast<CGFloat>(CGImageGetHeight(image));

Просмотреть файл

@ -644,8 +644,7 @@ DrawTargetCairo::GetType() const
case CAIRO_SURFACE_TYPE_SKIA:
case CAIRO_SURFACE_TYPE_QT:
MOZ_ASSERT(false, "Can't determine actual DrawTargetType for DrawTargetCairo - assuming SOFTWARE_RASTER");
// fallthrough
MOZ_FALLTHROUGH_ASSERT("Can't determine actual DrawTargetType for DrawTargetCairo - assuming SOFTWARE_RASTER");
case CAIRO_SURFACE_TYPE_IMAGE:
case CAIRO_SURFACE_TYPE_XLIB:
case CAIRO_SURFACE_TYPE_XCB:

Просмотреть файл

@ -91,6 +91,7 @@ bool
GLBlitHelper::InitTexQuadProgram(BlitType target)
{
const char kTexBlit_VertShaderSource[] = "\
#version 100 \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
@ -109,6 +110,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
";
const char kTex2DBlit_FragShaderSource[] = "\
#version 100 \n\
#ifdef GL_ES \n\
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
precision highp float; \n\
@ -127,6 +129,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
";
const char kTex2DRectBlit_FragShaderSource[] = "\
#version 100 \n\
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
precision highp float; \n\
#else \n\
@ -146,6 +149,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
";
#ifdef ANDROID /* MOZ_WIDGET_ANDROID || MOZ_WIDGET_GONK */
const char kTexExternalBlit_FragShaderSource[] = "\
#version 100 \n\
#extension GL_OES_EGL_image_external : require \n\
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
precision highp float; \n\
@ -174,6 +178,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
*/
const char kTexYUVPlanarBlit_FragShaderSource[] = "\
#version 100 \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
@ -200,6 +205,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
#ifdef XP_MACOSX
const char kTexNV12PlanarBlit_FragShaderSource[] = "\
#version 100 \n\
#extension GL_ARB_texture_rectangle : require \n\
#ifdef GL_ES \n\
precision mediump float \n\
@ -383,18 +389,16 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
// Cache and set attribute and uniform
mGL->fUseProgram(program);
switch (target) {
#ifdef ANDROID
case ConvertSurfaceTexture:
case ConvertGralloc:
#endif
case BlitTex2D:
case BlitTexRect:
case ConvertEGLImage:
case ConvertSurfaceTexture:
case ConvertGralloc: {
#ifdef ANDROID
case ConvertEGLImage: {
GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit");
MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found");
mGL->fUniform1i(texUnitLoc, 0);
#else
MOZ_ASSERT_UNREACHABLE("gralloc not support on non-android");
#endif
break;
}
case ConvertPlanarYCbCr: {
@ -434,6 +438,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
#endif
break;
}
default:
return false;
}
MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0);
mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip");

Просмотреть файл

@ -7,6 +7,7 @@
#define GFX_LAYERMETRICSWRAPPER_H
#include "Layers.h"
#include "UnitTransforms.h"
namespace mozilla {
namespace layers {
@ -299,6 +300,11 @@ public:
return gfx::Matrix4x4();
}
CSSTransformMatrix GetTransformTyped() const
{
return ViewAs<CSSTransformMatrix>(GetTransform());
}
bool TransformIsPerspective() const
{
MOZ_ASSERT(IsValid());

Просмотреть файл

@ -895,6 +895,12 @@ Layer::GetTransform() const
return transform;
}
const CSSTransformMatrix
Layer::GetTransformTyped() const
{
return ViewAs<CSSTransformMatrix>(GetTransform());
}
const Matrix4x4
Layer::GetLocalTransform()
{
@ -912,6 +918,12 @@ Layer::GetLocalTransform()
return transform;
}
const LayerToParentLayerMatrix4x4
Layer::GetLocalTransformTyped()
{
return ViewAs<LayerToParentLayerMatrix4x4>(GetLocalTransform());
}
bool
Layer::HasTransformAnimation() const
{

Просмотреть файл

@ -1276,6 +1276,9 @@ public:
virtual Layer* GetFirstChild() const { return nullptr; }
virtual Layer* GetLastChild() const { return nullptr; }
const gfx::Matrix4x4 GetTransform() const;
// Same as GetTransform(), but returns the transform as a strongly-typed
// matrix. Eventually this will replace GetTransform().
const CSSTransformMatrix GetTransformTyped() const;
const gfx::Matrix4x4& GetBaseTransform() const { return mTransform; }
// Note: these are virtual because ContainerLayerComposite overrides them.
virtual float GetPostXScale() const { return mPostXScale; }
@ -1346,10 +1349,17 @@ public:
/**
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform()
* for shadow layers, GetShadowTransform(), in either case with the
* pre- and post-scales applied.
*/
const gfx::Matrix4x4 GetLocalTransform();
/**
* Same as GetLocalTransform(), but returns a strongly-typed matrix.
* Eventually, this will replace GetLocalTransform().
*/
const LayerToParentLayerMatrix4x4 GetLocalTransformTyped();
/**
* Returns the local opacity for this layer: either mOpacity or,
* for shadow layers, GetShadowOpacity()

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/layers/GonkNativeHandle.h"
#endif
#include "Units.h"
#include "mozilla/gfx/Point.h" // for IntPoint
#include "mozilla/TypedEnumBits.h"
#include "nsRegion.h"
@ -284,6 +285,22 @@ enum TextureDumpMode {
DoNotCompress // dump texture uncompressed
};
// Some specialized typedefs of Matrix4x4Typed.
typedef gfx::Matrix4x4Typed<LayerPixel, CSSTransformedLayerPixel> CSSTransformMatrix;
// Several different async transforms can contribute to a layer's transform
// (specifically, an async animation can contribute a transform, and each APZC
// that scrolls a layer can contribute async scroll/zoom and overscroll
// transforms).
// To try to model this with typed units, we represent individual async
// transforms as ParentLayer -> ParentLayer transforms (aliased as
// AsyncTransformComponentMatrix), and we represent the product of all of them
// as a CSSTransformLayer -> ParentLayer transform (aliased as
// AsyncTransformMatrix). To create an AsyncTransformMatrix from component
// matrices, a ViewAs operation is needed. A MultipleAsyncTransforms
// PixelCastJustification is provided for this purpose.
typedef gfx::Matrix4x4Typed<ParentLayerPixel, ParentLayerPixel> AsyncTransformComponentMatrix;
typedef gfx::Matrix4x4Typed<CSSTransformedLayerPixel, ParentLayerPixel> AsyncTransformMatrix;
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -358,7 +358,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
if (!needsApzc) {
node = RecycleOrCreateNode(aState, nullptr, aLayersId);
AttachNodeToTree(node, aParent, aNextSibling);
node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(),
node->SetHitTestData(
GetEventRegions(aLayer),
aLayer.GetTransformTyped(),
aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(),
GetEventRegionsOverride(aParent, aLayer));
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
@ -462,7 +464,10 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
MOZ_ASSERT(node->IsPrimaryHolder() && node->GetApzc() && node->GetApzc()->Matches(guid));
ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer);
node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion),
node->SetHitTestData(
GetEventRegions(aLayer),
aLayer.GetTransformTyped(),
Some(clipRegion),
GetEventRegionsOverride(aParent, aLayer));
apzc->SetAncestorTransform(aAncestorTransform);
@ -526,7 +531,10 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
MOZ_ASSERT(aAncestorTransform.FuzzyEqualsMultiplicative(apzc->GetAncestorTransform()));
ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer);
node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion),
node->SetHitTestData(
GetEventRegions(aLayer),
aLayer.GetTransformTyped(),
Some(clipRegion),
GetEventRegionsOverride(aParent, aLayer));
}
@ -1848,7 +1856,7 @@ APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) c
// ancestorUntransform is updated to RC.Inverse() * QC.Inverse() when parent == P
ancestorUntransform = parent->GetAncestorTransform().Inverse();
// asyncUntransform is updated to PA.Inverse() when parent == P
Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransformWithOverscroll().Inverse();
Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransformWithOverscroll().Inverse().ToUnknownMatrix();
// untransformSinceLastApzc is RC.Inverse() * QC.Inverse() * PA.Inverse()
Matrix4x4 untransformSinceLastApzc = ancestorUntransform * asyncUntransform;
@ -1880,7 +1888,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co
// leftmost matrix in a multiplication is applied first.
// asyncUntransform is LA.Inverse()
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransformWithOverscroll().Inverse();
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransformWithOverscroll().Inverse().ToUnknownMatrix();
// aTransformToGeckoOut is initialized to LA.Inverse() * LD * MC * NC * OC * PC
result = asyncUntransform * aApzc->GetTransformToLastDispatchedPaint() * aApzc->GetAncestorTransform();

Просмотреть файл

@ -8,6 +8,8 @@
#define mozilla_layers_APZUtils_h
#include <stdint.h> // for uint32_t
#include "LayersTypes.h"
#include "UnitTransforms.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/FloatingPoint.h"
@ -61,6 +63,16 @@ static bool IsZero(const gfx::PointTyped<Units>& aPoint)
&& FuzzyEqualsAdditive(aPoint.y, 0.0f, COORDINATE_EPSILON);
}
// Deem an AsyncTransformComponentMatrix (obtained by multiplying together
// one or more AsyncTransformComponentMatrix objects) as constituting a
// complete async transform.
inline AsyncTransformMatrix
CompleteAsyncTransform(const AsyncTransformComponentMatrix& aMatrix)
{
return ViewAs<AsyncTransformMatrix>(aMatrix,
PixelCastJustification::MultipleAsyncTransforms);
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -2899,10 +2899,10 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
return false;
}
Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const {
AsyncTransformComponentMatrix AsyncPanZoomController::GetOverscrollTransform() const {
ReentrantMonitorAutoEnter lock(mMonitor);
if (!IsOverscrolled()) {
return Matrix4x4();
return AsyncTransformComponentMatrix();
}
// The overscroll effect is a uniform stretch along the overscrolled axis,
@ -2939,7 +2939,7 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const {
}
// Combine the transformations into a matrix.
return Matrix4x4::Scaling(scaleX, scaleY, 1)
return AsyncTransformComponentMatrix::Scaling(scaleX, scaleY, 1)
.PostTranslate(translation.x, translation.y, 0);
}
@ -2987,7 +2987,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
return requestAnimationFrame;
}
void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutTransform,
void AsyncPanZoomController::SampleContentTransformForFrame(AsyncTransform* aOutTransform,
ParentLayerPoint& aScrollOffset)
{
ReentrantMonitorAutoEnter lock(mMonitor);
@ -2996,7 +2996,7 @@ void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutT
*aOutTransform = GetCurrentAsyncTransform();
}
ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
AsyncTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint lastPaintScrollOffset;
@ -3028,13 +3028,14 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset)
* mFrameMetrics.GetZoom() * mTestAsyncZoom.scale;
return ViewTransform(
return AsyncTransform(
LayerToParentLayerScale(mFrameMetrics.GetAsyncZoom().scale * mTestAsyncZoom.scale),
-translation);
}
Matrix4x4 AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll() const {
return Matrix4x4(GetCurrentAsyncTransform()) * GetOverscrollTransform();
AsyncTransformComponentMatrix AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll() const {
return AsyncTransformComponentMatrix(GetCurrentAsyncTransform())
* GetOverscrollTransform();
}
Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {

Просмотреть файл

@ -44,7 +44,7 @@ struct ScrollableLayerGuid;
class CompositorParent;
class GestureEventListener;
class PCompositorParent;
struct ViewTransform;
struct AsyncTransform;
class AsyncPanZoomAnimation;
class FlingAnimation;
class InputBlockState;
@ -166,14 +166,14 @@ public:
* This function returns the async transform via the |aOutTransform|
* out parameter.
*/
void SampleContentTransformForFrame(ViewTransform* aOutTransform,
void SampleContentTransformForFrame(AsyncTransform* aOutTransform,
ParentLayerPoint& aScrollOffset);
/**
* Return a visual effect that reflects this apzc's
* overscrolled state, if any.
*/
Matrix4x4 GetOverscrollTransform() const;
AsyncTransformComponentMatrix GetOverscrollTransform() const;
/**
* A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics
@ -218,13 +218,13 @@ public:
* existing transform, it will make the layer appear with the desired pan/zoom
* amount.
*/
ViewTransform GetCurrentAsyncTransform() const;
AsyncTransform GetCurrentAsyncTransform() const;
/**
* Returns the same transform as GetCurrentAsyncTransform(), but includes
* any transform due to axis over-scroll.
*/
Matrix4x4 GetCurrentAsyncTransformWithOverscroll() const;
AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll() const;
/**
* Returns the transform to take something from the coordinate space of the

Просмотреть файл

@ -10,6 +10,7 @@
#include "LayersLogging.h" // for Stringify
#include "mozilla/gfx/Point.h" // for Point4D
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread
#include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4()
#include "nsPrintfCString.h" // for nsPrintfCString
#include "UnitTransforms.h" // for ViewAs
@ -206,7 +207,7 @@ HitTestingTreeNode::GetLayersId() const
void
HitTestingTreeNode::SetHitTestData(const EventRegions& aRegions,
const gfx::Matrix4x4& aTransform,
const CSSTransformMatrix& aTransform,
const Maybe<ParentLayerIntRegion>& aClipRegion,
const EventRegionsOverride& aOverride)
{
@ -227,12 +228,12 @@ Maybe<LayerPoint>
HitTestingTreeNode::Untransform(const ParentLayerPoint& aPoint) const
{
// convert into Layer coordinate space
gfx::Matrix4x4 localTransform = mTransform;
if (mApzc) {
localTransform = localTransform * mApzc->GetCurrentAsyncTransformWithOverscroll();
}
return UntransformBy(
ViewAs<LayerToParentLayerMatrix4x4>(localTransform).Inverse(), aPoint);
LayerToParentLayerMatrix4x4 transform = mTransform *
CompleteAsyncTransform(
mApzc
? mApzc->GetCurrentAsyncTransformWithOverscroll()
: AsyncTransformComponentMatrix());
return UntransformBy(transform.Inverse(), aPoint);
}
HitTestResult

Просмотреть файл

@ -85,7 +85,7 @@ public:
/* Hit test related methods */
void SetHitTestData(const EventRegions& aRegions,
const gfx::Matrix4x4& aTransform,
const CSSTransformMatrix& aTransform,
const Maybe<ParentLayerIntRegion>& aClipRegion,
const EventRegionsOverride& aOverride);
bool IsOutsideClip(const ParentLayerPoint& aPoint) const;
@ -135,7 +135,7 @@ private:
/* This is the transform from layer L. This does NOT include any async
* transforms. */
gfx::Matrix4x4 mTransform;
CSSTransformMatrix mTransform;
/* This is clip rect for L that we wish to use for hit-testing purposes. Note
* that this may not be exactly the same as the clip rect on layer L because

Просмотреть файл

@ -233,7 +233,7 @@ public:
}
}
bool SampleContentTransformForFrame(ViewTransform* aOutTransform,
bool SampleContentTransformForFrame(AsyncTransform* aOutTransform,
ParentLayerPoint& aScrollOffset,
const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(0)) {
mcc->AdvanceBy(aIncrement);
@ -340,7 +340,7 @@ protected:
{
const TimeDuration increment = TimeDuration::FromMilliseconds(1);
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
mcc->AdvanceBy(increment);
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
}
@ -355,7 +355,7 @@ protected:
const TimeDuration increment = TimeDuration::FromMilliseconds(1);
bool recoveredFromOverscroll = false;
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
while (apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut)) {
// The reported scroll offset should be the same throughout.
EXPECT_EQ(aExpectedScrollOffset, pointOut);
@ -1112,11 +1112,11 @@ TEST_F(APZCBasicTester, Overzoom) {
TEST_F(APZCBasicTester, SimpleTransform) {
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ParentLayerPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
EXPECT_EQ(AsyncTransform(), viewTransformOut);
}
@ -1174,7 +1174,7 @@ TEST_F(APZCBasicTester, ComplexTransform) {
layers[1]->SetFrameMetrics(childMetrics);
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
// Both the parent and child layer should behave exactly the same here, because
// the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
@ -1183,39 +1183,39 @@ TEST_F(APZCBasicTester, ComplexTransform) {
apzc->SetFrameMetrics(metrics);
apzc->NotifyLayersUpdated(metrics, true);
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
childApzc->SetFrameMetrics(childMetrics);
childApzc->NotifyLayersUpdated(childMetrics, true);
childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
// do an async scroll by 5 pixels and check the transform
metrics.ScrollBy(CSSPoint(5, 0));
apzc->SetFrameMetrics(metrics);
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
childMetrics.ScrollBy(CSSPoint(5, 0));
childApzc->SetFrameMetrics(childMetrics);
childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
// do an async zoom of 1.5x and check the transform
metrics.ZoomBy(1.5f);
apzc->SetFrameMetrics(metrics);
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
childMetrics.ZoomBy(1.5f);
childApzc->SetFrameMetrics(childMetrics);
childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
childApzc->Destroy();
@ -1253,7 +1253,7 @@ protected:
int touchStart = 50;
int touchEnd = 10;
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
nsTArray<uint32_t> allowedTouchBehaviors;
allowedTouchBehaviors.AppendElement(aBehavior);
@ -1264,10 +1264,10 @@ protected:
if (aShouldTriggerScroll) {
EXPECT_EQ(ParentLayerPoint(0, -(touchEnd-touchStart)), pointOut);
EXPECT_NE(ViewTransform(), viewTransformOut);
EXPECT_NE(AsyncTransform(), viewTransformOut);
} else {
EXPECT_EQ(ParentLayerPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
EXPECT_EQ(AsyncTransform(), viewTransformOut);
}
// Clear the fling from the previous pan, or stopping it will
@ -1279,7 +1279,7 @@ protected:
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ParentLayerPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
EXPECT_EQ(AsyncTransform(), viewTransformOut);
}
void DoPanWithPreventDefaultTest()
@ -1289,7 +1289,7 @@ protected:
int touchStart = 50;
int touchEnd = 10;
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
uint64_t blockId = 0;
// Pan down
@ -1303,7 +1303,7 @@ protected:
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ParentLayerPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
EXPECT_EQ(AsyncTransform(), viewTransformOut);
apzc->AssertStateIsReset();
}
@ -1357,7 +1357,7 @@ TEST_F(APZCBasicTester, Fling) {
int touchStart = 50;
int touchEnd = 10;
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
// Fling down. Each step scroll further down
Pan(apzc, mcc, touchStart, touchEnd);
@ -1525,7 +1525,7 @@ TEST_F(APZCBasicTester, OverScrollAbort) {
EXPECT_TRUE(apzc->IsOverscrolled());
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
// This sample call will run to the end of the fling animation
// and will schedule the overscroll animation.
@ -1582,7 +1582,7 @@ protected:
// Advance the fling animation by timeDelta milliseconds.
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut, TimeDuration::FromMilliseconds(timeDelta));
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
@ -1619,7 +1619,7 @@ protected:
// Sample the fling a couple of times to ensure it's going.
ParentLayerPoint point, finalPoint;
ViewTransform viewTransform;
AsyncTransform viewTransform;
apzc->SampleContentTransformForFrame(&viewTransform, point, TimeDuration::FromMilliseconds(10));
apzc->SampleContentTransformForFrame(&viewTransform, finalPoint, TimeDuration::FromMilliseconds(10));
EXPECT_GT(finalPoint.y, point.y);
@ -1818,11 +1818,11 @@ protected:
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
EXPECT_EQ(ParentLayerPoint(), pointOut);
EXPECT_EQ(ViewTransform(), viewTransformOut);
EXPECT_EQ(AsyncTransform(), viewTransformOut);
apzc->AssertStateIsReset();
}
@ -2049,7 +2049,7 @@ protected:
void SampleAnimationsOnce() {
const TimeDuration increment = TimeDuration::FromMilliseconds(1);
ParentLayerPoint pointOut;
ViewTransform viewTransformOut;
AsyncTransform viewTransformOut;
mcc->AdvanceBy(increment);
for (const RefPtr<Layer>& layer : layers) {
@ -2710,7 +2710,7 @@ TEST_F(APZHitTestingTester, TestRepaintFlushOnWheelEvents) {
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(swi, nullptr, nullptr));
EXPECT_EQ(origin, swi.mOrigin);
ViewTransform viewTransform;
AsyncTransform viewTransform;
ParentLayerPoint point;
apzcroot->SampleContentTransformForFrame(&viewTransform, point);
EXPECT_EQ(0, point.x);

Просмотреть файл

@ -146,7 +146,7 @@ FuzzyEquals(float a, float b) {
return (fabsf(a - b) < 1e-6);
}
static ViewTransform
static AsyncTransform
ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aCompositorMetrics)
{
// This is basically the same code as AsyncPanZoomController::GetCurrentAsyncTransform
@ -155,7 +155,7 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC
ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset())
* aCompositorMetrics.GetZoom();
return ViewTransform(aCompositorMetrics.GetAsyncZoom(), -translation);
return AsyncTransform(aCompositorMetrics.GetAsyncZoom(), -translation);
}
bool
@ -163,7 +163,7 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
const LayerMetricsWrapper& aLayer,
bool aHasPendingNewThebesContent,
bool aLowPrecision,
ViewTransform& aViewTransform)
AsyncTransform& aViewTransform)
{
MOZ_ASSERT(aLayer);
@ -1399,11 +1399,11 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
static Maybe<LayerRect>
GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor,
const LayerToParentLayerMatrix4x4& aTransformToCompBounds,
const ViewTransform& aAPZTransform,
const AsyncTransform& aAPZTransform,
const LayerRect& aClip)
{
LayerToParentLayerMatrix4x4 transform = aTransformToCompBounds *
ViewAs<ParentLayerToParentLayerMatrix4x4>(aAPZTransform);
AsyncTransformComponentMatrix(aAPZTransform);
return UntransformBy(transform.Inverse(),
aScrollAncestor.Metrics().GetCompositionBounds(), aClip);
@ -1443,7 +1443,7 @@ ClientMultiTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& a
// Find out the current view transform to determine which tiles to draw
// first, and see if we should just abort this paint. Aborting is usually
// caused by there being an incoming, more relevant paint.
ViewTransform viewTransform;
AsyncTransform viewTransform;
#if defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_ANDROID_APZ)
FrameMetrics contentMetrics = scrollAncestor.Metrics();
bool abortPaint = false;

Просмотреть файл

@ -376,7 +376,7 @@ public:
bool UpdateFromCompositorFrameMetrics(const LayerMetricsWrapper& aLayer,
bool aHasPendingNewThebesContent,
bool aLowPrecision,
ViewTransform& aViewTransform);
AsyncTransform& aViewTransform);
/**
* Determines if the compositor's upcoming composition bounds has fallen

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/gfx/Point.h" // for RoundedToInt, PointTyped
#include "mozilla/gfx/Rect.h" // for RoundedToInt, RectTyped
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
#include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/CompositorParent.h" // for CompositorParent, etc
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
@ -222,7 +223,7 @@ TransformClipRect(Layer* aLayer,
* only be applied once.
*/
static void
SetShadowTransform(Layer* aLayer, Matrix4x4 aTransform)
SetShadowTransform(Layer* aLayer, LayerToParentLayerMatrix4x4 aTransform)
{
if (ContainerLayer* c = aLayer->AsContainerLayer()) {
aTransform.PreScale(1.0f / c->GetPreXScale(),
@ -232,7 +233,7 @@ SetShadowTransform(Layer* aLayer, Matrix4x4 aTransform)
aTransform.PostScale(1.0f / aLayer->GetPostXScale(),
1.0f / aLayer->GetPostYScale(),
1);
aLayer->AsLayerComposite()->SetShadowTransform(aTransform);
aLayer->AsLayerComposite()->SetShadowTransform(aTransform.ToUnknownMatrix());
}
static void
@ -246,7 +247,7 @@ TranslateShadowLayer(Layer* aLayer,
// Note that the shadow transform is reset on every frame of composition so
// we don't have to worry about the adjustments compounding over successive
// frames.
Matrix4x4 layerTransform = aLayer->GetLocalTransform();
LayerToParentLayerMatrix4x4 layerTransform = aLayer->GetLocalTransformTyped();
// Apply the translation to the layer transform.
layerTransform.PostTranslate(aTranslation.x, aTranslation.y, 0);
@ -384,8 +385,8 @@ void
AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
Layer* aTransformedSubtreeRoot,
FrameMetrics::ViewID aTransformScrollId,
const Matrix4x4& aPreviousTransformForRoot,
const Matrix4x4& aCurrentTransformForRoot,
const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot,
const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot,
const ScreenMargin& aFixedLayerMargins,
bool aTransformAffectsLayerClip)
{
@ -429,8 +430,8 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
// Calculate the cumulative transforms between the subtree root with the
// old transform and the current transform.
Matrix4x4 oldCumulativeTransform = ancestorTransform * aPreviousTransformForRoot;
Matrix4x4 newCumulativeTransform = ancestorTransform * aCurrentTransformForRoot;
Matrix4x4 oldCumulativeTransform = ancestorTransform * aPreviousTransformForRoot.ToUnknownMatrix();
Matrix4x4 newCumulativeTransform = ancestorTransform * aCurrentTransformForRoot.ToUnknownMatrix();
if (newCumulativeTransform.IsSingular()) {
return;
}
@ -697,10 +698,10 @@ AsyncCompositionManager::RecordShadowTransforms(Layer* aLayer)
}
}
Matrix4x4
AdjustForClip(const Matrix4x4& asyncTransform, Layer* aLayer)
static AsyncTransformComponentMatrix
AdjustForClip(const AsyncTransformComponentMatrix& asyncTransform, Layer* aLayer)
{
Matrix4x4 result = asyncTransform;
AsyncTransformComponentMatrix result = asyncTransform;
// Container layers start at the origin, but they are clipped to where they
// actually have content on the screen. The tree transform is meant to apply
@ -801,9 +802,10 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
clipDeferredFromChildren);
}
Matrix4x4 oldTransform = aLayer->GetTransform();
LayerToParentLayerMatrix4x4 oldTransform = aLayer->GetTransformTyped() *
AsyncTransformMatrix();
Matrix4x4 combinedAsyncTransform;
AsyncTransformComponentMatrix combinedAsyncTransform;
bool hasAsyncTransform = false;
ScreenMargin fixedLayerMargins;
@ -835,13 +837,14 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
hasAsyncTransform = true;
ViewTransform asyncTransformWithoutOverscroll;
AsyncTransform asyncTransformWithoutOverscroll;
ParentLayerPoint scrollOffset;
controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
scrollOffset);
Matrix4x4 overscrollTransform = controller->GetOverscrollTransform();
Matrix4x4 asyncTransform =
Matrix4x4(asyncTransformWithoutOverscroll) * overscrollTransform;
AsyncTransformComponentMatrix overscrollTransform = controller->GetOverscrollTransform();
AsyncTransformComponentMatrix asyncTransform =
AsyncTransformComponentMatrix(asyncTransformWithoutOverscroll)
* overscrollTransform;
if (!aLayer->IsScrollInfoLayer()) {
controller->MarkAsyncTransformAppliedToContent();
@ -897,8 +900,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// frame and should not be transformed.
if (asyncClip && !metrics.UsesContainerScrolling()) {
MOZ_ASSERT(asyncTransform.Is2D());
asyncClip = Some(TransformBy(
ViewAs<ParentLayerToParentLayerMatrix4x4>(asyncTransform), *asyncClip));
asyncClip = Some(TransformBy(asyncTransform, *asyncClip));
}
aLayer->AsLayerComposite()->SetShadowClipRect(asyncClip);
@ -911,8 +913,10 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// effects apply to fixed and sticky layers. We do this by using
// GetTransform() as the base transform rather than GetLocalTransform(),
// which would include those factors.
Matrix4x4 transformWithoutOverscrollOrOmta = aLayer->GetTransform() *
AdjustForClip(asyncTransformWithoutOverscroll, aLayer);
LayerToParentLayerMatrix4x4 transformWithoutOverscrollOrOmta =
aLayer->GetTransformTyped()
* CompleteAsyncTransform(
AdjustForClip(asyncTransformWithoutOverscroll, aLayer));
// Since fixed/sticky layers are relative to their nearest scrolling ancestor,
// we use the ViewID from the bottommost scrollable metrics here.
@ -946,7 +950,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// frame, so these are the ones we need to shift by our async transform.
for (Layer* ancestorMaskLayer : ancestorMaskLayers) {
SetShadowTransform(ancestorMaskLayer,
ancestorMaskLayer->GetLocalTransform() * asyncTransform);
ancestorMaskLayer->GetLocalTransformTyped() * asyncTransform);
}
// Append the ancestor mask layer for this scroll frame to ancestorMaskLayers.
@ -968,12 +972,13 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
// shadow transform; in that case we want to apply ours on top of that one
// rather than clobber it.
SetShadowTransform(aLayer,
aLayer->GetLocalTransform() * AdjustForClip(combinedAsyncTransform, aLayer));
aLayer->GetLocalTransformTyped()
* AdjustForClip(combinedAsyncTransform, aLayer));
// Do the same for the layer's own mask layer, if it has one.
if (Layer* maskLayer = aLayer->GetMaskLayer()) {
SetShadowTransform(maskLayer,
maskLayer->GetLocalTransform() * combinedAsyncTransform);
maskLayer->GetLocalTransformTyped() * combinedAsyncTransform);
}
appliedTransform = true;
@ -1018,13 +1023,13 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
const FrameMetrics& metrics = aContent.Metrics();
AsyncPanZoomController* apzc = aContent.GetApzc();
Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform();
AsyncTransformComponentMatrix asyncTransform = apzc->GetCurrentAsyncTransform();
// |asyncTransform| represents the amount by which we have scrolled and
// zoomed since the last paint. Because the scrollbar was sized and positioned based
// on the painted content, we need to adjust it based on asyncTransform so that
// it reflects what the user is actually seeing now.
Matrix4x4 scrollbarTransform;
AsyncTransformComponentMatrix scrollbarTransform;
if (aScrollbar->GetScrollbarDirection() == Layer::VERTICAL) {
const ParentLayerCoord asyncScrollY = asyncTransform._42;
const float asyncZoomY = asyncTransform._22;
@ -1105,9 +1110,10 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
scrollbarTransform.PostTranslate(xTranslation, 0, 0);
}
Matrix4x4 transform = aScrollbar->GetLocalTransform() * scrollbarTransform;
LayerToParentLayerMatrix4x4 transform =
aScrollbar->GetLocalTransformTyped() * scrollbarTransform;
Matrix4x4 compensation;
AsyncTransformComponentMatrix compensation;
// If the scrollbar layer is for the root then the content's resolution
// applies to the scrollbar as well. Since we don't actually want the scroll
// thumb's size to vary with the zoom (other than its length reflecting the
@ -1115,9 +1121,10 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
// above), we apply a transform to cancel out this resolution.
if (metrics.IsRootContent()) {
compensation =
Matrix4x4::Scaling(metrics.GetPresShellResolution(),
metrics.GetPresShellResolution(),
1.0f).Inverse();
AsyncTransformComponentMatrix::Scaling(
metrics.GetPresShellResolution(),
metrics.GetPresShellResolution(),
1.0f).Inverse();
}
// If the scrollbar layer is a child of the content it is a scrollbar for,
// then we need to adjust for any async transform (including an overscroll
@ -1131,13 +1138,15 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
// the same coordinate space. This requires applying the content transform
// and then unapplying it after unapplying the async transform.
if (aScrollbarIsDescendant) {
Matrix4x4 asyncUntransform = (asyncTransform * apzc->GetOverscrollTransform()).Inverse();
Matrix4x4 asyncUntransform = (asyncTransform * apzc->GetOverscrollTransform()).Inverse().ToUnknownMatrix();
Matrix4x4 contentTransform = aContent.GetTransform();
Matrix4x4 contentUntransform = contentTransform.Inverse();
Matrix4x4 asyncCompensation = contentTransform
* asyncUntransform
* contentUntransform;
AsyncTransformComponentMatrix asyncCompensation =
ViewAs<AsyncTransformComponentMatrix>(
contentTransform
* asyncUntransform
* contentUntransform);
compensation = compensation * asyncCompensation;
@ -1146,7 +1155,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
// including the layer with the async transform. Otherwise the scrollbar
// shifts but gets clipped and so appears to flicker.
for (Layer* ancestor = aScrollbar; ancestor != aContent.GetLayer(); ancestor = ancestor->GetParent()) {
TransformClipRect(ancestor, ViewAs<ParentLayerToParentLayerMatrix4x4>(asyncCompensation));
TransformClipRect(ancestor, asyncCompensation);
}
}
transform = transform * compensation;
@ -1235,7 +1244,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
// We must apply the resolution scale before a pan/zoom transform, so we call
// GetTransform here.
Matrix4x4 oldTransform = aLayer->GetTransform();
LayerToParentLayerMatrix4x4 oldTransform = aLayer->GetTransformTyped() *
AsyncTransformMatrix();
CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel().ToScaleFactor();
@ -1294,13 +1304,13 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel().ToScaleFactor();
ParentLayerPoint translation = userRect.TopLeft() - geckoScroll;
Matrix4x4 treeTransform = ViewTransform(asyncZoom, -translation);
AsyncTransformComponentMatrix treeTransform = AsyncTransform(asyncZoom, -translation);
// Apply the tree transform on top of GetLocalTransform() here (rather than
// GetTransform()) in case the OMTA code in SampleAnimations already set a
// shadow transform; in that case we want to apply ours on top of that one
// rather than clobber it.
SetShadowTransform(aLayer, aLayer->GetLocalTransform() * treeTransform);
SetShadowTransform(aLayer, aLayer->GetLocalTransformTyped() * treeTransform);
// Make sure that overscroll and under-zoom are represented in the old
// transform so that fixed position content moves and scales accordingly.
@ -1337,8 +1347,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
// Make sure fixed position layers don't move away from their anchor points
// when we're asynchronously panning or zooming
AlignFixedAndStickyLayers(aLayer, aLayer, metrics.GetScrollId(), oldTransform,
aLayer->GetLocalTransform(), fixedLayerMargins,
false);
aLayer->GetLocalTransformTyped(),
fixedLayerMargins, false);
ExpandRootClipRect(aLayer, fixedLayerMargins);
}

Просмотреть файл

@ -28,32 +28,25 @@ class LayerManagerComposite;
class AutoResolveRefLayers;
class CompositorParent;
// Represents (affine) transforms that are calculated from a content view.
struct ViewTransform {
explicit ViewTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(),
ParentLayerPoint aTranslation = ParentLayerPoint())
// Represents async transforms consisting of a scale and a translation.
struct AsyncTransform {
explicit AsyncTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(),
ParentLayerPoint aTranslation = ParentLayerPoint())
: mScale(aScale)
, mTranslation(aTranslation)
{}
operator gfx::Matrix4x4() const
operator AsyncTransformComponentMatrix() const
{
return
gfx::Matrix4x4::Scaling(mScale.scale, mScale.scale, 1)
.PostTranslate(mTranslation.x, mTranslation.y, 0);
return AsyncTransformComponentMatrix::Scaling(mScale.scale, mScale.scale, 1)
.PostTranslate(mTranslation.x, mTranslation.y, 0);
}
// For convenience, to avoid writing the cumbersome
// "gfx::Matrix4x4(a) * gfx::Matrix4x4(b)".
friend gfx::Matrix4x4 operator*(const ViewTransform& a, const ViewTransform& b) {
return gfx::Matrix4x4(a) * gfx::Matrix4x4(b);
}
bool operator==(const ViewTransform& rhs) const {
bool operator==(const AsyncTransform& rhs) const {
return mTranslation == rhs.mTranslation && mScale == rhs.mScale;
}
bool operator!=(const ViewTransform& rhs) const {
bool operator!=(const AsyncTransform& rhs) const {
return !(*this == rhs);
}
@ -184,8 +177,8 @@ private:
*/
void AlignFixedAndStickyLayers(Layer* aLayer, Layer* aTransformedSubtreeRoot,
FrameMetrics::ViewID aTransformScrollId,
const gfx::Matrix4x4& aPreviousTransformForRoot,
const gfx::Matrix4x4& aCurrentTransformForRoot,
const LayerToParentLayerMatrix4x4& aPreviousTransformForRoot,
const LayerToParentLayerMatrix4x4& aCurrentTransformForRoot,
const ScreenMargin& aFixedLayerMargins,
bool aTransformAffectsLayerClip);

Просмотреть файл

@ -454,7 +454,7 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
return;
}
ViewTransform asyncTransformWithoutOverscroll;
AsyncTransform asyncTransformWithoutOverscroll;
ParentLayerPoint scrollOffset;
controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
scrollOffset);
@ -603,7 +603,7 @@ RenderLayers(ContainerT* aContainer,
gfx::Rect(aClipRect.ToUnknownRect()),
asyncTransform * aContainer->GetEffectiveTransform());
if (AsyncPanZoomController* apzc = layer->GetAsyncPanZoomController(i - 1)) {
asyncTransform = apzc->GetCurrentAsyncTransformWithOverscroll()
asyncTransform = apzc->GetCurrentAsyncTransformWithOverscroll().ToUnknownMatrix()
* asyncTransform;
}
}
@ -753,7 +753,7 @@ ContainerRender(ContainerT* aContainer,
for (LayerMetricsWrapper i(aContainer); i; i = i.GetFirstChild()) {
if (AsyncPanZoomController* apzc = i.GetApzc()) {
if (!apzc->GetAsyncTransformAppliedToContent()
&& !Matrix4x4(apzc->GetCurrentAsyncTransform()).IsIdentity()) {
&& !AsyncTransformComponentMatrix(apzc->GetCurrentAsyncTransform()).IsIdentity()) {
aManager->UnusedApzTransformWarning();
break;
}

Просмотреть файл

@ -703,6 +703,7 @@ PrepareFontOptions(FcPattern* aPattern,
// subpixel_order won't be used by the font as we won't use
// CAIRO_ANTIALIAS_SUBPIXEL, but don't leave it at default for
// caching reasons described above. Fall through:
MOZ_FALLTHROUGH;
case FC_RGBA_RGB:
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
break;

Просмотреть файл

@ -2180,6 +2180,7 @@ CreateScaledFont(FcPattern *aPattern, cairo_font_face_t *aFace)
// subpixel_order won't be used by the font as we won't use
// CAIRO_ANTIALIAS_SUBPIXEL, but don't leave it at default for
// caching reasons described above. Fall through:
MOZ_FALLTHROUGH;
case FC_RGBA_RGB:
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
break;

Просмотреть файл

@ -710,6 +710,18 @@ nsBMPDecoder::ReadColorTable(const char* aData, size_t aLength)
LexerTransition<nsBMPDecoder::State>
nsBMPDecoder::SkipGap()
{
// If there are no pixels we can stop.
//
// XXX: normally, if there are no pixels we will have stopped decoding before
// now, outside of this decoder. However, if the BMP is within an ICO file,
// it's possible that the ICO claimed the image had a non-zero size while the
// BMP claims otherwise. This test is to catch that awkward case. If we ever
// come up with a more general solution to this ICO-and-BMP-disagree-on-size
// problem, this test can be removed.
if (mH.mWidth == 0 || mH.mHeight == 0) {
return Transition::TerminateSuccess();
}
bool hasRLE = mH.mCompression == Compression::RLE8 ||
mH.mCompression == Compression::RLE4;
return hasRLE
@ -720,6 +732,7 @@ nsBMPDecoder::SkipGap()
LexerTransition<nsBMPDecoder::State>
nsBMPDecoder::ReadPixelRow(const char* aData)
{
MOZ_ASSERT(mCurrentRow > 0);
MOZ_ASSERT(mCurrentPos == 0);
const uint8_t* src = reinterpret_cast<const uint8_t*>(aData);

Просмотреть файл

@ -304,33 +304,18 @@ template <typename T>
extern JS_PUBLIC_API(void)
TraceNullableEdge(JSTracer* trc, JS::Heap<T>* edgep, const char* name);
extern JS_PUBLIC_API(void)
TraceNullableEdge(JSTracer* trc, JS::TenuredHeap<JSObject*>* edgep, const char* name);
// Edges that are always traced as part of root marking do not require
// incremental barriers. This function allows for marking non-barriered
// pointers, but asserts that this happens during root marking.
template <typename T>
extern JS_PUBLIC_API(void)
UnsafeTraceRoot(JSTracer* trc, T* edgep, const char* name);
} // namespace JS
// The following JS_CallUnbarriered*Tracer functions should only be called where
// you know for sure that a heap post barrier is not required. Use with extreme
// caution!
extern JS_PUBLIC_API(void)
JS_CallUnbarrieredValueTracer(JSTracer* trc, JS::Value* valuep, const char* name);
extern JS_PUBLIC_API(void)
JS_CallUnbarrieredIdTracer(JSTracer* trc, jsid* idp, const char* name);
extern JS_PUBLIC_API(void)
JS_CallUnbarrieredObjectTracer(JSTracer* trc, JSObject** objp, const char* name);
extern JS_PUBLIC_API(void)
JS_CallUnbarrieredStringTracer(JSTracer* trc, JSString** strp, const char* name);
extern JS_PUBLIC_API(void)
JS_CallUnbarrieredScriptTracer(JSTracer* trc, JSScript** scriptp, const char* name);
/**
* Trace an object that is known to always be tenured. No post barriers are
* required in this case.
*/
extern JS_PUBLIC_API(void)
JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap<JSObject*>* objp, const char* name);
extern JS_PUBLIC_API(void)
JS_TraceRuntime(JSTracer* trc);
@ -353,6 +338,10 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc,
void* thing, JS::TraceKind kind, bool includeDetails);
namespace js {
template <typename T>
extern JS_PUBLIC_API(void)
UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* edgep, const char* name);
namespace gc {
template <typename T>
extern JS_PUBLIC_API(bool)
@ -396,8 +385,8 @@ struct DefaultGCPolicy : public StructGCPolicy<T> {};
template <>
struct DefaultGCPolicy<jsid>
{
static void trace(JSTracer* trc, jsid* id, const char* name) {
JS_CallUnbarrieredIdTracer(trc, id, name);
static void trace(JSTracer* trc, jsid* idp, const char* name) {
js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
}
};

Просмотреть файл

@ -460,6 +460,14 @@ namespace JS {
template<typename T>
struct DeletePolicy
{
MOZ_CONSTEXPR DeletePolicy() {}
template<typename U>
MOZ_IMPLICIT DeletePolicy(DeletePolicy<U> other,
typename mozilla::EnableIf<mozilla::IsConvertible<U*, T*>::value,
int>::Type dummy = 0)
{}
void operator()(const T* ptr) {
js_delete(const_cast<T*>(ptr));
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -19,11 +19,10 @@
#ifndef asmjs_asmjs_h
#define asmjs_asmjs_h
#include "vm/NativeObject.h"
#include "NamespaceImports.h"
namespace js {
class AsmJSModule;
class ExclusiveContext;
namespace frontend {
template <typename ParseHandler> class Parser;
@ -34,29 +33,6 @@ namespace frontend {
typedef frontend::Parser<frontend::FullParseHandler> AsmJSParser;
typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
// An AsmJSModuleObject is an internal implementation object (i.e., not exposed
// directly to user script) which traces and owns an AsmJSModule. The
// AsmJSModuleObject is referenced by the extended slots of the content-visible
// module and export JSFunctions.
class AsmJSModuleObject : public NativeObject
{
static const unsigned MODULE_SLOT = 0;
public:
static const unsigned RESERVED_SLOTS = 1;
bool hasModule() const;
void setModule(AsmJSModule* module);
AsmJSModule& module() const;
void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
static const Class class_;
};
typedef Handle<AsmJSModuleObject*> HandleAsmJSModule;
// This function takes over parsing of a function starting with "use asm". The
// return value indicates whether an error was reported which the caller should
// propagate. If no error was reported, the function may still fail to validate

Просмотреть файл

@ -16,8 +16,8 @@
* limitations under the License.
*/
#ifndef wasm_ir_h
#define wasm_ir_h
#ifndef wasm_binary_h
#define wasm_binary_h
#include "asmjs/WasmTypes.h"
@ -422,102 +422,49 @@ enum NeedsBoundsCheck : uint8_t
NEEDS_BOUNDS_CHECK
};
// The FuncIR class contains the intermediate representation of a parsed/decoded
// and validated asm.js/WebAssembly function. The FuncIR lives only until it
// is fully compiled. Its contents are assumed to be well-formed; all validation
// of untrusted content must happen before FuncIR generation. A FuncIR object is
// associated with a LifoAlloc allocation which contains all the memory
// referenced by the FuncIR.
class FuncIR
typedef Vector<uint8_t, 0, SystemAllocPolicy> Bytecode;
typedef UniquePtr<Bytecode, JS::DeletePolicy<Bytecode>> UniqueBytecode;
// The Encoder class recycles (through its constructor) or creates a new Bytecode (through its
// init() method). Its Bytecode is released when it's done building the wasm IR in finish().
class Encoder
{
typedef Vector<ValType, 4, LifoAllocPolicy<Fallible>> ValTypeVector;
UniqueBytecode bytecode_;
mozilla::DebugOnly<bool> done_;
public:
// Source coordinates for a call site. As they're read sequentially, we
// don't need to store the call's bytecode offset, unless we want to
// check its consistency in debug mode.
struct SourceCoords {
DebugOnly<uint32_t> offset; // after call opcode
uint32_t line;
uint32_t column;
};
private:
typedef Vector<uint8_t, 4096, LifoAllocPolicy<Fallible>> Bytecode;
typedef Vector<SourceCoords, 4, LifoAllocPolicy<Fallible>> SourceCoordsVector;
// Note: this unrooted field assumes AutoKeepAtoms via TokenStream via
// asm.js compilation.
PropertyName* name_;
unsigned line_;
unsigned column_;
SourceCoordsVector callSourceCoords_;
uint32_t index_;
const LifoSig* sig_;
ValTypeVector localVars_;
Bytecode bytecode_;
unsigned generateTime_;
public:
FuncIR(LifoAlloc& alloc, PropertyName* name, unsigned line, unsigned column)
: name_(name),
line_(line),
column_(column),
callSourceCoords_(alloc),
index_(UINT_MAX),
sig_(nullptr),
localVars_(alloc),
bytecode_(alloc),
generateTime_(UINT_MAX)
{}
bool addVariable(ValType v) {
return localVars_.append(v);
}
bool addSourceCoords(uint32_t line, uint32_t column) {
SourceCoords sc = { bytecode_.length(), line, column };
return callSourceCoords_.append(sc);
}
void finish(uint32_t funcIndex, const LifoSig& sig, unsigned generateTime) {
MOZ_ASSERT(index_ == UINT_MAX);
MOZ_ASSERT(!sig_);
MOZ_ASSERT(generateTime_ == UINT_MAX);
index_ = funcIndex;
sig_ = &sig;
generateTime_ = generateTime;
}
private:
template<class T>
MOZ_WARN_UNUSED_RESULT
bool write(T v, size_t* offset) {
if (offset)
*offset = bytecode_.length();
return bytecode_.append(reinterpret_cast<uint8_t*>(&v), sizeof(T));
}
template<class T>
MOZ_WARN_UNUSED_RESULT
bool read(size_t* pc, T* out) const {
if (size_t(bytecode_.length() - *pc) >= sizeof(T))
return false;
memcpy((void*)out, &bytecode_[*pc], sizeof(T));
*pc += sizeof(T);
return true;
}
template<class T>
T uncheckedRead(size_t* pc) const {
MOZ_ASSERT(size_t(bytecode_.length() - *pc) >= sizeof(T));
T ret;
memcpy(&ret, &bytecode_[*pc], sizeof(T));
*pc += sizeof(T);
return ret;
*offset = bytecode_->length();
return bytecode_->append(reinterpret_cast<uint8_t*>(&v), sizeof(T));
}
public:
// Packing interface
Encoder()
: bytecode_(nullptr),
done_(false)
{}
bool init(UniqueBytecode bytecode) {
if (bytecode) {
bytecode_ = mozilla::Move(bytecode);
bytecode_->clear();
return true;
}
bytecode_.reset(js_new<Bytecode>());
return !!bytecode_;
}
size_t bytecodeOffset() const { return bytecode_->length(); }
bool empty() const { return bytecodeOffset() == 0; }
UniqueBytecode finish() {
MOZ_ASSERT(!done_);
done_ = true;
return mozilla::Move(bytecode_);
}
MOZ_WARN_UNUSED_RESULT bool
writeU8(uint8_t i, size_t* offset = nullptr) { return write<uint8_t>(i, offset); }
MOZ_WARN_UNUSED_RESULT bool
@ -554,14 +501,14 @@ class FuncIR
bool pcIsPatchable(size_t pc, unsigned size) const {
bool patchable = true;
for (unsigned i = 0; patchable && i < size; i++)
patchable &= Stmt(bytecode_[pc]) == Stmt::Bad;
patchable &= Stmt((*bytecode_)[pc]) == Stmt::Bad;
return patchable;
}
#endif
void patchU8(size_t pc, uint8_t i) {
MOZ_ASSERT(pcIsPatchable(pc, sizeof(uint8_t)));
bytecode_[pc] = i;
(*bytecode_)[pc] = i;
}
template<class T>
@ -569,44 +516,72 @@ class FuncIR
static_assert(sizeof(T) == sizeof(uint32_t),
"patch32 must be used with 32-bits wide types");
MOZ_ASSERT(pcIsPatchable(pc, sizeof(uint32_t)));
memcpy(&bytecode_[pc], &i, sizeof(uint32_t));
memcpy(&(*bytecode_)[pc], &i, sizeof(uint32_t));
}
void patchSig(size_t pc, const LifoSig* ptr) {
MOZ_ASSERT(pcIsPatchable(pc, sizeof(LifoSig*)));
memcpy(&bytecode_[pc], &ptr, sizeof(LifoSig*));
memcpy(&(*bytecode_)[pc], &ptr, sizeof(LifoSig*));
}
};
class Decoder
{
const Bytecode& bytecode_;
size_t cur_;
template<class T>
MOZ_WARN_UNUSED_RESULT
bool read(T* out) {
if (uintptr_t(bytecode_.length() - cur_) < sizeof(T))
return false;
memcpy((void*)out, &bytecode_[cur_], sizeof(T));
cur_ += sizeof(T);
return true;
}
template<class T>
T uncheckedRead() {
MOZ_ASSERT(uintptr_t(bytecode_.length() - cur_) >= sizeof(T));
T ret;
memcpy(&ret, &bytecode_[cur_], sizeof(T));
cur_ += sizeof(T);
return ret;
}
public:
explicit Decoder(const Bytecode& bytecode)
: bytecode_(bytecode),
cur_(0)
{}
bool done() const { return cur_ == bytecode_.length(); }
void assertCurrentIs(const DebugOnly<size_t> offset) const {
MOZ_ASSERT(offset == cur_);
}
// The fallible unpacking API should be used when we're not assuming
// anything about the bytecode, in particular if it is well-formed.
MOZ_WARN_UNUSED_RESULT bool
readU8 (size_t* pc, uint8_t* i) const { return read(pc, i); }
MOZ_WARN_UNUSED_RESULT bool
readI32(size_t* pc, int32_t* i) const { return read(pc, i); }
MOZ_WARN_UNUSED_RESULT bool
readF32(size_t* pc, float* f) const { return read(pc, f); }
MOZ_WARN_UNUSED_RESULT bool
readU32(size_t* pc, uint32_t* u) const { return read(pc, u); }
MOZ_WARN_UNUSED_RESULT bool
readF64(size_t* pc, double* d) const { return read(pc, d); }
MOZ_WARN_UNUSED_RESULT bool
readSig(size_t* pc, const LifoSig* sig) const { return read(pc, sig); }
MOZ_WARN_UNUSED_RESULT bool readU8 (uint8_t* i) { return read(i); }
MOZ_WARN_UNUSED_RESULT bool readI32(int32_t* i) { return read(i); }
MOZ_WARN_UNUSED_RESULT bool readF32(float* f) { return read(f); }
MOZ_WARN_UNUSED_RESULT bool readU32(uint32_t* u) { return read(u); }
MOZ_WARN_UNUSED_RESULT bool readF64(double* d) { return read(d); }
MOZ_WARN_UNUSED_RESULT bool readSig(const LifoSig* sig) { return read(sig); }
MOZ_WARN_UNUSED_RESULT bool
readI32X4(size_t* pc, jit::SimdConstant* c) const {
MOZ_WARN_UNUSED_RESULT bool readI32X4(jit::SimdConstant* c) {
int32_t v[4] = { 0, 0, 0, 0 };
for (size_t i = 0; i < 4; i++) {
if (!readI32(pc, &v[i]))
if (!readI32(&v[i]))
return false;
}
*c = jit::SimdConstant::CreateX4(v[0], v[1], v[2], v[3]);
return true;
}
MOZ_WARN_UNUSED_RESULT bool
readF32X4(size_t* pc, jit::SimdConstant* c) const {
MOZ_WARN_UNUSED_RESULT bool readF32X4(jit::SimdConstant* c) {
float v[4] = { 0., 0., 0., 0. };
for (size_t i = 0; i < 4; i++) {
if (!readF32(pc, &v[i]))
if (!readF32(&v[i]))
return false;
}
*c = jit::SimdConstant::CreateX4(v[0], v[1], v[2], v[3]);
@ -615,45 +590,100 @@ class FuncIR
// The unfallible unpacking API should be used when we are sure that the
// bytecode is well-formed.
uint8_t uncheckedReadU8 (size_t* pc) const { return uncheckedRead<uint8_t>(pc); }
int32_t uncheckedReadI32(size_t* pc) const { return uncheckedRead<int32_t>(pc); }
float uncheckedReadF32(size_t* pc) const { return uncheckedRead<float>(pc); }
uint32_t uncheckedReadU32(size_t* pc) const { return uncheckedRead<uint32_t>(pc); }
double uncheckedReadF64(size_t* pc) const { return uncheckedRead<double>(pc); }
const LifoSig* uncheckedReadSig(size_t* pc) const { return uncheckedRead<const LifoSig*>(pc); }
uint8_t uncheckedReadU8 () { return uncheckedRead<uint8_t>(); }
int32_t uncheckedReadI32() { return uncheckedRead<int32_t>(); }
float uncheckedReadF32() { return uncheckedRead<float>(); }
uint32_t uncheckedReadU32() { return uncheckedRead<uint32_t>(); }
double uncheckedReadF64() { return uncheckedRead<double>(); }
const LifoSig* uncheckedReadSig() { return uncheckedRead<const LifoSig*>(); }
jit::SimdConstant uncheckedReadI32X4(size_t* pc) const {
jit::SimdConstant uncheckedReadI32X4() {
int32_t v[4] = { 0, 0, 0, 0 };
for (size_t i = 0; i < 4; i++)
v[i] = uncheckedReadI32(pc);
v[i] = uncheckedReadI32();
return jit::SimdConstant::CreateX4(v[0], v[1], v[2], v[3]);
}
jit::SimdConstant uncheckedReadF32X4(size_t* pc) const {
jit::SimdConstant uncheckedReadF32X4() {
float v[4] = { 0., 0., 0., 0. };
for (size_t i = 0; i < 4; i++)
v[i] = uncheckedReadF32(pc);
v[i] = uncheckedReadF32();
return jit::SimdConstant::CreateX4(v[0], v[1], v[2], v[3]);
}
};
// Source coordinates for a call site. As they're read sequentially, we
// don't need to store the call's bytecode offset, unless we want to
// check its correctness in debug mode.
struct SourceCoords {
DebugOnly<size_t> offset; // after call opcode
uint32_t line;
uint32_t column;
};
typedef Vector<SourceCoords, 0, SystemAllocPolicy> SourceCoordsVector;
typedef Vector<ValType, 0, SystemAllocPolicy> ValTypeVector;
// The FuncBytecode class contains the intermediate representation of a
// parsed/decoded and validated asm.js/WebAssembly function. The FuncBytecode
// lives only until it is fully compiled.
class FuncBytecode
{
// Note: this unrooted field assumes AutoKeepAtoms via TokenStream via
// asm.js compilation.
PropertyName* name_;
unsigned line_;
unsigned column_;
SourceCoordsVector callSourceCoords_;
uint32_t index_;
const LifoSig& sig_;
UniqueBytecode bytecode_;
ValTypeVector localVars_;
unsigned generateTime_;
public:
FuncBytecode(PropertyName* name,
unsigned line,
unsigned column,
SourceCoordsVector&& sourceCoords,
uint32_t index,
const LifoSig& sig,
UniqueBytecode bytecode,
ValTypeVector&& localVars,
unsigned generateTime)
: name_(name),
line_(line),
column_(column),
callSourceCoords_(mozilla::Move(sourceCoords)),
index_(index),
sig_(sig),
bytecode_(mozilla::Move(bytecode)),
localVars_(mozilla::Move(localVars)),
generateTime_(generateTime)
{}
UniqueBytecode recycleBytecode() { return mozilla::Move(bytecode_); }
// Read-only interface
PropertyName* name() const { return name_; }
unsigned line() const { return line_; }
unsigned column() const { return column_; }
const SourceCoords& sourceCoords(size_t i) const { return callSourceCoords_[i]; }
uint32_t index() const { MOZ_ASSERT(index_ != UINT32_MAX); return index_; }
const LifoSig& sig() const { MOZ_ASSERT(sig_); return *sig_; }
uint32_t index() const { return index_; }
const LifoSig& sig() const { return sig_; }
const Bytecode& bytecode() const { return *bytecode_; }
size_t numLocalVars() const { return localVars_.length(); }
ValType localVarType(size_t i) const { return localVars_[i]; }
size_t numLocals() const { return sig_->args().length() + numLocalVars(); }
size_t numLocals() const { return sig_.args().length() + numLocalVars(); }
unsigned generateTime() const { MOZ_ASSERT(generateTime_ != UINT_MAX); return generateTime_; }
size_t size() const { return bytecode_.length(); }
unsigned generateTime() const { return generateTime_; }
};
typedef mozilla::UniquePtr<FuncBytecode, JS::DeletePolicy<FuncBytecode>> UniqueFuncBytecode;
} // namespace wasm
} // namespace js
#endif // wasm_ir_h
#endif // wasm_binary_h

Просмотреть файл

@ -35,20 +35,18 @@ static const unsigned COMPILATION_LIFO_DEFAULT_CHUNK_SIZE = 64 * 1024;
ModuleGenerator::ModuleGenerator(ExclusiveContext* cx)
: cx_(cx),
args_(cx),
globalBytes_(InitialGlobalDataBytes),
slowFuncs_(cx),
lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE),
jcx_(CompileRuntime::get(cx->compartment()->runtimeFromAnyThread())),
alloc_(&lifo_),
masm_(MacroAssembler::AsmJSToken(), alloc_),
sigs_(cx),
funcEntryOffsets_(cx),
exportFuncIndices_(cx),
parallel_(false),
outstanding_(0),
tasks_(cx),
freeTasks_(cx),
funcBytes_(0),
funcEntryOffsets_(cx),
activeFunc_(nullptr),
finishedFuncs_(false)
{
@ -108,8 +106,15 @@ ParallelCompilationEnabled(ExclusiveContext* cx)
bool
ModuleGenerator::init()
{
staticLinkData_ = cx_->make_unique<StaticLinkData>();
if (!staticLinkData_)
module_ = cx_->make_unique<ModuleData>();
if (!module_)
return false;
module_->globalBytes = InitialGlobalDataBytes;
module_->compileArgs = CompileArgs(cx_);
link_ = cx_->make_unique<StaticLinkData>();
if (!link_)
return false;
if (!sigs_.init())
@ -138,7 +143,7 @@ ModuleGenerator::init()
return false;
JSRuntime* runtime = cx_->compartment()->runtimeFromAnyThread();
for (size_t i = 0; i < numTasks; i++)
tasks_.infallibleEmplaceBack(runtime, args_, COMPILATION_LIFO_DEFAULT_CHUNK_SIZE);
tasks_.infallibleEmplaceBack(runtime, args(), COMPILATION_LIFO_DEFAULT_CHUNK_SIZE);
if (!freeTasks_.reserve(numTasks))
return false;
@ -151,13 +156,17 @@ ModuleGenerator::init()
bool
ModuleGenerator::allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOffset)
{
uint32_t pad = ComputeByteAlignment(globalBytes_, align);
if (UINT32_MAX - globalBytes_ < pad + bytes)
uint32_t globalBytes = module_->globalBytes;
uint32_t pad = ComputeByteAlignment(globalBytes, align);
if (UINT32_MAX - globalBytes < pad + bytes)
return false;
globalBytes_ += pad;
*globalDataOffset = globalBytes_;
globalBytes_ += bytes;
globalBytes += pad;
*globalDataOffset = globalBytes;
globalBytes += bytes;
module_->globalBytes = globalBytes;
return true;
}
@ -191,7 +200,7 @@ ModuleGenerator::finishOutstandingTask()
bool
ModuleGenerator::finishTask(IonCompileTask* task)
{
const FuncIR& func = task->func();
const FuncBytecode& func = task->func();
FuncCompileResults& results = task->results();
// Offset the recorded FuncOffsets by the offset of the function in the
@ -216,10 +225,10 @@ ModuleGenerator::finishTask(IonCompileTask* task)
CacheableChars funcName = StringToNewUTF8CharsZ(cx_, *func.name());
if (!funcName)
return false;
uint32_t nameIndex = funcNames_.length();
if (!funcNames_.emplaceBack(Move(funcName)))
uint32_t nameIndex = module_->funcNames.length();
if (!module_->funcNames.emplaceBack(Move(funcName)))
return false;
if (!codeRanges_.emplaceBack(nameIndex, func.line(), results.offsets()))
if (!module_->codeRanges.emplaceBack(nameIndex, func.line(), results.offsets()))
return false;
// Keep a record of slow functions for printing in the final console message.
@ -229,7 +238,6 @@ ModuleGenerator::finishTask(IonCompileTask* task)
return false;
}
task->reset();
freeTasks_.infallibleAppend(task);
return true;
}
@ -279,72 +287,73 @@ ModuleGenerator::declareImport(MallocSig&& sig, unsigned* index)
if (!allocateGlobalBytes(Module::SizeOfImportExit, sizeof(void*), &globalDataOffset))
return false;
*index = unsigned(imports_.length());
return imports_.emplaceBack(Move(sig), globalDataOffset);
*index = unsigned(module_->imports.length());
return module_->imports.emplaceBack(Move(sig), globalDataOffset);
}
uint32_t
ModuleGenerator::numDeclaredImports() const
{
return imports_.length();
return module_->imports.length();
}
uint32_t
ModuleGenerator::importExitGlobalDataOffset(uint32_t index) const
{
return imports_[index].exitGlobalDataOffset();
return module_->imports[index].exitGlobalDataOffset();
}
const MallocSig&
ModuleGenerator::importSig(uint32_t index) const
{
return imports_[index].sig();
return module_->imports[index].sig();
}
bool
ModuleGenerator::defineImport(uint32_t index, ProfilingOffsets interpExit, ProfilingOffsets jitExit)
{
Import& import = imports_[index];
Import& import = module_->imports[index];
import.initInterpExitOffset(interpExit.begin);
import.initJitExitOffset(jitExit.begin);
return codeRanges_.emplaceBack(CodeRange::ImportInterpExit, interpExit) &&
codeRanges_.emplaceBack(CodeRange::ImportJitExit, jitExit);
return module_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExit) &&
module_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExit);
}
bool
ModuleGenerator::declareExport(MallocSig&& sig, uint32_t funcIndex)
{
return exports_.emplaceBack(Move(sig), funcIndex);
return module_->exports.emplaceBack(Move(sig)) &&
exportFuncIndices_.append(funcIndex);
}
uint32_t
ModuleGenerator::exportFuncIndex(uint32_t index) const
{
return exports_[index].funcIndex();
return exportFuncIndices_[index];
}
const MallocSig&
ModuleGenerator::exportSig(uint32_t index) const
{
return exports_[index].sig();
return module_->exports[index].sig();
}
uint32_t
ModuleGenerator::numDeclaredExports() const
{
return exports_.length();
return module_->exports.length();
}
bool
ModuleGenerator::defineExport(uint32_t index, Offsets offsets)
{
exports_[index].initStubOffset(offsets.begin);
return codeRanges_.emplaceBack(CodeRange::Entry, offsets);
module_->exports[index].initStubOffset(offsets.begin);
return module_->codeRanges.emplaceBack(CodeRange::Entry, offsets);
}
bool
ModuleGenerator::startFunc(PropertyName* name, unsigned line, unsigned column,
FunctionGenerator* fg)
UniqueBytecode* recycled, FunctionGenerator* fg)
{
MOZ_ASSERT(!activeFunc_);
MOZ_ASSERT(!finishedFuncs_);
@ -353,25 +362,38 @@ ModuleGenerator::startFunc(PropertyName* name, unsigned line, unsigned column,
return false;
IonCompileTask* task = freeTasks_.popCopy();
FuncIR* func = task->lifo().new_<FuncIR>(task->lifo(), name, line, column);
if (!func)
return false;
task->init(*func);
task->reset(recycled);
fg->name_= name;
fg->line_ = line;
fg->column_ = column;
fg->m_ = this;
fg->task_ = task;
fg->func_ = func;
activeFunc_ = fg;
return true;
}
bool
ModuleGenerator::finishFunc(uint32_t funcIndex, const LifoSig& sig, unsigned generateTime,
FunctionGenerator* fg)
ModuleGenerator::finishFunc(uint32_t funcIndex, const LifoSig& sig, UniqueBytecode bytecode,
unsigned generateTime, FunctionGenerator* fg)
{
MOZ_ASSERT(activeFunc_ == fg);
fg->func_->finish(funcIndex, sig, generateTime);
UniqueFuncBytecode func = cx_->make_unique<FuncBytecode>(fg->name_,
fg->line_,
fg->column_,
Move(fg->callSourceCoords_),
funcIndex,
sig,
Move(bytecode),
Move(fg->localVars_),
generateTime
);
if (!func)
return false;
fg->task_->init(Move(func));
if (parallel_) {
if (!StartOffThreadWasmCompile(cx_, fg->task_))
@ -386,7 +408,6 @@ ModuleGenerator::finishFunc(uint32_t funcIndex, const LifoSig& sig, unsigned gen
fg->m_ = nullptr;
fg->task_ = nullptr;
fg->func_ = nullptr;
activeFunc_ = nullptr;
return true;
}
@ -417,7 +438,7 @@ ModuleGenerator::finishFuncs()
masm_.patchCall(callerOffset, calleeOffset);
}
funcBytes_ = masm_.size();
module_->functionBytes = masm_.size();
finishedFuncs_ = true;
return true;
}
@ -437,7 +458,7 @@ ModuleGenerator::declareFuncPtrTable(uint32_t numElems, uint32_t* index)
if (!allocateGlobalBytes(numElems * sizeof(void*), sizeof(void*), &globalDataOffset))
return false;
StaticLinkData::FuncPtrTableVector& tables = staticLinkData_->funcPtrTables;
StaticLinkData::FuncPtrTableVector& tables = link_->funcPtrTables;
*index = tables.length();
if (!tables.emplaceBack(globalDataOffset))
@ -452,7 +473,7 @@ ModuleGenerator::declareFuncPtrTable(uint32_t numElems, uint32_t* index)
uint32_t
ModuleGenerator::funcPtrTableGlobalDataOffset(uint32_t index) const
{
return staticLinkData_->funcPtrTables[index].globalDataOffset;
return link_->funcPtrTables[index].globalDataOffset;
}
void
@ -460,7 +481,7 @@ ModuleGenerator::defineFuncPtrTable(uint32_t index, const Vector<uint32_t>& elem
{
MOZ_ASSERT(finishedFuncs_);
StaticLinkData::FuncPtrTable& table = staticLinkData_->funcPtrTables[index];
StaticLinkData::FuncPtrTable& table = link_->funcPtrTables[index];
MOZ_ASSERT(table.elemOffsets.length() == elemFuncIndices.length());
for (size_t i = 0; i < elemFuncIndices.length(); i++)
@ -471,69 +492,74 @@ bool
ModuleGenerator::defineInlineStub(Offsets offsets)
{
MOZ_ASSERT(finishedFuncs_);
return codeRanges_.emplaceBack(CodeRange::Inline, offsets);
return module_->codeRanges.emplaceBack(CodeRange::Inline, offsets);
}
bool
ModuleGenerator::defineSyncInterruptStub(ProfilingOffsets offsets)
{
MOZ_ASSERT(finishedFuncs_);
return codeRanges_.emplaceBack(CodeRange::Interrupt, offsets);
return module_->codeRanges.emplaceBack(CodeRange::Interrupt, offsets);
}
bool
ModuleGenerator::defineAsyncInterruptStub(Offsets offsets)
{
MOZ_ASSERT(finishedFuncs_);
staticLinkData_->pod.interruptOffset = offsets.begin;
return codeRanges_.emplaceBack(CodeRange::Inline, offsets);
link_->pod.interruptOffset = offsets.begin;
return module_->codeRanges.emplaceBack(CodeRange::Inline, offsets);
}
bool
ModuleGenerator::defineOutOfBoundsStub(Offsets offsets)
{
MOZ_ASSERT(finishedFuncs_);
staticLinkData_->pod.outOfBoundsOffset = offsets.begin;
return codeRanges_.emplaceBack(CodeRange::Inline, offsets);
link_->pod.outOfBoundsOffset = offsets.begin;
return module_->codeRanges.emplaceBack(CodeRange::Inline, offsets);
}
Module*
bool
ModuleGenerator::finish(HeapUsage heapUsage,
Module::MutedBool mutedErrors,
MutedErrorsBool mutedErrors,
CacheableChars filename,
CacheableTwoByteChars displayURL,
UniqueStaticLinkData* staticLinkData,
UniqueModuleData* module,
UniqueStaticLinkData* linkData,
SlowFunctionVector* slowFuncs)
{
MOZ_ASSERT(!activeFunc_);
MOZ_ASSERT(finishedFuncs_);
module_->heapUsage = heapUsage;
module_->mutedErrors = mutedErrors;
module_->filename = Move(filename);
if (!GenerateStubs(*this, UsesHeap(heapUsage)))
return nullptr;
return false;
masm_.finish();
if (masm_.oom())
return nullptr;
return false;
// Start global data on a new page so JIT code may be given independent
// protection flags. Note assumption that global data starts right after
// code below.
uint32_t codeBytes = AlignBytes(masm_.bytesNeeded(), AsmJSPageSize);
module_->codeBytes = AlignBytes(masm_.bytesNeeded(), AsmJSPageSize);
// Inflate the global bytes up to page size so that the total bytes are a
// page size (as required by the allocator functions).
globalBytes_ = AlignBytes(globalBytes_, AsmJSPageSize);
uint32_t totalBytes = codeBytes + globalBytes_;
module_->globalBytes = AlignBytes(module_->globalBytes, AsmJSPageSize);
// Allocate the code (guarded by a UniquePtr until it is given to the Module).
UniqueCodePtr code = AllocateCode(cx_, totalBytes);
if (!code)
return nullptr;
module_->code = AllocateCode(cx_, module_->totalBytes());
if (!module_->code)
return false;
// Delay flushing until Module::dynamicallyLink. The flush-inhibited range
// is set by executableCopy.
AutoFlushICache afc("ModuleGenerator::finish", /* inhibit = */ true);
masm_.executableCopy(code.get());
uint8_t* code = module_->code.get();
masm_.executableCopy(code);
// c.f. JitCode::copyFrom
MOZ_ASSERT(masm_.jumpRelocationTableBytes() == 0);
@ -543,16 +569,18 @@ ModuleGenerator::finish(HeapUsage heapUsage,
// Convert the CallSiteAndTargetVector (needed during generation) to a
// CallSiteVector (what is stored in the Module).
CallSiteVector callSites;
if (!callSites.appendAll(masm_.callSites()))
return nullptr;
if (!module_->callSites.appendAll(masm_.callSites()))
return false;
// The MacroAssembler has accumulated all the heap accesses during codegen.
module_->heapAccesses = masm_.extractHeapAccesses();
// Add links to absolute addresses identified symbolically.
StaticLinkData::SymbolicLinkArray& symbolicLinks = staticLinkData_->symbolicLinks;
StaticLinkData::SymbolicLinkArray& symbolicLinks = link_->symbolicLinks;
for (size_t i = 0; i < masm_.numAsmJSAbsoluteAddresses(); i++) {
AsmJSAbsoluteAddress src = masm_.asmJSAbsoluteAddress(i);
if (!symbolicLinks[src.target].append(src.patchAt.offset()))
return nullptr;
return false;
}
// Relative link metadata: absolute addresses that refer to another point within
@ -565,8 +593,8 @@ ModuleGenerator::finish(HeapUsage heapUsage,
StaticLinkData::InternalLink link(StaticLinkData::InternalLink::CodeLabel);
link.patchAtOffset = masm_.labelToPatchOffset(*cl.patchAt());
link.targetOffset = cl.target()->offset();
if (!staticLinkData_->internalLinks.append(link))
return nullptr;
if (!link_->internalLinks.append(link))
return false;
}
#if defined(JS_CODEGEN_X86)
@ -577,9 +605,9 @@ ModuleGenerator::finish(HeapUsage heapUsage,
AsmJSGlobalAccess a = masm_.asmJSGlobalAccess(i);
StaticLinkData::InternalLink link(StaticLinkData::InternalLink::RawPointer);
link.patchAtOffset = masm_.labelToPatchOffset(a.patchAt);
link.targetOffset = codeBytes + a.globalDataOffset;
if (!staticLinkData_->internalLinks.append(link))
return nullptr;
link.targetOffset = module_->codeBytes + a.globalDataOffset;
if (!link_->internalLinks.append(link))
return false;
}
#endif
@ -591,38 +619,24 @@ ModuleGenerator::finish(HeapUsage heapUsage,
size_t off = masm_.longJump(i);
StaticLinkData::InternalLink link(StaticLinkData::InternalLink::InstructionImmediate);
link.patchAtOffset = off;
link.targetOffset = Assembler::ExtractInstructionImmediate(code.get() + off) -
uintptr_t(code.get());
if (!staticLinkData_->internalLinks.append(link))
return nullptr;
link.targetOffset = Assembler::ExtractInstructionImmediate(code + off) - uintptr_t(code);
if (!link_->internalLinks.append(link))
return false;
}
#endif
#if defined(JS_CODEGEN_X64)
// Global data accesses on x64 use rip-relative addressing and thus do
// not need patching after deserialization.
uint8_t* globalData = code.get() + codeBytes;
uint8_t* globalData = code + module_->codeBytes;
for (size_t i = 0; i < masm_.numAsmJSGlobalAccesses(); i++) {
AsmJSGlobalAccess a = masm_.asmJSGlobalAccess(i);
masm_.patchAsmJSGlobalAccess(a.patchAt, code.get(), globalData, a.globalDataOffset);
masm_.patchAsmJSGlobalAccess(a.patchAt, code, globalData, a.globalDataOffset);
}
#endif
*staticLinkData = Move(staticLinkData_);
*module = Move(module_);
*linkData = Move(link_);
*slowFuncs = Move(slowFuncs_);
return cx_->new_<Module>(args_,
funcBytes_,
codeBytes,
globalBytes_,
heapUsage,
mutedErrors,
Move(code),
Move(imports_),
Move(exports_),
masm_.extractHeapAccesses(),
Move(codeRanges_),
Move(callSites),
Move(funcNames_),
Move(filename),
Move(displayURL));
return true;
}

Просмотреть файл

@ -19,8 +19,8 @@
#ifndef wasm_generator_h
#define wasm_generator_h
#include "asmjs/WasmBinary.h"
#include "asmjs/WasmIonCompile.h"
#include "asmjs/WasmIR.h"
#include "asmjs/WasmModule.h"
#include "jit/MacroAssembler.h"
@ -54,6 +54,7 @@ typedef Vector<SlowFunction> SlowFunctionVector;
class MOZ_STACK_CLASS ModuleGenerator
{
typedef Vector<uint32_t> FuncOffsetVector;
typedef Vector<uint32_t> FuncIndexVector;
struct SigHashPolicy
{
@ -64,17 +65,10 @@ class MOZ_STACK_CLASS ModuleGenerator
typedef HashSet<const LifoSig*, SigHashPolicy> SigSet;
ExclusiveContext* cx_;
CompileArgs args_;
// Data handed over to the Module in finish()
uint32_t globalBytes_;
ImportVector imports_;
ExportVector exports_;
CodeRangeVector codeRanges_;
CacheableCharsVector funcNames_;
// Data handed back to the caller in finish()
UniqueStaticLinkData staticLinkData_;
UniqueModuleData module_;
UniqueStaticLinkData link_;
SlowFunctionVector slowFuncs_;
// Data scoped to the ModuleGenerator's lifetime
@ -83,6 +77,8 @@ class MOZ_STACK_CLASS ModuleGenerator
jit::TempAllocator alloc_;
jit::MacroAssembler masm_;
SigSet sigs_;
FuncOffsetVector funcEntryOffsets_;
FuncIndexVector exportFuncIndices_;
// Parallel compilation
bool parallel_;
@ -90,9 +86,7 @@ class MOZ_STACK_CLASS ModuleGenerator
Vector<IonCompileTask> tasks_;
Vector<IonCompileTask*> freeTasks_;
// Function compilation
uint32_t funcBytes_;
FuncOffsetVector funcEntryOffsets_;
// Assertions
DebugOnly<FunctionGenerator*> activeFunc_;
DebugOnly<bool> finishedFuncs_;
@ -106,7 +100,7 @@ class MOZ_STACK_CLASS ModuleGenerator
bool init();
CompileArgs args() const { return args_; }
CompileArgs args() const { return module_->compileArgs; }
jit::MacroAssembler& masm() { return masm_; }
const FuncOffsetVector& funcEntryOffsets() const { return funcEntryOffsets_; }
@ -130,8 +124,10 @@ class MOZ_STACK_CLASS ModuleGenerator
bool defineExport(uint32_t index, Offsets offsets);
// Functions:
bool startFunc(PropertyName* name, unsigned line, unsigned column, FunctionGenerator* fg);
bool finishFunc(uint32_t funcIndex, const LifoSig& sig, unsigned generateTime, FunctionGenerator* fg);
bool startFunc(PropertyName* name, unsigned line, unsigned column, UniqueBytecode* recycled,
FunctionGenerator* fg);
bool finishFunc(uint32_t funcIndex, const LifoSig& sig, UniqueBytecode bytecode,
unsigned generateTime, FunctionGenerator* fg);
bool finishFuncs();
// Function-pointer tables:
@ -145,14 +141,16 @@ class MOZ_STACK_CLASS ModuleGenerator
bool defineAsyncInterruptStub(Offsets offsets);
bool defineOutOfBoundsStub(Offsets offsets);
// Null return indicates failure. The caller must immediately root a
// non-null return value.
Module* finish(HeapUsage heapUsage,
Module::MutedBool mutedErrors,
CacheableChars filename,
CacheableTwoByteChars displayURL,
UniqueStaticLinkData* staticLinkData,
SlowFunctionVector* slowFuncs);
// Return a ModuleData object which may be used to construct a Module, the
// StaticLinkData required to call Module::staticallyLink, and the list of
// functions that took a long time to compile.
bool finish(HeapUsage heapUsage,
MutedErrorsBool mutedErrors,
CacheableChars filename,
CacheableTwoByteChars displayURL,
UniqueModuleData* module,
UniqueStaticLinkData* staticLinkData,
SlowFunctionVector* slowFuncs);
};
// A FunctionGenerator encapsulates the generation of a single function body.
@ -164,13 +162,36 @@ class MOZ_STACK_CLASS FunctionGenerator
{
friend class ModuleGenerator;
ModuleGenerator* m_;
IonCompileTask* task_;
FuncIR* func_;
ModuleGenerator* m_;
IonCompileTask* task_;
// Function metadata created during function generation, then handed over
// to the FuncBytecode in ModuleGenerator::finishFunc().
SourceCoordsVector callSourceCoords_;
ValTypeVector localVars_;
// Note: this unrooted field assumes AutoKeepAtoms via TokenStream via
// asm.js compilation.
PropertyName* name_;
unsigned line_;
unsigned column_;
public:
FunctionGenerator() : m_(nullptr), task_(nullptr), func_(nullptr) {}
FuncIR& func() const { MOZ_ASSERT(func_); return *func_; }
FunctionGenerator()
: m_(nullptr),
task_(nullptr),
name_(nullptr),
line_(0),
column_(0)
{}
bool addSourceCoords(size_t byteOffset, uint32_t line, uint32_t column) {
SourceCoords sc = { byteOffset, line, column };
return callSourceCoords_.append(sc);
}
bool addVariable(ValType v) {
return localVars_.append(v);
}
};
} // namespace wasm

Просмотреть файл

@ -39,8 +39,9 @@ class FunctionCompiler
typedef HashMap<size_t, BlockVector, DefaultHasher<uint32_t>, SystemAllocPolicy> UnlabeledBlockMap;
typedef Vector<size_t, 4, SystemAllocPolicy> PositionStack;
const FuncIR& func_;
size_t pc_;
const FuncBytecode& func_;
Decoder decoder_;
size_t nextId_;
size_t lastReadCallSite_;
TempAllocator& alloc_;
@ -60,9 +61,10 @@ class FunctionCompiler
FuncCompileResults& compileResults_;
public:
FunctionCompiler(const FuncIR& func, MIRGenerator& mirGen, FuncCompileResults& compileResults)
FunctionCompiler(const FuncBytecode& func, MIRGenerator& mirGen, FuncCompileResults& compileResults)
: func_(func),
pc_(0),
decoder_(func.bytecode()),
nextId_(0),
lastReadCallSite_(0),
alloc_(mirGen.alloc()),
graph_(mirGen.graph()),
@ -91,6 +93,8 @@ class FunctionCompiler
const LifoSig::ArgVector& args = func_.sig().args();
unsigned firstVarSlot = args.length();
if (!mirGen_.ensureBallast())
return false;
if (!newBlock(/* pred = */ nullptr, &curBlock_))
return false;
@ -145,7 +149,7 @@ class FunctionCompiler
MOZ_ASSERT(labeledBreaks_.empty());
MOZ_ASSERT(labeledContinues_.empty());
MOZ_ASSERT(inDeadCode());
MOZ_ASSERT(pc_ == func_.size(), "all bytecode must be consumed");
MOZ_ASSERT(decoder_.done(), "all bytecode must be consumed");
}
/************************* Read-only interface (after local scope setup) */
@ -889,9 +893,9 @@ class FunctionCompiler
return curBlock_->pop();
}
bool startPendingLoop(size_t pos, MBasicBlock** loopEntry)
bool startPendingLoop(size_t id, MBasicBlock** loopEntry)
{
if (!loopStack_.append(pos) || !breakableStack_.append(pos))
if (!loopStack_.append(id) || !breakableStack_.append(id))
return false;
if (inDeadCode()) {
*loopEntry = nullptr;
@ -934,10 +938,10 @@ class FunctionCompiler
private:
size_t popLoop()
{
size_t pos = loopStack_.popCopy();
MOZ_ASSERT(!unlabeledContinues_.has(pos));
size_t id = loopStack_.popCopy();
MOZ_ASSERT(!unlabeledContinues_.has(id));
breakableStack_.popBack();
return pos;
return id;
}
void fixupRedundantPhis(MBasicBlock* b)
@ -998,11 +1002,11 @@ class FunctionCompiler
public:
bool closeLoop(MBasicBlock* loopEntry, MBasicBlock* afterLoop)
{
size_t pos = popLoop();
size_t id = popLoop();
if (!loopEntry) {
MOZ_ASSERT(!afterLoop);
MOZ_ASSERT(inDeadCode());
MOZ_ASSERT(!unlabeledBreaks_.has(pos));
MOZ_ASSERT(!unlabeledBreaks_.has(id));
return true;
}
MOZ_ASSERT(loopEntry->loopDepth() == loopStack_.length() + 1);
@ -1016,15 +1020,15 @@ class FunctionCompiler
curBlock_ = afterLoop;
if (curBlock_)
mirGraph().moveBlockToEnd(curBlock_);
return bindUnlabeledBreaks(pos);
return bindUnlabeledBreaks(id);
}
bool branchAndCloseDoWhileLoop(MDefinition* cond, MBasicBlock* loopEntry)
{
size_t pos = popLoop();
size_t id = popLoop();
if (!loopEntry) {
MOZ_ASSERT(inDeadCode());
MOZ_ASSERT(!unlabeledBreaks_.has(pos));
MOZ_ASSERT(!unlabeledBreaks_.has(id));
return true;
}
MOZ_ASSERT(loopEntry->loopDepth() == loopStack_.length() + 1);
@ -1053,13 +1057,13 @@ class FunctionCompiler
curBlock_ = afterLoop;
}
}
return bindUnlabeledBreaks(pos);
return bindUnlabeledBreaks(id);
}
bool bindContinues(size_t pos, const LabelVector* maybeLabels)
bool bindContinues(size_t id, const LabelVector* maybeLabels)
{
bool createdJoinBlock = false;
if (UnlabeledBlockMap::Ptr p = unlabeledContinues_.lookup(pos)) {
if (UnlabeledBlockMap::Ptr p = unlabeledContinues_.lookup(id)) {
if (!bindBreaksOrContinues(&p->value(), &createdJoinBlock))
return false;
unlabeledContinues_.remove(p);
@ -1085,10 +1089,10 @@ class FunctionCompiler
return addBreakOrContinue(loopStack_.back(), &unlabeledContinues_);
}
bool startSwitch(size_t pos, MDefinition* expr, int32_t low, int32_t high,
bool startSwitch(size_t id, MDefinition* expr, int32_t low, int32_t high,
MBasicBlock** switchBlock)
{
if (!breakableStack_.append(pos))
if (!breakableStack_.append(id))
return false;
if (inDeadCode()) {
*switchBlock = nullptr;
@ -1129,7 +1133,7 @@ class FunctionCompiler
bool joinSwitch(MBasicBlock* switchBlock, const BlockVector& cases, MBasicBlock* defaultBlock)
{
size_t pos = breakableStack_.popCopy();
size_t id = breakableStack_.popCopy();
if (!switchBlock)
return true;
MTableSwitch* mir = switchBlock->lastIns()->toTableSwitch();
@ -1155,25 +1159,29 @@ class FunctionCompiler
curBlock_->end(MGoto::New(alloc(), next));
curBlock_ = next;
}
return bindUnlabeledBreaks(pos);
return bindUnlabeledBreaks(id);
}
// Provides unique identifiers for internal uses in the control flow stacks;
// these ids have to grow monotonically.
unsigned nextId() { return nextId_++; }
/************************************************************ DECODING ***/
uint8_t readU8() { return func_.uncheckedReadU8(&pc_); }
uint32_t readU32() { return func_.uncheckedReadU32(&pc_); }
int32_t readI32() { return func_.uncheckedReadI32(&pc_); }
float readF32() { return func_.uncheckedReadF32(&pc_); }
double readF64() { return func_.uncheckedReadF64(&pc_); }
const LifoSig* readSig() { return func_.uncheckedReadSig(&pc_); }
SimdConstant readI32X4() { return func_.uncheckedReadI32X4(&pc_); }
SimdConstant readF32X4() { return func_.uncheckedReadF32X4(&pc_); }
uint8_t readU8() { return decoder_.uncheckedReadU8(); }
uint32_t readU32() { return decoder_.uncheckedReadU32(); }
int32_t readI32() { return decoder_.uncheckedReadI32(); }
float readF32() { return decoder_.uncheckedReadF32(); }
double readF64() { return decoder_.uncheckedReadF64(); }
const LifoSig* readSig() { return decoder_.uncheckedReadSig(); }
SimdConstant readI32X4() { return decoder_.uncheckedReadI32X4(); }
SimdConstant readF32X4() { return decoder_.uncheckedReadF32X4(); }
Stmt readStmtOp() { return Stmt(readU8()); }
void readCallLineCol(uint32_t* line, uint32_t* column) {
const FuncIR::SourceCoords& sc = func_.sourceCoords(lastReadCallSite_++);
MOZ_ASSERT(pc_ == sc.offset);
const SourceCoords& sc = func_.sourceCoords(lastReadCallSite_++);
decoder_.assertCurrentIs(sc.offset);
*line = sc.line;
*column = sc.column;
}
@ -1182,8 +1190,7 @@ class FunctionCompiler
MOZ_ASSERT(Stmt(readU8()) == Stmt::DebugCheckPoint);
}
bool done() const { return pc_ == func_.size(); }
size_t pc() const { return pc_; }
bool done() const { return decoder_.done(); }
/*************************************************************************/
private:
@ -1266,10 +1273,10 @@ class FunctionCompiler
return true;
}
bool bindUnlabeledBreaks(size_t pos)
bool bindUnlabeledBreaks(size_t id)
{
bool createdJoinBlock = false;
if (UnlabeledBlockMap::Ptr p = unlabeledBreaks_.lookup(pos)) {
if (UnlabeledBlockMap::Ptr p = unlabeledBreaks_.lookup(id)) {
if (!bindBreaksOrContinues(&p->value(), &createdJoinBlock))
return false;
unlabeledBreaks_.remove(p);
@ -2287,10 +2294,10 @@ EmitInterruptCheckLoop(FunctionCompiler& f)
static bool
EmitWhile(FunctionCompiler& f, const LabelVector* maybeLabels)
{
size_t headPc = f.pc();
size_t headId = f.nextId();
MBasicBlock* loopEntry;
if (!f.startPendingLoop(headPc, &loopEntry))
if (!f.startPendingLoop(headId, &loopEntry))
return false;
MDefinition* condDef;
@ -2304,7 +2311,7 @@ EmitWhile(FunctionCompiler& f, const LabelVector* maybeLabels)
if (!EmitStatement(f))
return false;
if (!f.bindContinues(headPc, maybeLabels))
if (!f.bindContinues(headId, maybeLabels))
return false;
return f.closeLoop(loopEntry, afterLoop);
@ -2315,7 +2322,7 @@ EmitFor(FunctionCompiler& f, Stmt stmt, const LabelVector* maybeLabels)
{
MOZ_ASSERT(stmt == Stmt::ForInitInc || stmt == Stmt::ForInitNoInc ||
stmt == Stmt::ForNoInitInc || stmt == Stmt::ForNoInitNoInc);
size_t headPc = f.pc();
size_t headId = f.nextId();
if (stmt == Stmt::ForInitInc || stmt == Stmt::ForInitNoInc) {
if (!EmitStatement(f))
@ -2323,7 +2330,7 @@ EmitFor(FunctionCompiler& f, Stmt stmt, const LabelVector* maybeLabels)
}
MBasicBlock* loopEntry;
if (!f.startPendingLoop(headPc, &loopEntry))
if (!f.startPendingLoop(headId, &loopEntry))
return false;
MDefinition* condDef;
@ -2337,7 +2344,7 @@ EmitFor(FunctionCompiler& f, Stmt stmt, const LabelVector* maybeLabels)
if (!EmitStatement(f))
return false;
if (!f.bindContinues(headPc, maybeLabels))
if (!f.bindContinues(headId, maybeLabels))
return false;
if (stmt == Stmt::ForInitInc || stmt == Stmt::ForNoInitInc) {
@ -2353,16 +2360,16 @@ EmitFor(FunctionCompiler& f, Stmt stmt, const LabelVector* maybeLabels)
static bool
EmitDoWhile(FunctionCompiler& f, const LabelVector* maybeLabels)
{
size_t headPc = f.pc();
size_t headId = f.nextId();
MBasicBlock* loopEntry;
if (!f.startPendingLoop(headPc, &loopEntry))
if (!f.startPendingLoop(headId, &loopEntry))
return false;
if (!EmitStatement(f))
return false;
if (!f.bindContinues(headPc, maybeLabels))
if (!f.bindContinues(headId, maybeLabels))
return false;
MDefinition* condDef;
@ -2465,7 +2472,7 @@ EmitSwitch(FunctionCompiler& f)
return false;
MBasicBlock* switchBlock;
if (!f.startSwitch(f.pc(), exprDef, low, high, &switchBlock))
if (!f.startSwitch(f.nextId(), exprDef, low, high, &switchBlock))
return false;
while (numCases--) {
@ -3040,7 +3047,7 @@ wasm::IonCompileFunction(IonCompileTask* task)
{
int64_t before = PRMJ_Now();
const FuncIR& func = task->func();
const FuncBytecode& func = task->func();
FuncCompileResults& results = task->results();
JitContext jitContext(CompileRuntime::get(task->runtime()), &results.alloc());

Просмотреть файл

@ -19,7 +19,7 @@
#ifndef wasm_ion_compile_h
#define wasm_ion_compile_h
#include "asmjs/WasmIR.h"
#include "asmjs/WasmBinary.h"
#include "jit/MacroAssembler.h"
namespace js {
@ -63,7 +63,7 @@ class IonCompileTask
JSRuntime* const runtime_;
const CompileArgs args_;
LifoAlloc lifo_;
const FuncIR* func_;
UniqueFuncBytecode func_;
mozilla::Maybe<FuncCompileResults> results_;
IonCompileTask(const IonCompileTask&) = delete;
@ -85,19 +85,22 @@ class IonCompileTask
CompileArgs args() const {
return args_;
}
void init(const FuncIR& func) {
func_ = &func;
void init(UniqueFuncBytecode func) {
MOZ_ASSERT(!func_);
func_ = mozilla::Move(func);
results_.emplace(lifo_);
}
const FuncIR& func() const {
const FuncBytecode& func() const {
MOZ_ASSERT(func_);
return *func_;
}
FuncCompileResults& results() {
return *results_;
}
void reset() {
func_ = nullptr;
void reset(UniqueBytecode* recycled) {
if (func_)
*recycled = func_->recycleBytecode();
func_.reset(nullptr);
results_.reset();
lifo_.releaseAll();
}

Просмотреть файл

@ -76,6 +76,7 @@ wasm::AllocateCode(ExclusiveContext* cx, size_t bytes)
void
CodeDeleter::operator()(uint8_t* p)
{
MOZ_ASSERT(bytes_ != 0);
DeallocateExecutableMemory(p, bytes_, AsmJSPageSize);
}
@ -462,6 +463,13 @@ CacheableUniquePtr<CharT>::clone(JSContext* cx, CacheableUniquePtr* out) const
return true;
}
template <class CharT>
size_t
CacheableUniquePtr<CharT>::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this->get());
}
namespace js {
namespace wasm {
template struct CacheableUniquePtr<char>;
@ -469,24 +477,90 @@ template struct CacheableUniquePtr<char16_t>;
}
}
class Module::AutoMutateCode
size_t
ModuleData::serializedSize() const
{
AutoWritableJitCode awjc_;
AutoFlushICache afc_;
return sizeof(pod()) +
codeBytes +
SerializedVectorSize(imports) +
SerializedVectorSize(exports) +
SerializedPodVectorSize(heapAccesses) +
SerializedPodVectorSize(codeRanges) +
SerializedPodVectorSize(callSites) +
SerializedVectorSize(funcNames) +
filename.serializedSize() +
displayURL.serializedSize();
}
public:
AutoMutateCode(JSContext* cx, Module& module, const char* name)
: awjc_(cx->runtime(), module.code(), module.pod.codeBytes_),
afc_(name)
{
AutoFlushICache::setRange(uintptr_t(module.code()), module.pod.codeBytes_);
}
};
uint32_t
Module::totalBytes() const
uint8_t*
ModuleData::serialize(uint8_t* cursor) const
{
return pod.codeBytes_ + pod.globalBytes_;
cursor = WriteBytes(cursor, &pod(), sizeof(pod()));
cursor = WriteBytes(cursor, code.get(), codeBytes);
cursor = SerializeVector(cursor, imports);
cursor = SerializeVector(cursor, exports);
cursor = SerializePodVector(cursor, heapAccesses);
cursor = SerializePodVector(cursor, codeRanges);
cursor = SerializePodVector(cursor, callSites);
cursor = SerializeVector(cursor, funcNames);
cursor = filename.serialize(cursor);
cursor = displayURL.serialize(cursor);
return cursor;
}
/* static */ const uint8_t*
ModuleData::deserialize(ExclusiveContext* cx, const uint8_t* cursor)
{
cursor = ReadBytes(cursor, &pod(), sizeof(pod()));
code = AllocateCode(cx, totalBytes());
if (!code)
return nullptr;
cursor = ReadBytes(cursor, code.get(), codeBytes);
(cursor = DeserializeVector(cx, cursor, &imports)) &&
(cursor = DeserializeVector(cx, cursor, &exports)) &&
(cursor = DeserializePodVector(cx, cursor, &heapAccesses)) &&
(cursor = DeserializePodVector(cx, cursor, &codeRanges)) &&
(cursor = DeserializePodVector(cx, cursor, &callSites)) &&
(cursor = DeserializeVector(cx, cursor, &funcNames)) &&
(cursor = filename.deserialize(cx, cursor)) &&
(cursor = displayURL.deserialize(cx, cursor));
return cursor;
}
bool
ModuleData::clone(JSContext* cx, ModuleData* out) const
{
out->pod() = pod();
out->code = AllocateCode(cx, totalBytes());
if (!out->code)
return false;
memcpy(out->code.get(), code.get(), codeBytes);
return CloneVector(cx, imports, &out->imports) &&
CloneVector(cx, exports, &out->exports) &&
ClonePodVector(cx, heapAccesses, &out->heapAccesses) &&
ClonePodVector(cx, codeRanges, &out->codeRanges) &&
ClonePodVector(cx, callSites, &out->callSites) &&
CloneVector(cx, funcNames, &out->funcNames) &&
filename.clone(cx, &out->filename) &&
displayURL.clone(cx, &out->displayURL);
}
size_t
ModuleData::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
// Module::addSizeOfMisc takes care of code and global memory.
return SizeOfVectorExcludingThis(imports, mallocSizeOf) +
SizeOfVectorExcludingThis(exports, mallocSizeOf) +
heapAccesses.sizeOfExcludingThis(mallocSizeOf) +
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
callSites.sizeOfExcludingThis(mallocSizeOf) +
funcNames.sizeOfExcludingThis(mallocSizeOf) +
filename.sizeOfExcludingThis(mallocSizeOf) +
displayURL.sizeOfExcludingThis(mallocSizeOf);
}
uint8_t*
@ -524,7 +598,7 @@ Module::specializeToHeap(ArrayBufferObjectMaybeShared* heap)
// i.e. ptr > heapLength - data-type-byte-size - offset. data-type-byte-size
// and offset are already included in the addend so we
// just have to add the heap length here.
for (const HeapAccess& access : heapAccesses_) {
for (const HeapAccess& access : module_->heapAccesses) {
if (access.hasLengthCheck())
X86Encoding::AddInt32(access.patchLengthAt(code()), heapLength);
void* addr = access.patchHeapPtrImmAt(code());
@ -540,14 +614,14 @@ Module::specializeToHeap(ArrayBufferObjectMaybeShared* heap)
// checks at the right places. All accesses that have been recorded are the
// only ones that need bound checks (see also
// CodeGeneratorX64::visitAsmJS{Load,Store,CompareExchange,Exchange,AtomicBinop}Heap)
for (const HeapAccess& access : heapAccesses_) {
for (const HeapAccess& access : module_->heapAccesses) {
// See comment above for x86 codegen.
if (access.hasLengthCheck())
X86Encoding::AddInt32(access.patchLengthAt(code()), heapLength);
}
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
for (const HeapAccess& access : heapAccesses_)
for (const HeapAccess& access : module_->heapAccesses)
Assembler::UpdateBoundsCheck(heapLength, (Instruction*)(access.insnOffset() + code()));
#endif
@ -567,8 +641,8 @@ Module::despecializeFromHeap(ArrayBufferObjectMaybeShared* heap)
#if defined(JS_CODEGEN_X86)
uint32_t heapLength = heap->byteLength();
uint8_t* ptrBase = heap->dataPointerEither().unwrap(/*safe - used for value*/);
for (unsigned i = 0; i < heapAccesses_.length(); i++) {
const HeapAccess& access = heapAccesses_[i];
for (unsigned i = 0; i < module_->heapAccesses.length(); i++) {
const HeapAccess& access = module_->heapAccesses[i];
if (access.hasLengthCheck())
X86Encoding::AddInt32(access.patchLengthAt(code()), -heapLength);
void* addr = access.patchHeapPtrImmAt(code());
@ -578,8 +652,8 @@ Module::despecializeFromHeap(ArrayBufferObjectMaybeShared* heap)
}
#elif defined(JS_CODEGEN_X64)
uint32_t heapLength = heap->byteLength();
for (unsigned i = 0; i < heapAccesses_.length(); i++) {
const HeapAccess& access = heapAccesses_[i];
for (unsigned i = 0; i < module_->heapAccesses.length(); i++) {
const HeapAccess& access = module_->heapAccesses[i];
if (access.hasLengthCheck())
X86Encoding::AddInt32(access.patchLengthAt(code()), -heapLength);
}
@ -594,17 +668,17 @@ Module::sendCodeRangesToProfiler(JSContext* cx)
{
#ifdef JS_ION_PERF
if (PerfFuncEnabled()) {
for (const CodeRange& codeRange : codeRanges_) {
for (const CodeRange& codeRange : module_->codeRanges) {
if (!codeRange.isFunction())
continue;
uintptr_t start = uintptr_t(code() + codeRange.begin());
uintptr_t end = uintptr_t(code() + codeRange.end());
uintptr_t size = end - start;
const char* file = filename_.get();
const char* file = module_->filename.get();
unsigned line = codeRange.funcLineNumber();
unsigned column = 0;
const char* name = funcNames_[codeRange.funcNameIndex()].get();
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
writePerfSpewerAsmJSFunctionMap(start, size, file, line, column, name);
}
@ -612,14 +686,14 @@ Module::sendCodeRangesToProfiler(JSContext* cx)
#endif
#ifdef MOZ_VTUNE
if (IsVTuneProfilingActive()) {
for (const CodeRange& codeRange : codeRanges_) {
for (const CodeRange& codeRange : module_->codeRanges) {
if (!codeRange.isFunction())
continue;
uintptr_t start = uintptr_t(code() + codeRange.begin());
uintptr_t end = uintptr_t(code() + codeRange.end());
uintptr_t size = end - start;
const char* name = funcNames_[codeRange.funcNameIndex()].get();
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
unsigned method_id = iJIT_GetNewMethodID();
if (method_id == 0)
@ -654,16 +728,16 @@ Module::setProfilingEnabled(JSContext* cx, bool enabled)
// do it now since, once we start sampling, we'll be in a signal-handing
// context where we cannot malloc.
if (enabled) {
if (!funcLabels_.resize(funcNames_.length())) {
if (!funcLabels_.resize(module_->funcNames.length())) {
ReportOutOfMemory(cx);
return false;
}
for (const CodeRange& codeRange : codeRanges_) {
for (const CodeRange& codeRange : module_->codeRanges) {
if (!codeRange.isFunction())
continue;
unsigned lineno = codeRange.funcLineNumber();
const char* name = funcNames_[codeRange.funcNameIndex()].get();
UniqueChars label(JS_smprintf("%s (%s:%u)", name, filename_.get(), lineno));
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
UniqueChars label(JS_smprintf("%s (%s:%u)", name, module_->filename.get(), lineno));
if (!label) {
ReportOutOfMemory(cx);
return false;
@ -674,14 +748,16 @@ Module::setProfilingEnabled(JSContext* cx, bool enabled)
funcLabels_.clear();
}
// Patch callsites and returns to execute profiling prologues/epililogues.
// Patch callsites and returns to execute profiling prologues/epilogues.
{
AutoMutateCode amc(cx, *this, "Module::setProfilingEnabled");
AutoWritableJitCode awjc(cx->runtime(), code(), codeBytes());
AutoFlushICache afc("Module::setProfilingEnabled");
AutoFlushICache::setRange(uintptr_t(code()), codeBytes());
for (const CallSite& callSite : callSites_)
for (const CallSite& callSite : module_->callSites)
EnableProfilingPrologue(*this, callSite, enabled);
for (const CodeRange& codeRange : codeRanges_)
for (const CodeRange& codeRange : module_->codeRanges)
EnableProfilingEpilogue(*this, codeRange, enabled);
}
@ -709,114 +785,70 @@ Module::importToExit(const Import& import)
return *reinterpret_cast<ImportExit*>(globalData() + import.exitGlobalDataOffset());
}
/* static */ Module::CacheablePod
Module::zeroPod()
bool
Module::clone(JSContext* cx, const StaticLinkData& link, Module* out) const
{
CacheablePod pod = {0, 0, 0, HeapUsage::None, false, false, false};
return pod;
MOZ_ASSERT(dynamicallyLinked_);
// The out->module_ field was already cloned and initialized when 'out' was
// constructed. This function should clone the rest.
MOZ_ASSERT(out->module_);
out->isAsmJS_ = isAsmJS_;
out->profilingEnabled_ = profilingEnabled_;
if (!CloneVector(cx, funcLabels_, &out->funcLabels_))
return false;
#ifdef DEBUG
// Put the symbolic links back to -1 so PatchDataWithValueCheck assertions
// in Module::staticallyLink are valid.
for (auto imm : MakeEnumeratedRange(SymbolicAddress::Limit)) {
void* callee = AddressOf(imm, cx);
const StaticLinkData::OffsetVector& offsets = link.symbolicLinks[imm];
for (uint32_t offset : offsets) {
jit::Assembler::PatchDataWithValueCheck(jit::CodeLocationLabel(out->code() + offset),
jit::PatchedImmPtr((void*)-1),
jit::PatchedImmPtr(callee));
}
}
#endif
// If the copied machine code has been specialized to the heap, it must be
// unspecialized in the copy.
if (usesHeap())
out->despecializeFromHeap(heap_);
return true;
}
void
Module::init()
{
staticallyLinked_ = false;
interrupt_ = nullptr;
outOfBounds_ = nullptr;
dynamicallyLinked_ = false;
Module::Module(UniqueModuleData module, AsmJSBool isAsmJS)
: module_(Move(module)),
isAsmJS_(bool(isAsmJS)),
staticallyLinked_(false),
interrupt_(nullptr),
outOfBounds_(nullptr),
dynamicallyLinked_(false),
profilingEnabled_(false)
{
*(double*)(globalData() + NaN64GlobalDataOffset) = GenericNaN();
*(float*)(globalData() + NaN32GlobalDataOffset) = GenericNaN();
}
// Private constructor used for deserialization and cloning.
Module::Module(const CacheablePod& pod,
UniqueCodePtr code,
ImportVector&& imports,
ExportVector&& exports,
HeapAccessVector&& heapAccesses,
CodeRangeVector&& codeRanges,
CallSiteVector&& callSites,
CacheableCharsVector&& funcNames,
CacheableChars filename,
CacheableTwoByteChars displayURL,
CacheBool loadedFromCache,
ProfilingBool profilingEnabled,
FuncLabelVector&& funcLabels)
: pod(pod),
code_(Move(code)),
imports_(Move(imports)),
exports_(Move(exports)),
heapAccesses_(Move(heapAccesses)),
codeRanges_(Move(codeRanges)),
callSites_(Move(callSites)),
funcNames_(Move(funcNames)),
filename_(Move(filename)),
displayURL_(Move(displayURL)),
loadedFromCache_(loadedFromCache),
profilingEnabled_(profilingEnabled),
funcLabels_(Move(funcLabels))
{
MOZ_ASSERT_IF(!profilingEnabled, funcLabels_.empty());
MOZ_ASSERT_IF(profilingEnabled, funcNames_.length() == funcLabels_.length());
init();
}
// Public constructor for compilation.
Module::Module(CompileArgs args,
uint32_t functionBytes,
uint32_t codeBytes,
uint32_t globalBytes,
HeapUsage heapUsage,
MutedBool mutedErrors,
UniqueCodePtr code,
ImportVector&& imports,
ExportVector&& exports,
HeapAccessVector&& heapAccesses,
CodeRangeVector&& codeRanges,
CallSiteVector&& callSites,
CacheableCharsVector&& funcNames,
CacheableChars filename,
CacheableTwoByteChars displayURL)
: pod(zeroPod()),
code_(Move(code)),
imports_(Move(imports)),
exports_(Move(exports)),
heapAccesses_(Move(heapAccesses)),
codeRanges_(Move(codeRanges)),
callSites_(Move(callSites)),
funcNames_(Move(funcNames)),
filename_(Move(filename)),
displayURL_(Move(displayURL)),
loadedFromCache_(false),
profilingEnabled_(false)
{
// Work around MSVC 2013 bug around {} member initialization.
const_cast<uint32_t&>(pod.functionBytes_) = functionBytes;
const_cast<uint32_t&>(pod.codeBytes_) = codeBytes;
const_cast<uint32_t&>(pod.globalBytes_) = globalBytes;
const_cast<HeapUsage&>(pod.heapUsage_) = heapUsage;
const_cast<bool&>(pod.mutedErrors_) = bool(mutedErrors);
const_cast<bool&>(pod.usesSignalHandlersForOOB_) = args.useSignalHandlersForOOB;
const_cast<bool&>(pod.usesSignalHandlersForInterrupt_) = args.useSignalHandlersForInterrupt;
init();
}
Module::~Module()
{
if (code_) {
for (unsigned i = 0; i < imports_.length(); i++) {
ImportExit& exit = importToExit(imports_[i]);
if (exit.baselineScript)
exit.baselineScript->removeDependentWasmModule(*this, i);
}
for (unsigned i = 0; i < imports().length(); i++) {
ImportExit& exit = importToExit(imports()[i]);
if (exit.baselineScript)
exit.baselineScript->removeDependentWasmModule(*this, i);
}
}
void
Module::trace(JSTracer* trc)
{
for (const Import& import : imports_) {
for (const Import& import : imports()) {
if (importToExit(import).fun)
TraceEdge(trc, &importToExit(import).fun, "wasm function import");
}
@ -825,25 +857,16 @@ Module::trace(JSTracer* trc)
TraceEdge(trc, &heap_, "wasm buffer");
}
CompileArgs
Module::compileArgs() const
{
CompileArgs args;
args.useSignalHandlersForOOB = pod.usesSignalHandlersForOOB_;
args.useSignalHandlersForInterrupt = pod.usesSignalHandlersForInterrupt_;
return args;
}
bool
Module::containsFunctionPC(void* pc) const
{
return pc >= code() && pc < (code() + pod.functionBytes_);
return pc >= code() && pc < (code() + module_->functionBytes);
}
bool
Module::containsCodePC(void* pc) const
{
return pc >= code() && pc < (code() + pod.codeBytes_);
return pc >= code() && pc < (code() + codeBytes());
}
struct CallSiteRetAddrOffset
@ -860,13 +883,13 @@ Module::lookupCallSite(void* returnAddress) const
{
uint32_t target = ((uint8_t*)returnAddress) - code();
size_t lowerBound = 0;
size_t upperBound = callSites_.length();
size_t upperBound = module_->callSites.length();
size_t match;
if (!BinarySearch(CallSiteRetAddrOffset(callSites_), lowerBound, upperBound, target, &match))
if (!BinarySearch(CallSiteRetAddrOffset(module_->callSites), lowerBound, upperBound, target, &match))
return nullptr;
return &callSites_[match];
return &module_->callSites[match];
}
const CodeRange*
@ -874,13 +897,13 @@ Module::lookupCodeRange(void* pc) const
{
CodeRange::PC target((uint8_t*)pc - code());
size_t lowerBound = 0;
size_t upperBound = codeRanges_.length();
size_t upperBound = module_->codeRanges.length();
size_t match;
if (!BinarySearch(codeRanges_, lowerBound, upperBound, target, &match))
if (!BinarySearch(module_->codeRanges, lowerBound, upperBound, target, &match))
return nullptr;
return &codeRanges_[match];
return &module_->codeRanges[match];
}
struct HeapAccessOffset
@ -899,13 +922,13 @@ Module::lookupHeapAccess(void* pc) const
uint32_t target = ((uint8_t*)pc) - code();
size_t lowerBound = 0;
size_t upperBound = heapAccesses_.length();
size_t upperBound = module_->heapAccesses.length();
size_t match;
if (!BinarySearch(HeapAccessOffset(heapAccesses_), lowerBound, upperBound, target, &match))
if (!BinarySearch(HeapAccessOffset(module_->heapAccesses), lowerBound, upperBound, target, &match))
return nullptr;
return &heapAccesses_[match];
return &module_->heapAccesses[match];
}
bool
@ -920,7 +943,7 @@ Module::staticallyLink(ExclusiveContext* cx, const StaticLinkData& linkData)
JitContext jcx(CompileRuntime::get(cx->compartment()->runtimeFromAnyThread()));
MOZ_ASSERT(IsCompilingAsmJS());
AutoFlushICache afc("Module::staticallyLink", /* inhibit = */ true);
AutoFlushICache::setRange(uintptr_t(code()), pod.codeBytes_);
AutoFlushICache::setRange(uintptr_t(code()), codeBytes());
interrupt_ = code() + linkData.pod.interruptOffset;
outOfBounds_ = code() + linkData.pod.outOfBoundsOffset;
@ -983,7 +1006,7 @@ Module::staticallyLink(ExclusiveContext* cx, const StaticLinkData& linkData)
bool
Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> heap,
const AutoVectorRooter<JSFunction*>& imports)
const AutoVectorRooter<JSFunction*>& importArgs)
{
MOZ_ASSERT(staticallyLinked_);
MOZ_ASSERT(!dynamicallyLinked_);
@ -994,15 +1017,15 @@ Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> hea
JitContext jcx(CompileRuntime::get(cx->compartment()->runtimeFromAnyThread()));
MOZ_ASSERT(IsCompilingAsmJS());
AutoFlushICache afc("Module::dynamicallyLink");
AutoFlushICache::setRange(uintptr_t(code()), pod.codeBytes_);
AutoFlushICache::setRange(uintptr_t(code()), codeBytes());
// Initialize imports with actual imported values.
MOZ_ASSERT(imports.length() == imports_.length());
for (size_t i = 0; i < imports_.length(); i++) {
const Import& import = imports_[i];
MOZ_ASSERT(importArgs.length() == imports().length());
for (size_t i = 0; i < imports().length(); i++) {
const Import& import = imports()[i];
ImportExit& exit = importToExit(import);
exit.code = code() + import.interpExitCodeOffset();
exit.fun = imports[i];
exit.fun = importArgs[i];
exit.baselineScript = nullptr;
}
@ -1011,7 +1034,7 @@ Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> hea
specializeToHeap(heap);
// See AllocateCode comment above.
if (!ExecutableAllocator::makeExecutable(code(), pod.codeBytes_)) {
if (!ExecutableAllocator::makeExecutable(code(), codeBytes())) {
ReportOutOfMemory(cx);
return false;
}
@ -1043,7 +1066,7 @@ void
Module::deoptimizeImportExit(uint32_t importIndex)
{
MOZ_ASSERT(dynamicallyLinked_);
const Import& import = imports_[importIndex];
const Import& import = imports()[importIndex];
ImportExit& exit = importToExit(import);
exit.code = code() + import.interpExitCodeOffset();
exit.baselineScript = nullptr;
@ -1054,7 +1077,7 @@ Module::callExport(JSContext* cx, uint32_t exportIndex, CallArgs args)
{
MOZ_ASSERT(dynamicallyLinked_);
const Export& exp = exports_[exportIndex];
const Export& exp = exports()[exportIndex];
// Enable/disable profiling in the Module to match the current global
// profiling state. Don't do this if the Module is already active on the
@ -1190,7 +1213,7 @@ Module::callImport(JSContext* cx, uint32_t importIndex, unsigned argc, const Val
{
MOZ_ASSERT(dynamicallyLinked_);
const Import& import = imports_[importIndex];
const Import& import = imports()[importIndex];
RootedValue fval(cx, ObjectValue(*importToExit(import).fun));
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, rval))
@ -1264,211 +1287,93 @@ Module::profilingLabel(uint32_t funcIndex) const
return funcLabels_[funcIndex].get();
}
size_t
Module::serializedSize() const
void
Module::addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data)
{
return sizeof(pod) +
pod.codeBytes_ +
SerializedVectorSize(imports_) +
SerializedVectorSize(exports_) +
SerializedPodVectorSize(heapAccesses_) +
SerializedPodVectorSize(codeRanges_) +
SerializedPodVectorSize(callSites_) +
SerializedVectorSize(funcNames_) +
filename_.serializedSize() +
displayURL_.serializedSize();
*code += codeBytes();
*data += mallocSizeOf(this) +
globalBytes() +
mallocSizeOf(module_.get()) +
module_->sizeOfExcludingThis(mallocSizeOf) +
funcPtrTables_.sizeOfExcludingThis(mallocSizeOf) +
SizeOfVectorExcludingThis(funcLabels_, mallocSizeOf);
}
uint8_t*
Module::serialize(uint8_t* cursor) const
{
MOZ_ASSERT(!profilingEnabled_, "assumed by Module::deserialize");
const Class WasmModuleObject::class_ = {
"WasmModuleObject",
JSCLASS_IS_ANONYMOUS | JSCLASS_DELAY_METADATA_CALLBACK |
JSCLASS_HAS_RESERVED_SLOTS(WasmModuleObject::RESERVED_SLOTS),
nullptr, /* addProperty */
nullptr, /* delProperty */
nullptr, /* getProperty */
nullptr, /* setProperty */
nullptr, /* enumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
WasmModuleObject::finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
WasmModuleObject::trace
};
cursor = WriteBytes(cursor, &pod, sizeof(pod));
cursor = WriteBytes(cursor, code(), pod.codeBytes_);
cursor = SerializeVector(cursor, imports_);
cursor = SerializeVector(cursor, exports_);
cursor = SerializePodVector(cursor, heapAccesses_);
cursor = SerializePodVector(cursor, codeRanges_);
cursor = SerializePodVector(cursor, callSites_);
cursor = SerializeVector(cursor, funcNames_);
cursor = filename_.serialize(cursor);
cursor = displayURL_.serialize(cursor);
return cursor;
bool
WasmModuleObject::hasModule() const
{
MOZ_ASSERT(is<WasmModuleObject>());
return !getReservedSlot(MODULE_SLOT).isUndefined();
}
/* static */ const uint8_t*
Module::deserialize(ExclusiveContext* cx, const uint8_t* cursor, UniqueModule* out)
/* static */ void
WasmModuleObject::finalize(FreeOp* fop, JSObject* obj)
{
CacheablePod pod = zeroPod();
cursor = ReadBytes(cursor, &pod, sizeof(pod));
if (!cursor)
return nullptr;
UniqueCodePtr code = AllocateCode(cx, pod.codeBytes_ + pod.globalBytes_);
if (!code)
return nullptr;
cursor = ReadBytes(cursor, code.get(), pod.codeBytes_);
ImportVector imports;
cursor = DeserializeVector(cx, cursor, &imports);
if (!cursor)
return nullptr;
ExportVector exports;
cursor = DeserializeVector(cx, cursor, &exports);
if (!cursor)
return nullptr;
HeapAccessVector heapAccesses;
cursor = DeserializePodVector(cx, cursor, &heapAccesses);
if (!cursor)
return nullptr;
CodeRangeVector codeRanges;
cursor = DeserializePodVector(cx, cursor, &codeRanges);
if (!cursor)
return nullptr;
CallSiteVector callSites;
cursor = DeserializePodVector(cx, cursor, &callSites);
if (!cursor)
return nullptr;
CacheableCharsVector funcNames;
cursor = DeserializeVector(cx, cursor, &funcNames);
if (!cursor)
return nullptr;
CacheableChars filename;
cursor = filename.deserialize(cx, cursor);
if (!cursor)
return nullptr;
CacheableTwoByteChars displayURL;
cursor = displayURL.deserialize(cx, cursor);
if (!cursor)
return nullptr;
*out = cx->make_unique<Module>(pod,
Move(code),
Move(imports),
Move(exports),
Move(heapAccesses),
Move(codeRanges),
Move(callSites),
Move(funcNames),
Move(filename),
Move(displayURL),
Module::LoadedFromCache,
Module::ProfilingDisabled,
FuncLabelVector());
return cursor;
WasmModuleObject& moduleObj = obj->as<WasmModuleObject>();
if (moduleObj.hasModule())
fop->delete_(&moduleObj.module());
}
Module::UniqueModule
Module::clone(JSContext* cx, const StaticLinkData& linkData) const
/* static */ void
WasmModuleObject::trace(JSTracer* trc, JSObject* obj)
{
MOZ_ASSERT(dynamicallyLinked_);
WasmModuleObject& moduleObj = obj->as<WasmModuleObject>();
if (moduleObj.hasModule())
moduleObj.module().trace(trc);
}
UniqueCodePtr code = AllocateCode(cx, totalBytes());
if (!code)
/* static */ WasmModuleObject*
WasmModuleObject::create(ExclusiveContext* cx)
{
AutoSetNewObjectMetadata metadata(cx);
JSObject* obj = NewObjectWithGivenProto(cx, &WasmModuleObject::class_, nullptr);
if (!obj)
return nullptr;
memcpy(code.get(), this->code(), pod.codeBytes_);
return &obj->as<WasmModuleObject>();
}
#ifdef DEBUG
// Put the symbolic links back to -1 so PatchDataWithValueCheck assertions
// in Module::staticallyLink are valid.
for (auto imm : MakeEnumeratedRange(SymbolicAddress::Limit)) {
void* callee = AddressOf(imm, cx);
const StaticLinkData::OffsetVector& offsets = linkData.symbolicLinks[imm];
for (uint32_t offset : offsets) {
jit::Assembler::PatchDataWithValueCheck(jit::CodeLocationLabel(code.get() + offset),
jit::PatchedImmPtr((void*)-1),
jit::PatchedImmPtr(callee));
}
}
#endif
bool
WasmModuleObject::init(Module* module)
{
MOZ_ASSERT(is<WasmModuleObject>());
MOZ_ASSERT(!hasModule());
if (!module)
return false;
setReservedSlot(MODULE_SLOT, PrivateValue(module));
return true;
}
ImportVector imports;
if (!CloneVector(cx, imports_, &imports))
return nullptr;
ExportVector exports;
if (!CloneVector(cx, exports_, &exports))
return nullptr;
HeapAccessVector heapAccesses;
if (!ClonePodVector(cx, heapAccesses_, &heapAccesses))
return nullptr;
CodeRangeVector codeRanges;
if (!ClonePodVector(cx, codeRanges_, &codeRanges))
return nullptr;
CallSiteVector callSites;
if (!ClonePodVector(cx, callSites_, &callSites))
return nullptr;
CacheableCharsVector funcNames;
if (!CloneVector(cx, funcNames_, &funcNames))
return nullptr;
CacheableChars filename;
if (!filename_.clone(cx, &filename))
return nullptr;
CacheableTwoByteChars displayURL;
if (!displayURL_.clone(cx, &displayURL))
return nullptr;
FuncLabelVector funcLabels;
if (!CloneVector(cx, funcLabels_, &funcLabels))
return nullptr;
// Must not GC between Module allocation and (successful) return.
auto out = cx->make_unique<Module>(pod,
Move(code),
Move(imports),
Move(exports),
Move(heapAccesses),
Move(codeRanges),
Move(callSites),
Move(funcNames),
Move(filename),
Move(displayURL),
CacheBool::NotLoadedFromCache,
ProfilingBool(profilingEnabled_),
Move(funcLabels));
if (!out)
return nullptr;
// If the copied machine code has been specialized to the heap, it must be
// unspecialized in the copy.
if (usesHeap())
out->despecializeFromHeap(heap_);
if (!out->staticallyLink(cx, linkData))
return nullptr;
return Move(out);
Module&
WasmModuleObject::module() const
{
MOZ_ASSERT(is<WasmModuleObject>());
MOZ_ASSERT(hasModule());
return *(Module*)getReservedSlot(MODULE_SLOT).toPrivate();
}
void
Module::addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* asmJSModuleCode, size_t* asmJSModuleData)
WasmModuleObject::addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data)
{
*asmJSModuleCode += pod.codeBytes_;
*asmJSModuleData += mallocSizeOf(this) +
pod.globalBytes_ +
SizeOfVectorExcludingThis(imports_, mallocSizeOf) +
SizeOfVectorExcludingThis(exports_, mallocSizeOf) +
heapAccesses_.sizeOfExcludingThis(mallocSizeOf) +
codeRanges_.sizeOfExcludingThis(mallocSizeOf) +
callSites_.sizeOfExcludingThis(mallocSizeOf) +
funcNames_.sizeOfExcludingThis(mallocSizeOf) +
funcPtrTables_.sizeOfExcludingThis(mallocSizeOf);
if (hasModule())
module().addSizeOfMisc(mallocSizeOf, code, data);
}

Просмотреть файл

@ -25,6 +25,7 @@
namespace js {
class AsmJSModule;
class WasmActivation;
namespace jit { struct BaselineScript; }
@ -34,8 +35,7 @@ namespace wasm {
// deserialization and cloning. Some data can be simply copied as raw bytes and,
// as a convention, is stored in an inline CacheablePod struct. Everything else
// should implement the below methods which are called recusively by the
// containing Module. The implementation of all these methods are grouped
// together in WasmSerialize.cpp.
// containing Module. See comments for these methods in wasm::Module.
#define WASM_DECLARE_SERIALIZABLE(Type) \
size_t serializedSize() const; \
@ -103,16 +103,14 @@ class Export
{
MallocSig sig_;
struct CacheablePod {
uint32_t funcIndex_;
uint32_t stubOffset_;
} pod;
public:
Export() = default;
Export(MallocSig&& sig, uint32_t funcIndex)
explicit Export(MallocSig&& sig)
: sig_(Move(sig))
{
pod.funcIndex_ = funcIndex;
pod.stubOffset_ = UINT32_MAX;
}
Export(Export&& rhs)
@ -125,9 +123,6 @@ class Export
pod.stubOffset_ = stubOffset;
}
uint32_t funcIndex() const {
return pod.funcIndex_;
}
uint32_t stubOffset() const {
return pod.stubOffset_;
}
@ -317,6 +312,7 @@ class CodeDeleter
{
uint32_t bytes_;
public:
CodeDeleter() : bytes_(0) {}
explicit CodeDeleter(uint32_t bytes) : bytes_(bytes) {}
void operator()(uint8_t* p);
};
@ -341,6 +337,55 @@ UsesHeap(HeapUsage heapUsage)
return bool(heapUsage);
}
// See mutedErrors comment in jsapi.h.
enum class MutedErrorsBool
{
DontMuteErrors = false,
MuteErrors = true
};
// ModuleCacheablePod holds the trivially-memcpy()able serializable portion of
// ModuleData.
struct ModuleCacheablePod
{
uint32_t functionBytes;
uint32_t codeBytes;
uint32_t globalBytes;
HeapUsage heapUsage;
MutedErrorsBool mutedErrors;
CompileArgs compileArgs;
uint32_t totalBytes() const { return codeBytes + globalBytes; }
};
// ModuleData holds the guts of a Module. ModuleData is mutably built up by
// ModuleGenerator and then handed over to the Module constructor in finish(),
// where it is stored immutably.
struct ModuleData : ModuleCacheablePod
{
ModuleData() : loadedFromCache(false) { mozilla::PodZero(&pod()); }
ModuleCacheablePod& pod() { return *this; }
const ModuleCacheablePod& pod() const { return *this; }
UniqueCodePtr code;
ImportVector imports;
ExportVector exports;
HeapAccessVector heapAccesses;
CodeRangeVector codeRanges;
CallSiteVector callSites;
CacheableCharsVector funcNames;
CacheableChars filename;
CacheableTwoByteChars displayURL;
bool loadedFromCache;
WASM_DECLARE_SERIALIZABLE(ModuleData);
};
typedef UniquePtr<ModuleData, JS::DeletePolicy<ModuleData>> UniqueModuleData;
// Module represents a compiled WebAssembly module which lives until the last
// reference to any exported functions is dropped. Modules must be wrapped by a
// rooted JSObject immediately after creation so that Module::trace() is called
@ -363,6 +408,7 @@ UsesHeap(HeapUsage heapUsage)
class Module
{
typedef UniquePtr<const ModuleData, JS::DeletePolicy<const ModuleData>> UniqueConstModuleData;
struct ImportExit {
void* code;
jit::BaselineScript* baselineScript;
@ -387,25 +433,8 @@ class Module
typedef RelocatablePtrArrayBufferObjectMaybeShared BufferPtr;
// Initialized when constructed:
struct CacheablePod {
const uint32_t functionBytes_;
const uint32_t codeBytes_;
const uint32_t globalBytes_;
const HeapUsage heapUsage_;
const bool mutedErrors_;
const bool usesSignalHandlersForOOB_;
const bool usesSignalHandlersForInterrupt_;
} pod;
const UniqueCodePtr code_;
const ImportVector imports_;
const ExportVector exports_;
const HeapAccessVector heapAccesses_;
const CodeRangeVector codeRanges_;
const CallSiteVector callSites_;
const CacheableCharsVector funcNames_;
const CacheableChars filename_;
const CacheableTwoByteChars displayURL_;
const bool loadedFromCache_;
const UniqueConstModuleData module_;
bool isAsmJS_;
// Initialized during staticallyLink:
bool staticallyLinked_;
@ -421,9 +450,6 @@ class Module
bool profilingEnabled_;
FuncLabelVector funcLabels_;
class AutoMutateCode;
uint32_t totalBytes() const;
uint8_t* rawHeapPtr() const;
uint8_t*& rawHeapPtr();
WasmActivation*& activation();
@ -433,70 +459,50 @@ class Module
MOZ_WARN_UNUSED_RESULT bool setProfilingEnabled(JSContext* cx, bool enabled);
ImportExit& importToExit(const Import& import);
enum CacheBool { NotLoadedFromCache = false, LoadedFromCache = true };
enum ProfilingBool { ProfilingDisabled = false, ProfilingEnabled = true };
static CacheablePod zeroPod();
void init();
Module(const CacheablePod& pod,
UniqueCodePtr code,
ImportVector&& imports,
ExportVector&& exports,
HeapAccessVector&& heapAccesses,
CodeRangeVector&& codeRanges,
CallSiteVector&& callSites,
CacheableCharsVector&& funcNames,
CacheableChars filename,
CacheableTwoByteChars displayURL,
CacheBool loadedFromCache,
ProfilingBool profilingEnabled,
FuncLabelVector&& funcLabels);
template <class> friend struct js::MallocProvider;
friend class js::WasmActivation;
protected:
enum AsmJSBool { NotAsmJS = false, IsAsmJS = true };
const ModuleData& base() const { return *module_; }
bool clone(JSContext* cx, const StaticLinkData& link, Module* clone) const;
public:
static const unsigned SizeOfImportExit = sizeof(ImportExit);
static const unsigned OffsetOfImportExitFun = offsetof(ImportExit, fun);
static const unsigned SizeOfEntryArg = sizeof(EntryArg);
enum MutedBool { DontMuteErrors = false, MuteErrors = true };
explicit Module(UniqueModuleData module, AsmJSBool = NotAsmJS);
virtual ~Module();
virtual void trace(JSTracer* trc);
virtual void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
Module(CompileArgs args,
uint32_t functionBytes,
uint32_t codeBytes,
uint32_t globalBytes,
HeapUsage heapUsage,
MutedBool mutedErrors,
UniqueCodePtr code,
ImportVector&& imports,
ExportVector&& exports,
HeapAccessVector&& heapAccesses,
CodeRangeVector&& codeRanges,
CallSiteVector&& callSites,
CacheableCharsVector&& funcNames,
CacheableChars filename,
CacheableTwoByteChars displayURL);
~Module();
void trace(JSTracer* trc);
uint8_t* code() const { return code_.get(); }
uint8_t* globalData() const { return code() + pod.codeBytes_; }
uint32_t globalBytes() const { return pod.globalBytes_; }
HeapUsage heapUsage() const { return pod.heapUsage_; }
bool usesHeap() const { return UsesHeap(pod.heapUsage_); }
bool hasSharedHeap() const { return pod.heapUsage_ == HeapUsage::Shared; }
bool mutedErrors() const { return pod.mutedErrors_; }
CompileArgs compileArgs() const;
const ImportVector& imports() const { return imports_; }
const ExportVector& exports() const { return exports_; }
const char* functionName(uint32_t i) const { return funcNames_[i].get(); }
const char* filename() const { return filename_.get(); }
const char16_t* displayURL() const { return displayURL_.get(); }
bool loadedFromCache() const { return loadedFromCache_; }
uint8_t* code() const { return module_->code.get(); }
uint32_t codeBytes() const { return module_->codeBytes; }
uint8_t* globalData() const { return code() + module_->codeBytes; }
uint32_t globalBytes() const { return module_->globalBytes; }
HeapUsage heapUsage() const { return module_->heapUsage; }
bool usesHeap() const { return UsesHeap(module_->heapUsage); }
bool hasSharedHeap() const { return module_->heapUsage == HeapUsage::Shared; }
bool mutedErrors() const { return bool(module_->mutedErrors); }
CompileArgs compileArgs() const { return module_->compileArgs; }
const ImportVector& imports() const { return module_->imports; }
const ExportVector& exports() const { return module_->exports; }
const char* functionName(uint32_t i) const { return module_->funcNames[i].get(); }
const char* filename() const { return module_->filename.get(); }
const char16_t* displayURL() const { return module_->displayURL.get(); }
bool loadedFromCache() const { return module_->loadedFromCache; }
bool staticallyLinked() const { return staticallyLinked_; }
bool dynamicallyLinked() const { return dynamicallyLinked_; }
// Some wasm::Module's have the most-derived type AsmJSModule. The
// AsmJSModule stores the extra metadata necessary to implement asm.js (JS)
// semantics. The asAsmJS() member may be used as a checked downcast when
// isAsmJS() is true.
bool isAsmJS() const { return isAsmJS_; }
AsmJSModule& asAsmJS() { MOZ_ASSERT(isAsmJS_); return *(AsmJSModule*)this; }
const AsmJSModule& asAsmJS() const { MOZ_ASSERT(isAsmJS_); return *(const AsmJSModule*)this; }
// The range [0, functionBytes) is a subrange of [0, codeBytes) that
// contains only function body code, not the stub code. This distinction is
// used by the async interrupt handler to only interrupt when the pc is in
@ -513,7 +519,7 @@ class Module
// statically-linked state. The given StaticLinkData must have come from the
// compilation of this module.
bool staticallyLink(ExclusiveContext* cx, const StaticLinkData& linkData);
bool staticallyLink(ExclusiveContext* cx, const StaticLinkData& link);
// This function transitions the module from a statically-linked state to a
// dynamically-linked state. If this module usesHeap(), a non-null heap
@ -558,19 +564,32 @@ class Module
bool profilingEnabled() const { return profilingEnabled_; }
const char* profilingLabel(uint32_t funcIndex) const;
};
// See WASM_DECLARE_SERIALIZABLE.
size_t serializedSize() const;
uint8_t* serialize(uint8_t* cursor) const;
typedef UniquePtr<Module, JS::DeletePolicy<Module>> UniqueModule;
static const uint8_t* deserialize(ExclusiveContext* cx, const uint8_t* cursor,
UniqueModule* out);
UniqueModule clone(JSContext* cx, const StaticLinkData& linkData) const;
void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* asmJSModuleCode,
size_t* asmJSModuleData);
typedef UniquePtr<Module, JS::DeletePolicy<Module>> UniqueModule;
} // namespace wasm
// An WasmModuleObject is an internal object (i.e., not exposed directly to user
// code) which traces and owns a wasm::Module. The WasmModuleObject is
// referenced by the extended slots of exported JSFunctions and serves to keep
// the wasm::Module alive until its last GC reference is dead.
class WasmModuleObject : public NativeObject
{
static const unsigned MODULE_SLOT = 0;
bool hasModule() const;
static void finalize(FreeOp* fop, JSObject* obj);
static void trace(JSTracer* trc, JSObject* obj);
public:
static const unsigned RESERVED_SLOTS = 1;
static WasmModuleObject* create(ExclusiveContext* cx);
bool init(wasm::Module* module);
wasm::Module& module() const;
void addSizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
static const Class class_;
};
} // namespace js
} // namespace wasm
#endif // wasm_module_h

Просмотреть файл

@ -262,7 +262,7 @@ GenerateEntry(ModuleGenerator& mg, unsigned exportIndex, bool usesHeap)
MOZ_CRASH("no int64 in asm.js");
case ExprType::F32:
masm.convertFloat32ToDouble(ReturnFloat32Reg, ReturnDoubleReg);
// Fall through as ReturnDoubleReg now contains a Double
MOZ_FALLTHROUGH; // as ReturnDoubleReg now contains a Double
case ExprType::F64:
masm.canonicalizeDouble(ReturnDoubleReg);
masm.storeDouble(ReturnDoubleReg, Address(argv, 0));

Просмотреть файл

@ -2448,7 +2448,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
pn = pn->pn_expr;
if (!pn->isKind(PNK_STATEMENTLIST))
return statement(pn, dst);
/* FALL THROUGH */
MOZ_FALLTHROUGH;
case PNK_STATEMENTLIST:
return blockStatement(pn, dst);

Просмотреть файл

@ -4059,7 +4059,8 @@ CType::Finalize(JSFreeOp* fop, JSObject* obj)
}
}
// Fall through.
MOZ_FALLTHROUGH;
case TYPE_array: {
// Free the ffi_type info.
slot = JS_GetReservedSlot(obj, SLOT_FFITYPE);
@ -5508,7 +5509,7 @@ PostBarrierCallback(JSTracer* trc, JSString* key, void* data)
UnbarrieredFieldInfoHash* table = reinterpret_cast<UnbarrieredFieldInfoHash*>(data);
JSString* prior = key;
JS_CallUnbarrieredStringTracer(trc, &key, "CType fieldName");
js::UnsafeTraceManuallyBarrieredEdge(trc, &key, "CType fieldName");
table->rekeyIfMoved(JS_ASSERT_STRING_IS_FLAT(prior), JS_ASSERT_STRING_IS_FLAT(key));
}

Просмотреть файл

@ -2108,6 +2108,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
// Any subexpression of a comma expression could be effectful.
case PNK_COMMA:
MOZ_ASSERT(pn->pn_count > 0);
MOZ_FALLTHROUGH;
// Subcomponents of a literal may be effectful.
case PNK_ARRAY:
case PNK_OBJECT:
@ -8802,7 +8803,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
break;
case PNK_POSHOLDER:
MOZ_ASSERT_UNREACHABLE("Should never try to emit PNK_POSHOLDER");
MOZ_FALLTHROUGH_ASSERT("Should never try to emit PNK_POSHOLDER");
default:
MOZ_ASSERT(0);

Просмотреть файл

@ -156,7 +156,7 @@ class NameResolver
* flagged as a contributor.
*/
pos--;
/* fallthrough */
MOZ_FALLTHROUGH;
default:
/* Save any other nodes we encounter on the way up. */
@ -727,8 +727,8 @@ class NameResolver
// Import/export spec lists contain import/export specs containing
// only pairs of names. Alternatively, an export spec lists may
// contain a single export batch specifier.
case PNK_IMPORT_SPEC_LIST: {
case PNK_EXPORT_SPEC_LIST:
case PNK_IMPORT_SPEC_LIST: {
MOZ_ASSERT(cur->isArity(PN_LIST));
#ifdef DEBUG
bool isImport = cur->isKind(PNK_IMPORT_SPEC_LIST);

Просмотреть файл

@ -6356,7 +6356,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
case TOK_MUL:
kind = PNK_YIELD_STAR;
tokenStream.consumeKnownToken(TOK_MUL, TokenStream::Operand);
// Fall through.
MOZ_FALLTHROUGH;
default:
exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
if (!exprNode)
@ -6388,7 +6388,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
JSMSG_BAD_ANON_GENERATOR_RETURN);
return null();
}
// Fall through.
MOZ_FALLTHROUGH;
case LegacyGenerator:
{
@ -6659,7 +6659,7 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
// check its validity for legacy generators.
if (!checkYieldNameValidity())
return null();
// Fall through.
MOZ_FALLTHROUGH;
case TOK_NAME:
{
RootedPropertyName label(context, tokenStream.currentName());
@ -9121,7 +9121,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
case TOK_YIELD:
if (!checkYieldNameValidity())
return null();
// Fall through.
MOZ_FALLTHROUGH;
case TOK_NAME:
return identifierName(yieldHandling);

Просмотреть файл

@ -414,6 +414,16 @@ JS::TraceNullableEdge(JSTracer* trc, JS::Heap<T>* thingp, const char* name)
DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name);
}
JS_PUBLIC_API(void)
JS::TraceNullableEdge(JSTracer* trc, JS::TenuredHeap<JSObject*>* thingp, const char* name)
{
MOZ_ASSERT(thingp);
if (JSObject* ptr = thingp->getPtr()) {
DispatchToTracer(trc, &ptr, name);
thingp->setPtr(ptr);
}
}
template <typename T>
void
js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
@ -421,6 +431,13 @@ js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
JS_PUBLIC_API(void)
js::UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
{
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
void
js::TraceWeakEdge(JSTracer* trc, WeakRef<T>* thingp, const char* name)
@ -441,6 +458,13 @@ js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
JS_PUBLIC_API(void)
JS::UnsafeTraceRoot(JSTracer* trc, T* thingp, const char* name)
{
js::TraceRoot(trc, thingp, name);
}
template <typename T>
void
js::TraceRoot(JSTracer* trc, ReadBarriered<T>* thingp, const char* name)
@ -506,7 +530,10 @@ FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS)
#define INSTANTIATE_PUBLIC_TRACE_FUNCTIONS(type) \
template JS_PUBLIC_API(void) JS::TraceEdge<type>(JSTracer*, JS::Heap<type>*, const char*); \
template JS_PUBLIC_API(void) JS::TraceNullableEdge<type>(JSTracer*, JS::Heap<type>*, \
const char*);
const char*); \
template JS_PUBLIC_API(void) JS::UnsafeTraceRoot<type>(JSTracer*, type*, const char*); \
template JS_PUBLIC_API(void) js::UnsafeTraceManuallyBarrieredEdge<type>(JSTracer*, type*, \
const char*);
FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS)
#undef INSTANTIATE_PUBLIC_TRACE_FUNCTIONS

Просмотреть файл

@ -105,48 +105,6 @@ JS::CallbackTracer::getTracingEdgeName(char* buffer, size_t bufferSize)
/*** Public Tracing API **************************************************************************/
JS_PUBLIC_API(void)
JS_CallUnbarrieredValueTracer(JSTracer* trc, Value* valuep, const char* name)
{
TraceManuallyBarrieredEdge(trc, valuep, name);
}
JS_PUBLIC_API(void)
JS_CallUnbarrieredIdTracer(JSTracer* trc, jsid* idp, const char* name)
{
TraceManuallyBarrieredEdge(trc, idp, name);
}
JS_PUBLIC_API(void)
JS_CallUnbarrieredObjectTracer(JSTracer* trc, JSObject** objp, const char* name)
{
TraceManuallyBarrieredEdge(trc, objp, name);
}
JS_PUBLIC_API(void)
JS_CallUnbarrieredStringTracer(JSTracer* trc, JSString** strp, const char* name)
{
TraceManuallyBarrieredEdge(trc, strp, name);
}
JS_PUBLIC_API(void)
JS_CallUnbarrieredScriptTracer(JSTracer* trc, JSScript** scriptp, const char* name)
{
TraceManuallyBarrieredEdge(trc, scriptp, name);
}
JS_PUBLIC_API(void)
JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap<JSObject*>* objp, const char* name)
{
JSObject* obj = objp->getPtr();
if (!obj)
return;
TraceManuallyBarrieredEdge(trc, &obj, name);
objp->setPtr(obj);
}
JS_PUBLIC_API(void)
JS::TraceChildren(JSTracer* trc, GCCellPtr thing)
{

Просмотреть файл

@ -3815,7 +3815,7 @@ EmitAtomLetter(RegExpCompiler* compiler,
}
case 4:
macro_assembler->CheckCharacter(chars[3], &ok);
// Fall through!
MOZ_FALLTHROUGH;
case 3:
macro_assembler->CheckCharacter(chars[0], &ok);
macro_assembler->CheckCharacter(chars[1], &ok);

Просмотреть файл

@ -1563,7 +1563,7 @@ RegExpParser<CharT>::ParseDisjunction()
Advance();
break;
}
// Fall through
MOZ_FALLTHROUGH;
case 'd': case 's': case 'w': {
widechar c = Next();
Advance(2);
@ -1605,8 +1605,8 @@ RegExpParser<CharT>::ParseDisjunction()
Advance(2);
break;
}
MOZ_FALLTHROUGH;
}
// FALLTHROUGH
case '0': {
if (unicode_) {
Advance(2);
@ -1735,7 +1735,7 @@ RegExpParser<CharT>::ParseDisjunction()
int dummy;
if (ParseIntervalQuantifier(&dummy, &dummy))
return ReportError(JSMSG_NOTHING_TO_REPEAT);
// fallthrough
MOZ_FALLTHROUGH;
}
default:
if (unicode_) {

Просмотреть файл

@ -2481,6 +2481,7 @@ BacktrackingAllocator::computeSpillWeight(LiveBundle* bundle)
case LUse::FIXED:
fixed = true;
MOZ_FALLTHROUGH;
case LUse::REGISTER:
usesTotal += 2000;
break;

Просмотреть файл

@ -1913,7 +1913,7 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo)
// Invalid assumption based on baseline code.
case Bailout_OverflowInvalidate:
outerScript->setHadOverflowBailout();
// FALL THROUGH
MOZ_FALLTHROUGH;
case Bailout_NonStringInputInvalidate:
case Bailout_DoubleOutput:
case Bailout_ObjectIdentityOrTypeGuard:

Просмотреть файл

@ -1173,6 +1173,7 @@ RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, Handle
case ICStub::GetElem_NativeSlotSymbol:
if (indirect)
continue;
MOZ_FALLTHROUGH;
case ICStub::GetElem_NativePrototypeSlotName:
case ICStub::GetElem_NativePrototypeSlotSymbol:
case ICStub::GetElem_NativePrototypeCallNativeName:

Просмотреть файл

@ -721,6 +721,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
case JSOP_MOD:
case JSOP_NEG:
type = inspector->expectedResultType(last);
break;
default:
break;
}
@ -1549,7 +1550,7 @@ IonBuilder::traverseBytecode()
MOZ_ASSERT(i == 0);
if (current->peek(-1) == popped[0])
break;
// FALL THROUGH
MOZ_FALLTHROUGH;
default:
MOZ_ASSERT(popped[i]->isImplicitlyUsed() ||
@ -1940,6 +1941,7 @@ IonBuilder::inspectOpcode(JSOp op)
return pushConstant(ObjectValue(*scope));
}
// Fall through to JSOP_BINDNAME
MOZ_FALLTHROUGH;
case JSOP_BINDNAME:
return jsop_bindname(info().getName(pc));

Просмотреть файл

@ -923,6 +923,7 @@ class JitcodeGlobalEntry
break;
case IonCache:
markedAny |= ionCacheEntry().mark<ShouldMarkProvider>(trc);
break;
case Dummy:
break;
default:
@ -941,6 +942,7 @@ class JitcodeGlobalEntry
break;
case IonCache:
ionCacheEntry().sweepChildren(rt);
break;
case Dummy:
break;
default:

Просмотреть файл

@ -1815,7 +1815,7 @@ LIRGenerator::visitToDouble(MToDouble* convert)
case MIRType_Boolean:
MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
/* FALLTHROUGH */
MOZ_FALLTHROUGH;
case MIRType_Int32:
{
@ -1871,7 +1871,7 @@ LIRGenerator::visitToFloat32(MToFloat32* convert)
case MIRType_Boolean:
MOZ_ASSERT(conversion != MToFPInstruction::NumbersOnly);
/* FALLTHROUGH */
MOZ_FALLTHROUGH;
case MIRType_Int32:
{

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше